对比了一下 easyexcel ,jxls , poi-tl 等工具,感觉各有千秋。
做个笔记,有需要的同学可以进行参考
github地址:https://github.com/alibaba/easyexcel
1、先定义模板

2、上代码
java
package com.luo.easyexcel.demos;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
public class BasicTest {
public static void main(String[] args) {
ExcelWriter excelWriter = EasyExcel.write("D:\\result.xlsx", User.class)
.withTemplate("D:\\template.xlsx")
.registerWriteHandler(new FillRowMergeStrategy())
.autoCloseStream(false)
.build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
Map<String, Object> params = new HashMap<>(8);
params.put("spr", "张三");
params.put("spsj", LocalDateTime.now());
params.put("cjr", "李四");
params.put("cjsj", LocalDateTime.now());
excelWriter.fill(params, writeSheet);
excelWriter.fill(getData(), fillConfig, writeSheet);
// 完成写入
excelWriter.finish();
}
private static class FillRowMergeStrategy implements CellWriteHandler {
/** 需要进行单元格合并的列数组 **/
private int mergeColumnIndex = 0;
private int mergeRowIndex = 4;
/**
* 在每个单元格写入完成后执行,适合做样式、合并、校验等操作
* @param writeSheetHolder 当前 sheet 的上下文信息(如当前行、sheet 对象等)
* @param writeTableHolder 表格相关上下文(通常不常用)
* @param cellDataList 当前单元格的数据集合(包含样式、值等)
* @param cell
* @param head 表头信息
* @param relativeRowIndex 当前行在数据中的索引(从 0 开始)
* @param isHead 是否是表头
*/
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
int curRowIndex = cell.getRowIndex();
int curColIndex = cell.getColumnIndex();
if (curRowIndex > mergeRowIndex) {
if (curColIndex == mergeColumnIndex) {
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
}
}
}
/**
* 当前单元格向上合并
*
* @param writeSheetHolder
* @param cell
* 当前单元格
* @param curRowIndex
* 当前行
* @param curColIndex
* 当前列
*/
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
Object curData = getCellValue(cell);
Row preRow = cell.getSheet().getRow(curRowIndex - 1);
if (preRow == null) {
// 当获取不到上一行数据时,使用缓存sheet中数据
preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
}
Cell preCell = preRow.getCell(curColIndex);
Object preData = getCellValue(preCell);
// 将当前单元格数据与上一个单元格数据比较
boolean same = preData.equals(curData);
if (same) {
Sheet sheet = writeSheetHolder.getSheet();
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 若上一个单元格未被合并,则新增合并单元
if (!isMerged) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
}
// 获取单元格值
private Object getCellValue(Cell cell) {
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
return cell.getNumericCellValue();
case BOOLEAN:
return cell.getBooleanCellValue();
default:
return null;
}
}
}
/**
* 测试数据
*/
private static List<User> getData() {
List<User> userList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
if (i > 5) {
userList.add(new User("张三" + i,"男", "北京"+i, LocalDate.now(), "17745528756", "xxxxxxx", 18));
}else if (i > 3){
userList.add(new User("张三" + i,"男", "北京"+i, LocalDate.now(), "17745528756", "xxxxxxx", 19));
}else {
userList.add(new User("张三" + i,"男", "北京"+i, LocalDate.now(), "17745528756", "xxxxxxx", 20));
}
}
return userList;
}
}
效果如下
