|
|
@ -1,6 +1,7 @@
|
|
|
|
package com.ruoyi.common.utils.poi;
|
|
|
|
package com.ruoyi.common.utils.poi;
|
|
|
|
|
|
|
|
|
|
|
|
import com.ruoyi.common.annotation.Excel;
|
|
|
|
import com.ruoyi.common.annotation.Excel;
|
|
|
|
|
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
|
import org.apache.poi.ss.usermodel.*;
|
|
|
|
import org.apache.poi.ss.usermodel.*;
|
|
|
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
|
|
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
|
|
|
|
|
|
|
|
|
|
@ -9,10 +10,7 @@ import java.io.IOException;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
import java.net.URLEncoder;
|
|
|
|
import java.net.URLEncoder;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.Comparator;
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* ClassName: MultiSheetExcelUtil
|
|
|
|
* ClassName: MultiSheetExcelUtil
|
|
|
@ -40,7 +38,7 @@ public class MultiSheetExcelUtil {
|
|
|
|
|
|
|
|
|
|
|
|
public <T> void createSheet(List<T> list, String sheetName, Class<T> clazz) {
|
|
|
|
public <T> void createSheet(List<T> list, String sheetName, Class<T> clazz) {
|
|
|
|
Sheet sheet = workbook.createSheet(sheetName);
|
|
|
|
Sheet sheet = workbook.createSheet(sheetName);
|
|
|
|
List<Object[]> fields = getFields(clazz);
|
|
|
|
List<FieldMeta> fields = getFields(clazz); // 使用新版getFields
|
|
|
|
createTitleRow(sheet, fields);
|
|
|
|
createTitleRow(sheet, fields);
|
|
|
|
fillDataRows(sheet, list, fields);
|
|
|
|
fillDataRows(sheet, list, fields);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -68,54 +66,86 @@ public class MultiSheetExcelUtil {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static List<Object[]> getFields(Class<?> clazz) {
|
|
|
|
|
|
|
|
List<Object[]> fields = new ArrayList<>();
|
|
|
|
private static class FieldMeta {
|
|
|
|
Field[] declaredFields = clazz.getDeclaredFields();
|
|
|
|
private final Field field; // 反射字段对象
|
|
|
|
for (Field field : declaredFields) {
|
|
|
|
private final String title; // 表头名称(@Excel.name)
|
|
|
|
Excel excel = field.getAnnotation(Excel.class);
|
|
|
|
private final String dateFormat; // 日期格式(@Excel.dateFormat)
|
|
|
|
if (excel != null) {
|
|
|
|
private final int sort; // 排序(@Excel.sort)
|
|
|
|
fields.add(new Object[]{field.getName(), excel.name(), excel.readConverterExp(), excel.dictType(), excel.sort()});
|
|
|
|
|
|
|
|
}
|
|
|
|
public FieldMeta(Field field, String title, String dateFormat, int sort) {
|
|
|
|
|
|
|
|
this.field = field;
|
|
|
|
|
|
|
|
this.title = title;
|
|
|
|
|
|
|
|
this.dateFormat = dateFormat;
|
|
|
|
|
|
|
|
this.sort = sort;
|
|
|
|
|
|
|
|
this.field.setAccessible(true); // 提前设置可访问
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Class<?> superClass = clazz.getSuperclass();
|
|
|
|
|
|
|
|
while (superClass != null) {
|
|
|
|
// Getter 方法
|
|
|
|
Field[] superFields = superClass.getDeclaredFields();
|
|
|
|
public Field getField() { return field; }
|
|
|
|
for (Field field : superFields) {
|
|
|
|
public String getTitle() { return title; }
|
|
|
|
Excel excel = field.getAnnotation(Excel.class);
|
|
|
|
public String getDateFormat() { return dateFormat; }
|
|
|
|
if (excel != null) {
|
|
|
|
public int getSort() { return sort; }
|
|
|
|
fields.add(new Object[]{field.getName(), excel.name(), excel.readConverterExp(), excel.dictType(), excel.sort()});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 获取所有带@Excel注解的字段(包含父类)
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static List<FieldMeta> getFields(Class<?> clazz) {
|
|
|
|
|
|
|
|
List<FieldMeta> fields = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 递归获取所有字段(包括父类)
|
|
|
|
|
|
|
|
Class<?> currentClass = clazz;
|
|
|
|
|
|
|
|
while (currentClass != null) {
|
|
|
|
|
|
|
|
for (Field field : currentClass.getDeclaredFields()) {
|
|
|
|
|
|
|
|
Excel excelAnno = field.getAnnotation(Excel.class);
|
|
|
|
|
|
|
|
if (excelAnno != null) {
|
|
|
|
|
|
|
|
fields.add(new FieldMeta(
|
|
|
|
|
|
|
|
field,
|
|
|
|
|
|
|
|
excelAnno.name(),
|
|
|
|
|
|
|
|
excelAnno.dateFormat(),
|
|
|
|
|
|
|
|
excelAnno.sort()
|
|
|
|
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
superClass = superClass.getSuperclass();
|
|
|
|
currentClass = currentClass.getSuperclass();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fields.sort(Comparator.comparing(o -> (Integer) o[4]));
|
|
|
|
|
|
|
|
|
|
|
|
// 按sort排序
|
|
|
|
|
|
|
|
fields.sort(Comparator.comparingInt(FieldMeta::getSort));
|
|
|
|
return fields;
|
|
|
|
return fields;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Object getFieldValueByName(String fieldName, Object obj) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
Field field = obj.getClass().getDeclaredField(fieldName);
|
|
|
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
|
|
|
return field.get(obj);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setCellValue(Cell cell, Object value) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setCellValue(Cell cell, Object value, FieldMeta meta) {
|
|
|
|
if (value == null) {
|
|
|
|
if (value == null) {
|
|
|
|
cell.setCellValue("");
|
|
|
|
cell.setCellValue("");
|
|
|
|
} else if (value instanceof String) {
|
|
|
|
return;
|
|
|
|
cell.setCellValue((String) value);
|
|
|
|
}
|
|
|
|
} else if (value instanceof Integer) {
|
|
|
|
|
|
|
|
cell.setCellValue((Integer) value);
|
|
|
|
// 处理日期类型
|
|
|
|
} else if (value instanceof Long) {
|
|
|
|
if (value instanceof Date) {
|
|
|
|
cell.setCellValue((Long) value);
|
|
|
|
String format = StringUtils.isNotEmpty(meta.getDateFormat())
|
|
|
|
} else if (value instanceof Double) {
|
|
|
|
? meta.getDateFormat()
|
|
|
|
cell.setCellValue((Double) value);
|
|
|
|
: "yyyy-MM-dd"; // 默认格式
|
|
|
|
} else if (value instanceof Boolean) {
|
|
|
|
|
|
|
|
cell.setCellValue((Boolean) value);
|
|
|
|
CellStyle style = workbook.createCellStyle();
|
|
|
|
} else {
|
|
|
|
style.setDataFormat(
|
|
|
|
|
|
|
|
workbook.getCreationHelper()
|
|
|
|
|
|
|
|
.createDataFormat()
|
|
|
|
|
|
|
|
.getFormat(format)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
cell.setCellValue((Date) value);
|
|
|
|
|
|
|
|
cell.setCellStyle(style);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 处理数字类型
|
|
|
|
|
|
|
|
else if (value instanceof Number) {
|
|
|
|
|
|
|
|
cell.setCellValue(((Number) value).doubleValue());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 其他类型
|
|
|
|
|
|
|
|
else {
|
|
|
|
cell.setCellValue(value.toString());
|
|
|
|
cell.setCellValue(value.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -162,21 +192,42 @@ public class MultiSheetExcelUtil {
|
|
|
|
return style;
|
|
|
|
return style;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void createTitleRow(Sheet sheet, List<Object[]> fields) {
|
|
|
|
|
|
|
|
|
|
|
|
private void createTitleRow(Sheet sheet, List<FieldMeta> fields) {
|
|
|
|
|
|
|
|
Row headerRow = sheet.createRow(0);
|
|
|
|
CellStyle headerStyle = createHeaderStyle(workbook);
|
|
|
|
CellStyle headerStyle = createHeaderStyle(workbook);
|
|
|
|
CellStyle dataStyle = createDataStyle(workbook); // 数据行样式(可选)
|
|
|
|
|
|
|
|
Row row = sheet.createRow(0);
|
|
|
|
|
|
|
|
for (int i = 0; i < fields.size(); i++) {
|
|
|
|
for (int i = 0; i < fields.size(); i++) {
|
|
|
|
Cell cell = row.createCell(i);
|
|
|
|
Cell cell = headerRow.createCell(i);
|
|
|
|
cell.setCellValue((String) fields.get(i)[1]);
|
|
|
|
cell.setCellValue(fields.get(i).getTitle());
|
|
|
|
cell.setCellStyle(headerStyle);
|
|
|
|
cell.setCellStyle(headerStyle);
|
|
|
|
// 设置列宽
|
|
|
|
sheet.setColumnWidth(i, 6000); // 默认列宽
|
|
|
|
sheet.setColumnWidth(i, Math.max(sheet.getColumnWidth(i), 3000));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private <T> void fillDataRows(Sheet sheet, List<T> list, List<Object[]> fields) {
|
|
|
|
|
|
|
|
CellStyle dataStyle = createDataStyle(workbook); // 应用数据行样式
|
|
|
|
private <T> void fillDataRows(Sheet sheet, List<T> list, List<FieldMeta> fields) {
|
|
|
|
|
|
|
|
int rowNum = 1;
|
|
|
|
|
|
|
|
for (T item : list) {
|
|
|
|
|
|
|
|
Row row = sheet.createRow(rowNum++);
|
|
|
|
|
|
|
|
for (int i = 0; i < fields.size(); i++) {
|
|
|
|
|
|
|
|
FieldMeta meta = fields.get(i);
|
|
|
|
|
|
|
|
Cell cell = row.createCell(i);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 直接通过缓存的Field对象获取值
|
|
|
|
|
|
|
|
Object value = meta.getField().get(item);
|
|
|
|
|
|
|
|
setCellValue(cell, value, meta); // 传递FieldMeta对象
|
|
|
|
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
|
|
|
|
cell.setCellValue("N/A");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*private <T> void fillDataRows(Sheet sheet, List<T> list, List<Object[]> fields) {
|
|
|
|
|
|
|
|
CellStyle dataStyle = createDataStyle(workbook);
|
|
|
|
int rowNum = 1;
|
|
|
|
int rowNum = 1;
|
|
|
|
for (T item : list) {
|
|
|
|
for (T item : list) {
|
|
|
|
Row row = sheet.createRow(rowNum++);
|
|
|
|
Row row = sheet.createRow(rowNum++);
|
|
|
@ -185,10 +236,16 @@ public class MultiSheetExcelUtil {
|
|
|
|
Object[] fieldInfo = fields.get(i);
|
|
|
|
Object[] fieldInfo = fields.get(i);
|
|
|
|
String fieldName = (String) fieldInfo[0];
|
|
|
|
String fieldName = (String) fieldInfo[0];
|
|
|
|
Object value = getFieldValueByName(fieldName, item);
|
|
|
|
Object value = getFieldValueByName(fieldName, item);
|
|
|
|
setCellValue(cell, value);
|
|
|
|
// 获取Field对象并传递
|
|
|
|
cell.setCellStyle(dataStyle); // 应用数据行样式
|
|
|
|
try {
|
|
|
|
|
|
|
|
Field field = item.getClass().getDeclaredField(fieldName);
|
|
|
|
|
|
|
|
setCellValue(cell, value, field); // 调用新版方法
|
|
|
|
|
|
|
|
} catch (NoSuchFieldException e) {
|
|
|
|
|
|
|
|
setCellValue(cell, value, null); // 降级处理
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cell.setCellStyle(dataStyle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|