You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

661 lines
26 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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();
}
}

Powered by TurnKey Linux.