|
|
package ${basePackage}.frame.excel;
|
|
|
|
|
|
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
|
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
|
import org.apache.poi.ss.usermodel.Cell;
|
|
|
import org.apache.poi.ss.usermodel.CellStyle;
|
|
|
import org.apache.poi.ss.usermodel.Row;
|
|
|
import org.apache.poi.ss.usermodel.Sheet;
|
|
|
import org.apache.poi.ss.usermodel.Workbook;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFComment;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFDrawing;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
import ${basePackage}.frame.excel.annotation.ColumnDescription;
|
|
|
import ${basePackage}.frame.excel.annotation.ColumnName;
|
|
|
import ${basePackage}.frame.excel.annotation.Ignore;
|
|
|
import ${basePackage}.frame.excel.annotation.ParentFirst;
|
|
|
import ${basePackage}.frame.excel.annotation.SheetName;
|
|
|
import ${basePackage}.frame.excel.converter.BooleanConverter;
|
|
|
import ${basePackage}.frame.excel.converter.ByteConverter;
|
|
|
import ${basePackage}.frame.excel.converter.CharacterConverter;
|
|
|
import ${basePackage}.frame.excel.converter.Converter;
|
|
|
import ${basePackage}.frame.excel.converter.DateConverter;
|
|
|
import ${basePackage}.frame.excel.converter.DoubleConverter;
|
|
|
import ${basePackage}.frame.excel.converter.FloatConverter;
|
|
|
import ${basePackage}.frame.excel.converter.IntegerConverter;
|
|
|
import ${basePackage}.frame.excel.converter.LongConverter;
|
|
|
import ${basePackage}.frame.excel.converter.ShortConverter;
|
|
|
import ${basePackage}.frame.excel.converter.StringConverter;
|
|
|
import ${basePackage}.frame.excel.exception.ReadErrorException;
|
|
|
import ${basePackage}.frame.excel.exception.TemplateNotMatchException;
|
|
|
import ${basePackage}.frame.excel.exception.ValueConverterException;
|
|
|
import ${basePackage}.frame.excel.style.DataCellStyle;
|
|
|
import ${basePackage}.frame.excel.style.ErrorCellStyle;
|
|
|
import ${basePackage}.frame.excel.style.HeadCellStyle;
|
|
|
import ${basePackage}.frame.excel.style.RedFont;
|
|
|
import ${basePackage}.frame.excel.style.SuccessCellStyle;
|
|
|
import ${basePackage}.frame.utils.ClassUtil;
|
|
|
import ${basePackage}.frame.utils.FileUtil;
|
|
|
import ${basePackage}.frame.utils.LogUtil;
|
|
|
import ${basePackage}.frame.utils.ValidationUtil;
|
|
|
import ${basePackage}.module.system.ent.Dept;
|
|
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.io.File;
|
|
|
import java.io.FileOutputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.Serializable;
|
|
|
import java.lang.reflect.Field;
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
import java.lang.reflect.Method;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
|
|
|
/**
|
|
|
* WExcel - Excel-Sheet对象,完整的数据集合对象。
|
|
|
*
|
|
|
* @author wangbing
|
|
|
* @version 0.0.1
|
|
|
* @since 2017-01-01
|
|
|
*/
|
|
|
public class WExcel<T> implements Serializable, Cloneable {
|
|
|
|
|
|
/**
|
|
|
* 表名
|
|
|
*/
|
|
|
private String name;
|
|
|
|
|
|
/**
|
|
|
* 是否冻结第一行
|
|
|
*/
|
|
|
private boolean freezeFirst;
|
|
|
|
|
|
/**
|
|
|
* 模板类
|
|
|
*/
|
|
|
private Class<T> templateClass;
|
|
|
|
|
|
/**
|
|
|
* 表头的集合
|
|
|
*/
|
|
|
private List<WColumn> columnList = new ArrayList<>();
|
|
|
|
|
|
/**
|
|
|
* 单元格里存放的对象
|
|
|
*/
|
|
|
private List<WRow> rowList = new ArrayList<>();
|
|
|
|
|
|
/**
|
|
|
* 根据输入的模板类打印下载模板。
|
|
|
*/
|
|
|
public WExcel(Class<T> tClass) {
|
|
|
this.templateClass = tClass;
|
|
|
initColumns(tClass);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据模板类对DataTable添加相应的列。
|
|
|
*
|
|
|
* @return WColumn集合
|
|
|
*/
|
|
|
private List<WColumn> initColumns(Class<?> clazz) {
|
|
|
//获取工作簿名称,没有则以类名为默认工作簿名称
|
|
|
if (clazz.isAnnotationPresent(SheetName.class)) {
|
|
|
SheetName sheetName = clazz.getAnnotation(SheetName.class);
|
|
|
this.setName(sheetName.value());
|
|
|
this.setFreezeFirst(sheetName.freezeFirst());
|
|
|
} else {
|
|
|
this.setName(clazz.getSimpleName());
|
|
|
}
|
|
|
|
|
|
//是否关注父类属性
|
|
|
boolean parentFirst = clazz.isAnnotationPresent(ParentFirst.class) && clazz.getAnnotation(ParentFirst.class).value();
|
|
|
Field[] fields = ClassUtil.getFields(clazz, parentFirst);
|
|
|
for (Field field : fields) {
|
|
|
if (field.isAnnotationPresent(Ignore.class) && field.getAnnotation(Ignore.class).value()) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
WColumn WColumn = new WColumn();
|
|
|
WColumn.setField(field);
|
|
|
|
|
|
Method set = ClassUtil.setMethod(field.getName(), clazz, field.getType());
|
|
|
WColumn.setSetMethod(set);
|
|
|
|
|
|
Method get = ClassUtil.getMethod(field.getName(), clazz);
|
|
|
WColumn.setGetMethod(get);
|
|
|
|
|
|
//获取列名称
|
|
|
if (!field.isAnnotationPresent(ColumnName.class)) {
|
|
|
WColumn.setName(field.getName());
|
|
|
} else {
|
|
|
ColumnName columnColumnName = field.getAnnotation(ColumnName.class);
|
|
|
WColumn.setName(columnColumnName.value());
|
|
|
WColumn.setCellWidth(columnColumnName.width());
|
|
|
WColumn.setRequired(columnColumnName.required());
|
|
|
}
|
|
|
//获取列填写说明或描述
|
|
|
if (field.isAnnotationPresent(ColumnDescription.class)) {
|
|
|
WColumn.setDescription(field.getAnnotation(ColumnDescription.class).value());
|
|
|
}
|
|
|
|
|
|
//获取列类型
|
|
|
if (field.isAnnotationPresent(${basePackage}.frame.excel.annotation.Converter.class)) {
|
|
|
${basePackage}.frame.excel.annotation.Converter converter = field.getAnnotation(${basePackage}.frame.excel.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());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_BOOLEAN);
|
|
|
} else if (field.getType() == byte.class || field.getType() == Byte.class) {
|
|
|
WColumn.setConverter(new ByteConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == char.class || field.getType() == Character.class) {
|
|
|
WColumn.setConverter(new CharacterConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_STRING);
|
|
|
} else if (field.getType() == short.class || field.getType() == Short.class) {
|
|
|
WColumn.setConverter(new ShortConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == int.class || field.getType() == Integer.class) {
|
|
|
WColumn.setConverter(new IntegerConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == long.class || field.getType() == Long.class) {
|
|
|
WColumn.setConverter(new LongConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == float.class || field.getType() == Float.class) {
|
|
|
WColumn.setConverter(new FloatConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == double.class || field.getType() == Double.class) {
|
|
|
WColumn.setConverter(new DoubleConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == Date.class) {
|
|
|
WColumn.setConverter(new DateConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_NUMERIC);
|
|
|
} else if (field.getType() == String.class) {
|
|
|
WColumn.setConverter(new StringConverter());
|
|
|
WColumn.setCellType(Cell.CELL_TYPE_STRING);
|
|
|
} else {
|
|
|
throw new RuntimeException("Can not find Converter");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
columnList.add(WColumn);
|
|
|
}
|
|
|
return columnList;
|
|
|
}
|
|
|
|
|
|
public WExcel loadData(List<T> list) {
|
|
|
return loadData(list, null);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 此构造方法仅用于转换对象列表。<br/>
|
|
|
* 并不会对数据的格式和合法性进行检验。
|
|
|
*
|
|
|
* @param list 需要导出的对象列表
|
|
|
*/
|
|
|
public WExcel loadData(List<T> list, Processor<T> processor) {
|
|
|
if (list.size() > 0) {
|
|
|
for (T t : list) {
|
|
|
WRow row = new WRow();
|
|
|
for (WColumn column : columnList) {
|
|
|
if (column == null) {
|
|
|
continue;
|
|
|
}
|
|
|
Method method = column.getGetMethod();
|
|
|
try {
|
|
|
Object value = method.invoke(t);
|
|
|
if (null == value) {
|
|
|
row.put(column.getName(), new WCell());
|
|
|
} else {
|
|
|
String string = column.getConverter().string(value);
|
|
|
row.put(column.getName(), new WCell(string));
|
|
|
}
|
|
|
} catch (IllegalAccessException e) {
|
|
|
LogUtil.w("can not invoke get method!");
|
|
|
} catch (InvocationTargetException e) {
|
|
|
LogUtil.w(method.getName() + " unexpected exception!");
|
|
|
}
|
|
|
// <2层检查>检查模板注解验证是否通过
|
|
|
row.addErrors(ValidationUtil.validate(t));
|
|
|
// <3层检查>如果没有错误,则可以执行处理器进行逻辑处理
|
|
|
if (!row.hasError() && processor != null) {
|
|
|
row.addErrors(processor.exec(t));
|
|
|
}
|
|
|
}
|
|
|
this.rowList.add(row);
|
|
|
}
|
|
|
}
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
public WExcel loadData(byte[] bytes) throws TemplateNotMatchException, ReadErrorException {
|
|
|
return loadData(bytes, null);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 以Excel文件的字节数组为数据源,为自己赋值的同时,与指定的模板类进行数据校验。<br/>
|
|
|
* 如果匹配过程中发现了不符合的数据,会在对应的单元中添加错误信息。<br/>
|
|
|
*/
|
|
|
public WExcel loadData(byte[] bytes, Processor<T> processor) throws TemplateNotMatchException, ReadErrorException {
|
|
|
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) {
|
|
|
try {
|
|
|
is.close();
|
|
|
} catch (IOException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
if (!flag) {
|
|
|
throw new ReadErrorException("读取Excel文件错误");
|
|
|
}
|
|
|
//第一张Sheet表
|
|
|
Sheet sheet = workbook.getSheetAt(0);
|
|
|
//获取Sheet名称
|
|
|
if (templateClass.isAnnotationPresent(SheetName.class)) {//如果模板存在注解则使用注解名称
|
|
|
SheetName sheetName = templateClass.getAnnotation(SheetName.class);
|
|
|
this.setName(sheetName.value());
|
|
|
} else {//将类名设为表名,如果类名不存在,将Excel表名设为表名
|
|
|
this.setName(sheet.getSheetName());
|
|
|
}
|
|
|
|
|
|
//读取表头
|
|
|
Row headRow = sheet.getRow(0);
|
|
|
//获取Excel列的总数
|
|
|
int columnSum = headRow.getPhysicalNumberOfCells();
|
|
|
|
|
|
//检查列数量
|
|
|
if (columnList.size() != columnSum) {
|
|
|
throw new TemplateNotMatchException("与模板列数量不同。");
|
|
|
} else {
|
|
|
for (int i = 0; i < columnList.size(); i++) {
|
|
|
WColumn wColumn = columnList.get(i);
|
|
|
Cell cell = headRow.getCell(i);
|
|
|
String headValue = 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 = getValue(excelCell);
|
|
|
}
|
|
|
value = value.trim();
|
|
|
|
|
|
WCell.setValue(value);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
T t = templateClass.newInstance();
|
|
|
// <1层检查>检查数据格式是否正确
|
|
|
row.addErrors(transferMap(row, t));
|
|
|
// <2层检查>检查模板注解验证是否通过
|
|
|
row.addErrors(ValidationUtil.validate(t));
|
|
|
// <3层检查>如果没有错误,则可以执行处理器进行逻辑处理
|
|
|
if (!row.hasError() && processor != null) {
|
|
|
row.addErrors(processor.exec(t));
|
|
|
}
|
|
|
} catch (InstantiationException | IllegalAccessException e) {
|
|
|
row.addError("模板对象默认构造函数错误");
|
|
|
}
|
|
|
}
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 转换某行为一个对象
|
|
|
*
|
|
|
* @param row 行对象
|
|
|
* @param target 模板对象
|
|
|
* @return 模板对象
|
|
|
*/
|
|
|
public List<String> transferMap(WRow row, T target) {
|
|
|
List<String> err = new ArrayList<>();
|
|
|
for (String key : row.keySet()) {
|
|
|
for (WColumn column : columnList) {
|
|
|
String name = column.getName();
|
|
|
Method setMethod = column.getSetMethod();
|
|
|
|
|
|
if (key.equals(name)) {
|
|
|
WCell WCell = row.get(column.getName());
|
|
|
if (null != WCell) {
|
|
|
String value = WCell.getValue();
|
|
|
//获取转换器
|
|
|
Converter converter = column.getConverter();
|
|
|
try {
|
|
|
setMethod.invoke(target, converter.convert(value));
|
|
|
} catch (ValueConverterException e) {
|
|
|
e.printStackTrace();
|
|
|
err.add(e.getMessage());
|
|
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
|
e.printStackTrace();
|
|
|
err.add("[" + setMethod.getName() + "]执行错误");
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取表名
|
|
|
*
|
|
|
* @return 表名
|
|
|
*/
|
|
|
public String getName() {
|
|
|
return name;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 设置表名
|
|
|
*
|
|
|
* @param name 表名
|
|
|
*/
|
|
|
public void setName(String name) {
|
|
|
this.name = name;
|
|
|
}
|
|
|
|
|
|
public boolean getFreezeFirst() {
|
|
|
return freezeFirst;
|
|
|
}
|
|
|
|
|
|
public void setFreezeFirst(boolean freezeFirst) {
|
|
|
this.freezeFirst = freezeFirst;
|
|
|
}
|
|
|
|
|
|
public final String toCSV() {
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
for (WColumn WColumn : this.columnList) {
|
|
|
if (WColumn != null) {
|
|
|
sb.append(WColumn.getName()).append(",");
|
|
|
}
|
|
|
}
|
|
|
sb.append("\n");
|
|
|
|
|
|
for (int i = 0; i < this.rowList.size(); i++) {
|
|
|
for (int j = 0; j < this.columnList.size(); j++) {
|
|
|
WColumn wColumn = this.columnList.get(j);
|
|
|
WCell wCell = this.rowList.get(i).get(wColumn.getName());
|
|
|
sb.append(wCell.getValue()).append(",");
|
|
|
}
|
|
|
sb.append("\n");
|
|
|
}
|
|
|
|
|
|
return sb.toString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 判断DataTable是否包含错误信息
|
|
|
*
|
|
|
* @return 是否包含错误.
|
|
|
*/
|
|
|
public final boolean hasError() {
|
|
|
for (WRow wRow : rowList) {
|
|
|
if (wRow.hasError()) {
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
public byte[] getBytes() {
|
|
|
XSSFWorkbook workbook = getExcel();
|
|
|
if (workbook != null) {
|
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
try {
|
|
|
workbook.write(outputStream);
|
|
|
} catch (IOException e) {
|
|
|
return null;
|
|
|
}
|
|
|
return outputStream.toByteArray();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
public XSSFWorkbook getExcel() {
|
|
|
XSSFWorkbook workbook = new XSSFWorkbook();
|
|
|
//创建一个Sheet表
|
|
|
XSSFSheet sheet = workbook.createSheet(name);
|
|
|
sheet.setDefaultRowHeightInPoints(18);
|
|
|
Row firstRow = sheet.createRow(0); // 下标为0的行开始
|
|
|
XSSFDrawing drawing = sheet.createDrawingPatriarch();
|
|
|
|
|
|
int offset = 0;
|
|
|
// 添加结果和错误说明列
|
|
|
if (hasError()) {
|
|
|
offset++;
|
|
|
{// 第一栏结果栏
|
|
|
Cell firstCell = firstRow.createCell(0);
|
|
|
firstCell.setCellStyle(new HeadCellStyle(workbook).getStyle());
|
|
|
firstCell.setCellValue(new XSSFRichTextString("执行结果"));
|
|
|
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6);
|
|
|
XSSFComment comment = drawing.createCellComment(anchor);
|
|
|
comment.setString("此列为检查结果,导入时请处理完错误,并删除该列!");
|
|
|
firstCell.setCellComment(comment);
|
|
|
}
|
|
|
offset++;
|
|
|
{// 第二栏错误信息栏
|
|
|
Cell secondCell = firstRow.createCell(1);
|
|
|
secondCell.setCellStyle(new HeadCellStyle(workbook).getStyle());
|
|
|
secondCell.setCellValue(new XSSFRichTextString("结果说明"));
|
|
|
sheet.setColumnWidth(1, 18 * 256);
|
|
|
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6);
|
|
|
XSSFComment comment = drawing.createCellComment(anchor);
|
|
|
comment.setString("此列为检查结果信息列,导入时请处理完错误,并删除该列!");
|
|
|
secondCell.setCellComment(comment);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (int j = 0; j < this.columnList.size(); j++) {
|
|
|
WColumn column = this.columnList.get(j);
|
|
|
Cell firstCell = firstRow.createCell(j + offset);
|
|
|
String columnName = column.getName();
|
|
|
XSSFRichTextString textString;
|
|
|
if (column.isRequired()) {
|
|
|
textString = new XSSFRichTextString("*" + columnName);
|
|
|
textString.applyFont(0, 1, new RedFont(workbook).getFont());
|
|
|
textString.applyFont(1, textString.length(), workbook.createFont());
|
|
|
} else {
|
|
|
textString = new XSSFRichTextString(columnName);
|
|
|
textString.applyFont(workbook.createFont());
|
|
|
}
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
sb.append(column.getDescription()).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(new HeadCellStyle(workbook).getStyle());
|
|
|
sheet.setColumnWidth(j + offset, (4 + column.getCellWidth()) * 256);
|
|
|
}
|
|
|
|
|
|
// 冻结第一行
|
|
|
if (freezeFirst) {
|
|
|
sheet.createFreezePane(255, 1);
|
|
|
}
|
|
|
|
|
|
// 填充数据
|
|
|
for (int i = 0; i < this.rowList.size(); i++) {
|
|
|
WRow wRow = this.rowList.get(i);
|
|
|
Row row = sheet.createRow(i + 1);
|
|
|
|
|
|
if(offset> 0){
|
|
|
if (this.rowList.get(i).hasError()) {
|
|
|
// 添加结果
|
|
|
List<String> errorList = wRow.getErrorList();
|
|
|
Cell resultCell = row.createCell(0);
|
|
|
resultCell.setCellStyle(new ErrorCellStyle(workbook).getStyle());
|
|
|
resultCell.setCellValue("错误");
|
|
|
// 添加错误信息详细说明
|
|
|
Cell errsCell = row.createCell(1);
|
|
|
errsCell.setCellStyle(new ErrorCellStyle(workbook).getStyle());
|
|
|
String join = String.join(";", errorList);
|
|
|
errsCell.setCellValue(new XSSFRichTextString(join));
|
|
|
} else {
|
|
|
// 添加结果
|
|
|
Cell resultCell = row.createCell(0);
|
|
|
resultCell.setCellStyle(new SuccessCellStyle(workbook).getStyle());
|
|
|
resultCell.setCellValue("成功");
|
|
|
// 添加错误信息详细说明
|
|
|
Cell errsCell = row.createCell(1);
|
|
|
errsCell.setCellStyle(new SuccessCellStyle(workbook).getStyle());
|
|
|
errsCell.setCellValue("");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (int j = 0; j < this.columnList.size(); j++) {
|
|
|
WColumn column = this.columnList.get(j);
|
|
|
|
|
|
Cell xssfCell = row.createCell(j + offset);
|
|
|
WCell WCell = this.rowList.get(i).get(column.getName());
|
|
|
if (null == WCell) {
|
|
|
continue;
|
|
|
}
|
|
|
String value = WCell.getValue();
|
|
|
xssfCell.setCellType(column.getCellType());
|
|
|
if (column.getCellType() == Cell.CELL_TYPE_NUMERIC || column.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
|
|
|
xssfCell.setCellStyle(new DataCellStyle(workbook, CellStyle.ALIGN_RIGHT, wRow.hasError()).getStyle());
|
|
|
} else {
|
|
|
xssfCell.setCellStyle(new DataCellStyle(workbook, CellStyle.ALIGN_LEFT, wRow.hasError()).getStyle());
|
|
|
}
|
|
|
|
|
|
xssfCell.setCellValue(value);
|
|
|
}
|
|
|
}
|
|
|
return workbook;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取单元格的值
|
|
|
*
|
|
|
* @param cell 要获取值的单元格
|
|
|
* @return 单元格的值
|
|
|
*/
|
|
|
public static String getValue(Cell cell) {
|
|
|
if (cell == null) {
|
|
|
return "";
|
|
|
}
|
|
|
switch (cell.getCellType()) {
|
|
|
case Cell.CELL_TYPE_STRING:
|
|
|
return cell.getStringCellValue();
|
|
|
case Cell.CELL_TYPE_BOOLEAN:
|
|
|
return String.valueOf(cell.getBooleanCellValue());
|
|
|
case Cell.CELL_TYPE_NUMERIC:
|
|
|
if (HSSFDateUtil.isCellDateFormatted(cell)) {
|
|
|
Date value = cell.getDateCellValue();
|
|
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value);
|
|
|
} else {
|
|
|
double numericCellValue = cell.getNumericCellValue();
|
|
|
String s = String.valueOf(numericCellValue);
|
|
|
return s.replaceAll("\\.0$", "");
|
|
|
}
|
|
|
default:
|
|
|
return cell.getStringCellValue();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public interface Processor<T> {
|
|
|
List<String> exec(T t);
|
|
|
}
|
|
|
|
|
|
public void toFile(File file) throws IOException {
|
|
|
File parentFile = file.getParentFile();
|
|
|
if (!parentFile.exists() && !parentFile.mkdirs()) {
|
|
|
throw new RuntimeException("路径创建失败");
|
|
|
}
|
|
|
if (!file.exists() && !file.createNewFile()) {
|
|
|
throw new RuntimeException("文件创建失败");
|
|
|
}
|
|
|
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
|
|
fileOutputStream.write(getBytes());
|
|
|
fileOutputStream.close();
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
Dept dept = new Dept();
|
|
|
dept.setDeptName("AAAAAA");
|
|
|
ArrayList<Dept> depts = new ArrayList<Dept>();
|
|
|
depts.add(dept);
|
|
|
File file = new File("E:\\E.xlsx");
|
|
|
|
|
|
// 导出模板
|
|
|
// new WExcel<Dept>(Dept.class).loadData(depts).toFile(file);
|
|
|
|
|
|
// 检查excel文件是否符合导入
|
|
|
byte[] bytes = FileUtil.readFileToByteArray(new File("E:\\E.xlsx"));
|
|
|
try {
|
|
|
WExcel check = new WExcel<Dept>(Dept.class).loadData(bytes);
|
|
|
check.toFile(new File("E:\\E_err.xlsx"));
|
|
|
System.out.println(check.hasError());
|
|
|
} catch (TemplateNotMatchException e) {
|
|
|
e.printStackTrace();
|
|
|
} catch (ReadErrorException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
|
|
|
System.out.println();
|
|
|
}
|
|
|
}
|