建议使用实例 1List 的方式,不需要建 Obj
样式规则主要代码:
private class StyleStrategy extends AbstractCellStyleStrategy {
private List<?> data; // 把整份数据传进来
private int type = 0; //不同的样式处理
private Map<Integer, List<int[]>> mergeMap = new HashMap<>(); //存储合并信息
private Set<Integer> mergeRows = new HashSet<>(); // 需要合并的行号 ,只 处理这些行进行相同单元格合并
public StyleStrategy(List<?> data, int... mergeRows) {
this.data = data;
this.mergeRows =
Arrays.stream(mergeRows).boxed().collect(Collectors.toSet());
calcMergedCol();
}
public StyleStrategy(int type, List<?> data, int... mergeRows) {
this.type = type;
this.data = data;
this.mergeRows =
Arrays.stream(mergeRows).boxed().collect(Collectors.toSet());
calcMergedCol();
}
/**
* 设置单元格样式
*
* @param context
*/
@Override
protected void setContentCellStyle(CellWriteHandlerContext context) {
Cell cell = context.getCell();
Sheet sheet = context.getWriteSheetHolder().getSheet();
int col = cell.getColumnIndex();
int row = context.getRowIndex();
//字符串若是数字的转为数字类型, 消除绿色角标
String cellValue = cell.getStringCellValue();
if (StringUtil.isNum(cellValue) != -1) {
cell.setCellValue(Double.parseDouble(cellValue));
}
/* —— 指定行相同内容格合并 —— */
List<int[]> rowMerge = mergeMap.get(row);
if (rowMerge != null) {
for (int[] range : rowMerge) {
int startCol = range[0];
int endCol = range[1];
if (col == startCol) {
// 如果已经合并过会抛异常,这里简单 try 住
try {
sheet.addMergedRegion(new CellRangeAddress(row, row,
startCol, endCol));
} catch (IllegalStateException ignored) {
// 已合并则跳过
}
}
}
}
// 全局设置列宽
// sheet.setColumnWidth(col, 16 * 256);
// 创建并设置单元格样式
Workbook wb = sheet.getWorkbook();
CellStyle style = wb.createCellStyle();
// 居中 + 换行
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setWrapText(true);
// 刷背景色
// if (row >= 2 ) {
//
style.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
// style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// }
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
//设置空边框
// style.setTopBorderColor(IndexedColors.WHITE.getIndex());
// style.setBottomBorderColor(IndexedColors.WHITE.getIndex());
// //设置边框
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
//设置行高、字号样式
if (type == 0) {
// 创建字体
Font font = wb.createFont();
font.setFontName("宋体"); // 字体名
//各行样式:行高、字号、加粗等
if (row == 0) {
sheet.getRow(row).setHeight((short) (46 * 20));
font.setFontHeightInPoints((short) 16); // 字号
font.setBold(true); // 加粗
} else if (row == 1) {
sheet.getRow(row).setHeight((short) (30 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(true); // 加粗
} else if (row == 2) {
sheet.getRow(row).setHeight((short) (30 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(true); // 加粗
} else if (row == data.size() - 1) {
sheet.getRow(row).setHeight((short) (66 * 20));//行高
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(false); // 加粗
} else {
sheet.getRow(row).setHeight((short) (28 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(false); // 加粗
}
// font.setColor(IndexedColors.RED.getIndex()); // 需要颜色再打开
style.setFont(font); // 把字体挂到样式
//各列样式:列宽,对其方式等
if (col == 0) {
sheet.setColumnWidth(col, 12 * 256);
} else if (col == 1) {
sheet.setColumnWidth(col, 24 * 256);
} else if (col == 2) {
sheet.setColumnWidth(col, 18 * 256);
} else if (col == 3) {
sheet.setColumnWidth(col, 12 * 256);
} else if (col == 7) {
sheet.setColumnWidth(col, 32 * 256);
} else {
sheet.setColumnWidth(col, 18 * 256);//其他的16
}
//指定单元格样式
if (row == 1 && (col == 2 || col == 6)) {
style.setAlignment(HorizontalAlignment.LEFT); //水平对齐方式
style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直 对齐方式
}
} else if (type == 1) {
// 创建字体
Font font = wb.createFont();
font.setFontName("宋体"); // 字体名
//各行样式:行高、字号、加粗等
if (row == 0) {
sheet.getRow(row).setHeight((short) (42 * 20));
font.setFontHeightInPoints((short) 16); // 字号
font.setBold(true); // 加粗
} else if (row == 1) {
sheet.getRow(row).setHeight((short) (32 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(true); // 加粗
} else if (row == 2) {
sheet.getRow(row).setHeight((short) (32 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(true); // 加粗
} else if (row == data.size() - 1) {
// style.setTopBorderColor(IndexedColors.WHITE.getIndex());// 空白上边框
//
style.setBottomBorderColor(IndexedColors.WHITE.getIndex());//空白下边框
//
style.setLeftBorderColor(IndexedColors.WHITE.getIndex());//空白左边框
// style.setRightBorderColor(IndexedColors.WHITE.getIndex());
//空白右边框
sheet.getRow(row).setHeight((short) (36 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(false); // 加粗
} else {
sheet.getRow(row).setHeight((short) (28 * 20));
font.setFontHeightInPoints((short) 12); // 字号
font.setBold(false); // 加粗
}
// font.setColor(IndexedColors.RED.getIndex()); // 需要颜色再打开
style.setFont(font); // 把字体挂到样式
//各列样式:列宽,对其方式等
if (col == 0) {
sheet.setColumnWidth(col, 10 * 256);
} else if (col == 1) {
sheet.setColumnWidth(col, 24 * 256);
} else if (col == 2) {
sheet.setColumnWidth(col, 18 * 256);
} else if (col == 3) {
sheet.setColumnWidth(col, 12 * 256);
} else if (col == 4) {
sheet.setColumnWidth(col, 24 * 256);
} else if (col == 5) {
sheet.setColumnWidth(col, 12 * 256);
} else if (col == 6) {
sheet.setColumnWidth(col, 12 * 256);
} else if (col == 7) {
sheet.setColumnWidth(col, 14 * 256);
} else if (col == 8) {
sheet.setColumnWidth(col, 12 * 256);
} else if (col == 9) {
sheet.setColumnWidth(col, 18 * 256);
} else {
sheet.setColumnWidth(col, 36 * 256);//其他的
}
//指定单元格样式
if (row == 1 && (col == 2 || col == 9)) {
style.setAlignment(HorizontalAlignment.LEFT); //水平对齐方式
style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直 对齐方式
}
}
cell.setCellStyle(style);
}
private void calcMergedCol() {
if (data == null || data.isEmpty()) return;
for (int r = 0; r < data.size(); r++) {
if (!mergeRows.isEmpty() && !mergeRows.contains(r)) continue;
Object row = data.get(r); // 可能是 List<String> 也可能是 JavaBean
Object[] cells; // 统一转成“列数组”
/* ---------- ① List<List<String>> 情况 ---------- */
if (row instanceof List) {
@SuppressWarnings("unchecked")
List<?> tmp = (List<?>) row;
// 如果第一个元素就是 String,就认为整行都是 String
if (!tmp.isEmpty() && tmp.get(0) instanceof String) {
cells = tmp.toArray(); // List<String> → String[]
} else {
/* ---------- ② List<YourBean> 情况 ---------- */
// EasyExcel 把每行包成 List<YourBean>,size=1
if (tmp.size() != 1) continue;
cells = objectToArray(tmp.get(0)); // 用你原来的反射
}
} else {
/* ---------- ③ 直接是 JavaBean(理论上不会走到) ---------- */
cells = objectToArray(row);
}
/* ---------- 公共合并逻辑 ---------- */
int colCount = cells.length;
List<int[]> rowMerge = new ArrayList<>();
int start = 0;
while (start < colCount) {
Object val = cells[start];
int end = start;
while (end + 1 < colCount && Objects.equals(val, cells[end +
1])) {
end++;
}
if (end > start) rowMerge.add(new int[]{start, end});
start = end + 1;
}
if (!rowMerge.isEmpty()) mergeMap.put(r, rowMerge);
}
}
}
private static Object[] objectToArray(Object row) {
try {
Class<?> clz = row.getClass();
Field[] fs = clz.getDeclaredFields();
Object[] cells = new Object[fs.length];
for (int i = 0; i < fs.length; i++) {
fs[i].setAccessible(true);
cells[i] = fs[i].get(row);
}
return cells;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
实例1: List excelData 无需创建对象导出,但需要自己组装 excelData 数据
/**
* 导出对账业务明细
*
* @param supplierStatement
* @return
*/
@PostMapping("/excelStatementDetail")
public void excelStatementDetail(@RequestBody ProSupplierStatement
supplierStatement) {
Preconditions.checkNotNull(supplierStatement.getId(), "id参数不能为空");
ProSupplierStatement old =
supplierStatementApi.getById(supplierStatement.getId());
Preconditions.checkNotNull(old, "数据不存在,请刷新后再试");
//文件名,也是titleRow的内容
String fileName = old.getTitle() + "业务明细";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd
HH:mm:ss");
//titleRow标题行数据
List<List<String>> excelData = new ArrayList<>();
List<String> head_1 = new ArrayList<>();
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
head_1.add(fileName);
excelData.add(head_1);
//其他表头行数据
List<String> head_2 = new ArrayList<>();
head_2.add("供应商");
head_2.add("供应商");
head_2.add(old.getSupplierName());
head_2.add(old.getSupplierName());
head_2.add(old.getSupplierName());
head_2.add(null);
head_2.add(null);
head_2.add("对账单号");
head_2.add("对账单号");
head_2.add(old.getCode());
head_2.add(old.getCode());
excelData.add(head_2);
//表头行数据
List<String> head_3 = new ArrayList<>();
head_3.add("序号");
head_3.add("业务单号");
head_3.add("日期");
head_3.add("类型");
head_3.add("品名");
head_3.add("单位");
head_3.add("数量");
head_3.add("总重量");
head_3.add("单价");
head_3.add("金额(元)");
head_3.add("备注");
excelData.add(head_3);
//业务数据获取
List<ProSupplierStatementDetail> details =
supplierStatementApi.getStatementDetailData(supplierStatement.getId());
//处理业务行数据,并统计合计列数据
Integer index = 1;
BigDecimal totalQuantity = BigDecimal.ZERO;
BigDecimal totalWeight = BigDecimal.ZERO;
BigDecimal totalPrice = BigDecimal.ZERO;
for (ProSupplierStatementDetail detail : details) {
totalQuantity = totalQuantity.add(detail.getQuantity());
totalWeight = totalWeight.add(detail.getWeight());
totalPrice = totalPrice.add(detail.getTotalPrice());
List<String> row = new ArrayList<>();
row.add(index.toString());
row.add(detail.getSourceCode());
row.add(formatter.format(detail.getSourceDate()));
row.add(detail.getSourceType());
row.add(detail.getMaterialsName());
row.add(detail.getUnit());
row.add(detail.getQuantity().stripTrailingZeros().toPlainString());
row.add(detail.getWeight().stripTrailingZeros().toPlainString());
row.add(detail.getUnitPrice().stripTrailingZeros().toPlainString());
row.add(detail.getTotalPrice().stripTrailingZeros().toPlainString());
row.add(detail.getSourceRemark());
excelData.add(row); //将业务数据加到导出数据中
}
//合计行数据
List<String> total_row = new ArrayList<>();
total_row.add(null);
total_row.add("合计");
total_row.add(null);
total_row.add(null);
total_row.add(null);
total_row.add(null);
total_row.add(totalQuantity.stripTrailingZeros().toPlainString());
total_row.add(totalWeight.stripTrailingZeros().toPlainString());
total_row.add(null);
total_row.add(totalPrice.stripTrailingZeros().toPlainString());
total_row.add(null);
excelData.add(total_row);
//其他页脚行数据
实例2:
List<List> excelData 使用对象数据进行导出
List<String> audit_row = new ArrayList<>();
audit_row.add("制表人");
audit_row.add(null);
audit_row.add(null);
audit_row.add("审核人");
audit_row.add(null);
audit_row.add(null);
audit_row.add(null);
audit_row.add(null);
audit_row.add(null);
audit_row.add("核对无误");
audit_row.add("核对无误");
excelData.add(audit_row);
//执行导出
try (ExcelWriter writer =
EasyExcel.write(response.getOutputStream()).build()) {
writer.write(
excelData,
EasyExcel.writerSheet(0, "sheet1")
.registerWriteHandler(new StyleStrategy(1,
excelData, 0, 1, excelData.size() - 1))//注册样式规则,type可以用来设置区分
.build());
} catch (IOException e) {
logError(e, "导出错误" + e.getMessage());
}
}