|
|
@ -0,0 +1,636 @@
|
|
|
|
|
|
|
|
package com.wb.excel.api;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.wb.excel.api.annotation.*;
|
|
|
|
|
|
|
|
import com.wb.excel.api.converter.*;
|
|
|
|
|
|
|
|
import com.wb.excel.api.converter.Converter;
|
|
|
|
|
|
|
|
import com.wb.excel.api.enumeration.Status;
|
|
|
|
|
|
|
|
import com.wb.excel.api.exception.IllegalParameterException;
|
|
|
|
|
|
|
|
import com.wb.excel.api.exception.TemplateNotMatchException;
|
|
|
|
|
|
|
|
import com.wb.excel.api.style.*;
|
|
|
|
|
|
|
|
import com.wb.excel.api.util.ClassUtil;
|
|
|
|
|
|
|
|
import com.wb.excel.api.util.ExcelUtil;
|
|
|
|
|
|
|
|
import com.wb.excel.api.util.StringUtil;
|
|
|
|
|
|
|
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
|
|
|
|
|
|
import org.apache.poi.ss.usermodel.*;
|
|
|
|
|
|
|
|
import org.apache.poi.xssf.usermodel.*;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import javax.validation.constraints.NotNull;
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 数据表的定义。<br/>
|
|
|
|
|
|
|
|
* Created on 2014/09/19.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @author 沈振家
|
|
|
|
|
|
|
|
* @since 0.1.0
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class WSheet<T> implements Serializable, Cloneable {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 表名
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private String name;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 表头的集合
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private List<WColumn> columnList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 单元格里存放的对象
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private List<WRow> rowList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据输入的模板类打印下载模板。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public WSheet(Class<T> tClass) {
|
|
|
|
|
|
|
|
initColumns(tClass);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据模板类对DataTable添加相应的列。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return 包含@Name标记的字段Set
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private List<WColumn> initColumns(Class<?> clazz) {
|
|
|
|
|
|
|
|
//获取工作簿名称,没有则以类名为默认工作簿名称
|
|
|
|
|
|
|
|
SheetName sheetName = clazz.getAnnotation(SheetName.class);
|
|
|
|
|
|
|
|
if (sheetName != null) {
|
|
|
|
|
|
|
|
this.setName(sheetName.value());
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.setName(clazz.getName());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//是否关注父类属性
|
|
|
|
|
|
|
|
boolean parentFirst = clazz.isAnnotationPresent(ParentFirst.class) && clazz.getAnnotation(ParentFirst.class).value();
|
|
|
|
|
|
|
|
Field[] fields = ClassUtil.getFields(clazz, parentFirst);
|
|
|
|
|
|
|
|
for (Field field : fields) {
|
|
|
|
|
|
|
|
WColumn WColumn = new WColumn();
|
|
|
|
|
|
|
|
WColumn.setField(field);
|
|
|
|
|
|
|
|
if (field.isAnnotationPresent(Ignore.class) && field.getAnnotation(Ignore.class).value()) {
|
|
|
|
|
|
|
|
WColumn.setHidden(true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获取列名称
|
|
|
|
|
|
|
|
if (!field.isAnnotationPresent(ColumnName.class)) {
|
|
|
|
|
|
|
|
WColumn.setName(field.getName());
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ColumnName columnColumnName = field.getAnnotation(ColumnName.class);
|
|
|
|
|
|
|
|
WColumn.setName(columnColumnName.value());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//获取列填写说明或描述
|
|
|
|
|
|
|
|
if (field.isAnnotationPresent(ColumnDescription.class)) {
|
|
|
|
|
|
|
|
WColumn.setDescription(field.getAnnotation(ColumnDescription.class).value());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//列填写标志(是否必填)
|
|
|
|
|
|
|
|
if (field.isAnnotationPresent(NotNull.class)) {
|
|
|
|
|
|
|
|
WColumn.setRequired(true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获取列类型
|
|
|
|
|
|
|
|
if (field.isAnnotationPresent(com.wb.excel.api.annotation.Converter.class)) {
|
|
|
|
|
|
|
|
com.wb.excel.api.annotation.Converter converter = field.getAnnotation(com.wb.excel.api.annotation.Converter.class);
|
|
|
|
|
|
|
|
Class target = converter.target();
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
WColumn.setConverter((Converter) target.newInstance());
|
|
|
|
|
|
|
|
} catch (InstantiationException e) {
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (field.getType() == boolean.class || field.getType() == Boolean.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new BooleanConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == byte.class || field.getType() == Byte.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new ByteConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == char.class || field.getType() == Character.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new CharacterConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == short.class || field.getType() == Short.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new ShortConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == int.class || field.getType() == Integer.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new IntegerConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == long.class || field.getType() == Long.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new LongConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == float.class || field.getType() == Float.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new FloatConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == double.class || field.getType() == Double.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new DoubleConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == Date.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new DateConverter());
|
|
|
|
|
|
|
|
} else if (field.getType() == String.class) {
|
|
|
|
|
|
|
|
WColumn.setConverter(new StringConverter());
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
throw new RuntimeException("Can not find Converter");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
columnList.add(WColumn);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return columnList;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 此构造方法仅用于转换对象列表。<br/>
|
|
|
|
|
|
|
|
* 并不会对数据的格式和合法性进行检验。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param list 需要导出的对象列表
|
|
|
|
|
|
|
|
* @throws NoSuchMethodException
|
|
|
|
|
|
|
|
* @throws InvocationTargetException
|
|
|
|
|
|
|
|
* @throws IllegalAccessException
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public WSheet(List<T> list) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
|
|
|
|
|
|
|
if (list == null || list.size() == 0) {
|
|
|
|
|
|
|
|
throw new IllegalParameterException("不允许传入空的列表");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (list.size() > 0) {
|
|
|
|
|
|
|
|
List<WColumn> wColumns = initColumns(list.get(0).getClass());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (T t : list) {
|
|
|
|
|
|
|
|
WRow row = new WRow();
|
|
|
|
|
|
|
|
for (WColumn column : wColumns) {
|
|
|
|
|
|
|
|
if (column == null) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Field field = column.getField();
|
|
|
|
|
|
|
|
String att = StringUtil.upperFirstWord(field.getName());
|
|
|
|
|
|
|
|
Method method = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 尝试获取get方法
|
|
|
|
|
|
|
|
method = t.getClass().getMethod("get" + att);
|
|
|
|
|
|
|
|
} catch (NoSuchMethodException e) {
|
|
|
|
|
|
|
|
// 尝试获取is方法,工具生成布尔值可能是is而不是get
|
|
|
|
|
|
|
|
method = t.getClass().getMethod("is" + att);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Object value = method.invoke(t);
|
|
|
|
|
|
|
|
if (null == value) {
|
|
|
|
|
|
|
|
row.put(column.getName(), new WCell());
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
row.put(column.getName(), new WCell(column.getConverter().string(value)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.rowList.add(row);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 以Excel文件的字节数组为数据源,为自己赋值的同时,与指定的模板类进行数据校验。<br/>
|
|
|
|
|
|
|
|
* 如果匹配过程中发现了不符合的数据,会在对应的单元中添加错误信息。<br/>
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param bytes Excel文件的字节数组
|
|
|
|
|
|
|
|
* @param clazz 类型
|
|
|
|
|
|
|
|
* @throws IOException <br/>1:输入流无法转为Excel文件 - 请检查输入的 bytes 是否正确;<br/>
|
|
|
|
|
|
|
|
* 2:输入流关闭出错;<br/>
|
|
|
|
|
|
|
|
* @throws TemplateNotMatchException <br/>1:Excel文件的列数与对象类型不匹配 - 请检查Excel表与模板类是否一致;<br/>
|
|
|
|
|
|
|
|
* 2:获取枚举类型出错 - 你在模板类中标注了一个变量的值为枚举类型,但程序寻找枚举类时出错;<br/>
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public WSheet(byte[] bytes, Class<T> clazz) throws IOException, TemplateNotMatchException {
|
|
|
|
|
|
|
|
Workbook workbook = null;
|
|
|
|
|
|
|
|
InputStream is = null;
|
|
|
|
|
|
|
|
boolean flag;
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
flag = true;
|
|
|
|
|
|
|
|
is = new ByteArrayInputStream(bytes); //读取文件流
|
|
|
|
|
|
|
|
workbook = new HSSFWorkbook(is);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
flag = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
flag = true;
|
|
|
|
|
|
|
|
is = new ByteArrayInputStream(bytes); //读取文件流
|
|
|
|
|
|
|
|
workbook = new XSSFWorkbook(is);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
flag = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is != null) {
|
|
|
|
|
|
|
|
is.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag) {
|
|
|
|
|
|
|
|
throw new TemplateNotMatchException("不支持的文件类型");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//第一张Sheet表
|
|
|
|
|
|
|
|
Sheet sheet = workbook.getSheetAt(0);
|
|
|
|
|
|
|
|
//获取Sheet名称
|
|
|
|
|
|
|
|
SheetName sheetName = clazz.getAnnotation(SheetName.class);
|
|
|
|
|
|
|
|
if (sheetName != null) {//如果模板存在注解则使用注解名称
|
|
|
|
|
|
|
|
this.setName(sheetName.value());
|
|
|
|
|
|
|
|
} else {//将类名设为表名,如果类名不存在,将Excel表名设为表名
|
|
|
|
|
|
|
|
this.setName(sheet.getSheetName());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//读取表头
|
|
|
|
|
|
|
|
Row headRow = sheet.getRow(0);
|
|
|
|
|
|
|
|
//获取Excel列的总数
|
|
|
|
|
|
|
|
int columnSum = headRow.getPhysicalNumberOfCells();
|
|
|
|
|
|
|
|
//匹配列的数量。用于判断Excel是否包含所有必须列。
|
|
|
|
|
|
|
|
int columnMatchNumber = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//检查列数量
|
|
|
|
|
|
|
|
List<WColumn> list = initColumns(clazz);
|
|
|
|
|
|
|
|
if (list.size() != columnSum) {
|
|
|
|
|
|
|
|
throw new TemplateNotMatchException("与模板列数量不同。");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
|
|
|
|
|
|
WColumn wColumn = list.get(i);
|
|
|
|
|
|
|
|
Cell cell = headRow.getCell(i);
|
|
|
|
|
|
|
|
String headValue = ExcelUtil.getValue(cell);
|
|
|
|
|
|
|
|
headValue = headValue.replace("*", "");
|
|
|
|
|
|
|
|
headValue = headValue.replace(" ", "");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!wColumn.getName().equals(headValue)) {
|
|
|
|
|
|
|
|
throw new TemplateNotMatchException("第" + (i + 1) + "项,不匹配的列名," + wColumn.getName() + "和" + headValue);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int maxRowNumber = sheet.getLastRowNum(); //Excel文件的总行数
|
|
|
|
|
|
|
|
/* 逐行读取导入文件的数据 */
|
|
|
|
|
|
|
|
for (int i = 0; i < maxRowNumber; i++) {
|
|
|
|
|
|
|
|
Row inputRow = sheet.getRow(i + 1); //Excel中的一行数据,第0行为表头,所以要加1
|
|
|
|
|
|
|
|
WRow row = new WRow();
|
|
|
|
|
|
|
|
rowList.add(row);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (null != inputRow) {
|
|
|
|
|
|
|
|
for (int j = 0; j < columnList.size(); j++) {
|
|
|
|
|
|
|
|
WColumn wcolumn = columnList.get(j);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 取得当前格子的值 */
|
|
|
|
|
|
|
|
Cell excelCell = inputRow.getCell(j);
|
|
|
|
|
|
|
|
WCell WCell = new WCell();
|
|
|
|
|
|
|
|
row.put(wcolumn.getName(), WCell);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String value = "";
|
|
|
|
|
|
|
|
if (null != excelCell) {
|
|
|
|
|
|
|
|
value = ExcelUtil.getValue(excelCell);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
value = value.trim();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WCell.setValue(value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否必须项
|
|
|
|
|
|
|
|
if (wcolumn.isRequired()) {
|
|
|
|
|
|
|
|
if (value.length() == 0) {
|
|
|
|
|
|
|
|
WCell.setStatus(Status.EMPTY);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查长度是否合法
|
|
|
|
|
|
|
|
// if (wcolumn) {
|
|
|
|
|
|
|
|
// if (value.length() > lengths[j].max() || value.length() < lengths[j].min()) {
|
|
|
|
|
|
|
|
// this.setStatus(i, j, Status.LENGTH);
|
|
|
|
|
|
|
|
// cellFlag = false;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查字符是否符合正则表达式
|
|
|
|
|
|
|
|
// if (cellFlag && null != columnTypes[j] && !columnTypes[j].value().equals(DataType.STRING)) {
|
|
|
|
|
|
|
|
// if (!DataType.check(columnTypes[j].value(), WCell, value)) {
|
|
|
|
|
|
|
|
// this.setStatus(i, j, Status.FORMAT);
|
|
|
|
|
|
|
|
// cellFlag = false;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// /**
|
|
|
|
|
|
|
|
// * 能过列名取得列下标。
|
|
|
|
|
|
|
|
// *
|
|
|
|
|
|
|
|
// * @param columnName 列名
|
|
|
|
|
|
|
|
// * @return 该列对应的下标
|
|
|
|
|
|
|
|
// * @throws ColumnNameNotExistException
|
|
|
|
|
|
|
|
// */
|
|
|
|
|
|
|
|
// private int getColumnIndex(String columnName) throws ColumnNameNotExistException {
|
|
|
|
|
|
|
|
// int columnIndex = -1;
|
|
|
|
|
|
|
|
// for (int i = 0; i < this.getColumnIndex(); i++) {
|
|
|
|
|
|
|
|
// if (this.columnList.get(i).getName().equals(columnName)) {
|
|
|
|
|
|
|
|
// columnIndex = i;
|
|
|
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if (columnIndex == -1) {
|
|
|
|
|
|
|
|
// throw new ColumnNameNotExistException("不存在的列名:" + columnName);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return columnIndex;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 转换某行为一个对象
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param clazz 类型
|
|
|
|
|
|
|
|
* @param rowIndex 行号
|
|
|
|
|
|
|
|
* @return 对象
|
|
|
|
|
|
|
|
* @throws IllegalAccessException
|
|
|
|
|
|
|
|
* @throws InstantiationException
|
|
|
|
|
|
|
|
* @throws NoSuchMethodException
|
|
|
|
|
|
|
|
* @throws InvocationTargetException
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public T transferOneObject(Class<T> clazz, int rowIndex)
|
|
|
|
|
|
|
|
throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
|
|
|
|
|
|
|
|
T object = clazz.newInstance();
|
|
|
|
|
|
|
|
ParentFirst parentFirstAnnotation = clazz.getAnnotation(ParentFirst.class);
|
|
|
|
|
|
|
|
boolean parentFirst = parentFirstAnnotation != null && parentFirstAnnotation.value();
|
|
|
|
|
|
|
|
Field[] fields = ClassUtil.getFields(clazz, parentFirst);
|
|
|
|
|
|
|
|
Set<Field> set = new HashSet<>();
|
|
|
|
|
|
|
|
for (Field field : fields) {
|
|
|
|
|
|
|
|
set.add(field);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < this.columnList.size(); j++) {
|
|
|
|
|
|
|
|
WColumn wColumn = this.columnList.get(0);
|
|
|
|
|
|
|
|
if (wColumn.isHidden()) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String key = this.columnList.get(j).getName();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (WColumn column : columnList) {
|
|
|
|
|
|
|
|
Field field = column.getField();
|
|
|
|
|
|
|
|
ColumnName fieldColumnName = field.getAnnotation(ColumnName.class);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (key.equals(fieldColumnName.value())) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String att = StringUtil.upperFirstWord(field.getName());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WCell WCell = this.rowList.get(rowIndex).get(column.getName());
|
|
|
|
|
|
|
|
if (null != WCell) {
|
|
|
|
|
|
|
|
String value = WCell.getValue();
|
|
|
|
|
|
|
|
Method method = clazz.getMethod("set" + att, field.getType());
|
|
|
|
|
|
|
|
//获取转换器
|
|
|
|
|
|
|
|
Converter converter = column.getConverter();
|
|
|
|
|
|
|
|
method.invoke(object, converter.convert(value));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return object;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 将DataTable转为T型的List<br/><br/>
|
|
|
|
|
|
|
|
* 如果你试图这么做,请确保在每个字段上都加上了@Name注解<br/>
|
|
|
|
|
|
|
|
* 并确保该注解的值与DataTable中列的名字一致。<br/>
|
|
|
|
|
|
|
|
* 注解的值在这里作为唯一的标识。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return T型列表
|
|
|
|
|
|
|
|
* @see WColumn 列名称
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public List<T> transferList(Class<T> clazz) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
|
|
|
|
|
|
|
|
List<T> list = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < this.rowList.size(); i++) {
|
|
|
|
|
|
|
|
T object = transferOneObject(clazz, i);
|
|
|
|
|
|
|
|
list.add(object);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 获取表名
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return 表名
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getName() {
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 设置表名
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param name 表名
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public void setName(String name) {
|
|
|
|
|
|
|
|
this.name = name;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// public final String toCSV() {
|
|
|
|
|
|
|
|
// StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// for (WColumn WColumn : this.getWColumns()) {
|
|
|
|
|
|
|
|
// if (WColumn != null) {
|
|
|
|
|
|
|
|
// sb.append(WColumn.getName()).append(",");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// sb.append("\n");
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// for (int i = 0; i < this.getRowIndex(); i++) {
|
|
|
|
|
|
|
|
// for (int j = 0; j < this.getColumnIndex(); j++) {
|
|
|
|
|
|
|
|
// WCell WCell = this.getCell(i, j);
|
|
|
|
|
|
|
|
// if (this.columnList.get(j).getDataType().equals(DataType.STRING)
|
|
|
|
|
|
|
|
// || this.columnList.get(j).getDataType().equals(DataType.DATE)
|
|
|
|
|
|
|
|
// || this.columnList.get(j).getDataType().equals(DataType.DATETIME)) {
|
|
|
|
|
|
|
|
// sb.append("\"\t").append(WCell.getValue()).append("\",");
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// sb.append(WCell.getValue()).append(",");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// sb.append("\n");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// return sb.toString();
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 判断DataTable是否包含错误信息
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return 是否包含错误.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public final boolean hasError() {
|
|
|
|
|
|
|
|
for (WRow wRow : rowList) {
|
|
|
|
|
|
|
|
Iterator<WCell> iterator = wRow.values().iterator();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (iterator.hasNext()) {
|
|
|
|
|
|
|
|
WCell next = iterator.next();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (next.getStatus().name() != Status.PASS.name()) {
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 得到已生成好的Excel文件的字节流信息
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return 字节流信息
|
|
|
|
|
|
|
|
* @throws IOException
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public byte[] getBytes() throws IOException {
|
|
|
|
|
|
|
|
XSSFWorkbook workbook = getExcel(false);
|
|
|
|
|
|
|
|
if (workbook != null) {
|
|
|
|
|
|
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
|
|
|
|
|
workbook.write(outputStream);
|
|
|
|
|
|
|
|
return outputStream.toByteArray();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public XSSFWorkbook getExcel(boolean flag) {
|
|
|
|
|
|
|
|
XSSFWorkbook workbook = new XSSFWorkbook();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------- 创建样式 ------------------
|
|
|
|
|
|
|
|
CellStyle headCellStyle = new HeadCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle errorCellStyle = new ErrorCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle errorNumberCellStyle = new ErrorNumberCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle normalCellStyle = new NormalCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle normalNumberCellStyle = new NormalNumberCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle checkMessageCellStyle = new CheckMessageCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle checkFailureCellStyle = new CheckFailureCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
CellStyle checkSuccessCellStyle = new CheckSuccessCellStyle(workbook).getStyle();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------- 创建字体 ----------------
|
|
|
|
|
|
|
|
Font normalFont = new NormalFont(workbook).getFont();
|
|
|
|
|
|
|
|
Font redFont = new RedFont(workbook).getFont();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//创建一个Sheet表
|
|
|
|
|
|
|
|
XSSFSheet sheet = workbook.createSheet(name);
|
|
|
|
|
|
|
|
sheet.setDefaultRowHeightInPoints(20);
|
|
|
|
|
|
|
|
Row firstRow = sheet.createRow(0); // 下标为0的行开始
|
|
|
|
|
|
|
|
XSSFDrawing drawing = sheet.createDrawingPatriarch();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------表头--------------------
|
|
|
|
|
|
|
|
// if (flag) {
|
|
|
|
|
|
|
|
// // 检查结果栏
|
|
|
|
|
|
|
|
// org.apache.poi.ss.usermodel.Cell firstCell = firstRow.createCell(0);
|
|
|
|
|
|
|
|
// String columnName = WSheet.CHECK_STATUS_NAME;
|
|
|
|
|
|
|
|
// firstCell.setCellStyle(headCellStyle);
|
|
|
|
|
|
|
|
// firstCell.setCellValue(new XSSFRichTextString(columnName));
|
|
|
|
|
|
|
|
// sheet.setColumnWidth(0, (4 + 8) * 256);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// 数据栏
|
|
|
|
|
|
|
|
int hiddenNumber = 0;
|
|
|
|
|
|
|
|
for (int j = 0; j < this.columnList.size(); j++) {
|
|
|
|
|
|
|
|
WColumn column = this.columnList.get(j);
|
|
|
|
|
|
|
|
Field field = column.getField();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (column.isHidden()) {
|
|
|
|
|
|
|
|
hiddenNumber++;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int k = j - hiddenNumber;
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
|
|
|
|
k++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
org.apache.poi.ss.usermodel.Cell firstCell = firstRow.createCell(k);
|
|
|
|
|
|
|
|
String columnName = column.getName();
|
|
|
|
|
|
|
|
XSSFRichTextString textString;
|
|
|
|
|
|
|
|
if (column.isRequired()) {
|
|
|
|
|
|
|
|
textString = new XSSFRichTextString("*" + columnName);
|
|
|
|
|
|
|
|
textString.applyFont(0, 1, redFont);
|
|
|
|
|
|
|
|
textString.applyFont(1, textString.length(), normalFont);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
textString = new XSSFRichTextString(columnName);
|
|
|
|
|
|
|
|
textString.applyFont(normalFont);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
sb.append(column.getDescription()).append("\n");
|
|
|
|
|
|
|
|
// 添加数据说明信息。
|
|
|
|
|
|
|
|
if (field.isAnnotationPresent(ColumnDescription.class)) {
|
|
|
|
|
|
|
|
// 获取声明字段上的Description信息。
|
|
|
|
|
|
|
|
ColumnDescription columnDescription = field.getAnnotation(ColumnDescription.class);
|
|
|
|
|
|
|
|
sb.append(columnDescription.value());
|
|
|
|
|
|
|
|
sb.append("\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果填写了注释信息
|
|
|
|
|
|
|
|
if (sb.length() > 1) {
|
|
|
|
|
|
|
|
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6);
|
|
|
|
|
|
|
|
XSSFComment comment = drawing.createCellComment(anchor);
|
|
|
|
|
|
|
|
comment.setString(sb.toString());
|
|
|
|
|
|
|
|
firstCell.setCellComment(comment);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
firstCell.setCellValue(textString);
|
|
|
|
|
|
|
|
firstCell.setCellStyle(headCellStyle);
|
|
|
|
|
|
|
|
sheet.setColumnWidth(k, (4 + column.getCellWidth()) * 256);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 错误消息栏
|
|
|
|
|
|
|
|
// if (flag) {
|
|
|
|
|
|
|
|
// org.apache.poi.ss.usermodel.Cell firstCell = firstRow.createCell(table.getColumnIndex() + 1 - hiddenNumber);
|
|
|
|
|
|
|
|
// String columnName = WSheet.CHECK_STATUS_RESULT;
|
|
|
|
|
|
|
|
// firstCell.setCellStyle(headCellStyle);
|
|
|
|
|
|
|
|
// firstCell.setCellValue(new XSSFRichTextString(columnName));
|
|
|
|
|
|
|
|
// sheet.setColumnWidth(table.getColumnIndex() + 1, (4 + 10) * 256);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 冻结第一行
|
|
|
|
|
|
|
|
//sheet.createFreezePane(255,1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------数据--------------------
|
|
|
|
|
|
|
|
for (int i = 0; i < this.rowList.size(); i++) {
|
|
|
|
|
|
|
|
Row row = sheet.createRow(i + 1);
|
|
|
|
|
|
|
|
boolean rowFlag = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//如果该行有错误
|
|
|
|
|
|
|
|
// if (flag) {
|
|
|
|
|
|
|
|
// org.apache.poi.ss.usermodel.Cell xssfCell = row.createCell(0);
|
|
|
|
|
|
|
|
// if (table.getRowError(i) != null) {
|
|
|
|
|
|
|
|
// rowFlag = false;
|
|
|
|
|
|
|
|
// xssfCell.setCellValue("不通过");
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(checkFailureCellStyle);
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// xssfCell.setCellValue("通过");
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(checkSuccessCellStyle);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int j = 0;
|
|
|
|
|
|
|
|
hiddenNumber = 0;
|
|
|
|
|
|
|
|
for (; j < this.columnList.size(); j++) {
|
|
|
|
|
|
|
|
WColumn column = this.columnList.get(j);
|
|
|
|
|
|
|
|
if (column.isHidden()) {
|
|
|
|
|
|
|
|
hiddenNumber++;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int k = j - hiddenNumber;
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
|
|
|
|
k++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
org.apache.poi.ss.usermodel.Cell xssfCell = row.createCell(k);
|
|
|
|
|
|
|
|
WCell WCell = this.rowList.get(i).get(column.getName());
|
|
|
|
|
|
|
|
if (null == WCell) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
String value = WCell.getValue();
|
|
|
|
|
|
|
|
xssfCell.setCellValue(value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果该列是数字类型,则靠右
|
|
|
|
|
|
|
|
// if (table.getWColumns()[j].getDataType() == DataType.DECIMAL
|
|
|
|
|
|
|
|
// || table.getWColumns()[j].getDataType() == DataType.NUMBER) {
|
|
|
|
|
|
|
|
// if (flag && !WCell.getStatus().equals(Status.PASS)) {
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(errorNumberCellStyle);
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(normalNumberCellStyle);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// if (flag && !WCell.getStatus().equals(Status.PASS)) {
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(errorCellStyle);
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(normalCellStyle);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (flag && !rowFlag) {
|
|
|
|
|
|
|
|
// Cell xssfCell = row.createCell(j + 1 - hiddenNumber);
|
|
|
|
|
|
|
|
// xssfCell.setCellValue(table.getRowError(i));
|
|
|
|
|
|
|
|
// xssfCell.setCellStyle(checkMessageCellStyle);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return workbook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|