EasyExcel的不确定表头(根据数据生成表头)的excel导出和二级表头或多级表头以及设置表头的宽度自适应
1、效果如图
2、Controller
@GetMapping("/exportExcel") public void exportExcel(@RequestParam(value = "menu") String menu, @RequestParam(value = "dwflglId") int dwflglId, @RequestParam(value = "qjCode") String qjCode, HttpServletResponse response) throws IOException { //内容集合 List<ZjlrysIndexView> jthz = getJthz(dwflglId, qjCode); //表头集合 List<ZjlrysTableHead> header = getHeaderOfHz(dwflglId, qjCode); response.setHeader("Content-Disposition", "attachment; filename=Zjlryshz.xlsx"); // 响应类型,编码 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); String bigTitle = "资金流入预算表"; EasyExcel.write(response.getOutputStream()).head(getExcelHeader(header, bigTitle)).registerWriteHandler(new Custemhandler()).sheet("资金流入预算导出模板").doWrite(getExportData(jthz)); }
通过getExcelHeader(header, bigTitle)得到表头集合
private List<List<String>> getExcelHeader(List<ZjlrysTableHead> header, String bigTitle) { List<List<String>> head = new ArrayList<>(); List<String> head0 = new ArrayList<>(); head0.add(bigTitle); head0.add("资金项目"); head.add(head0); head0 = new ArrayList<>(); head0.add(bigTitle); head0.add("行次"); head.add(head0); for (var h : header) { head0 = new ArrayList<>(); head0.add(bigTitle); head0.add(h.getName()); head.add(head0); } return head; }
多级表头
private List<List<String>> getExcelHeader(String bigTitle, String nsrsbh, String ssyf) { List<List<String>> head = new ArrayList<>(); head.add(Arrays.asList(bigTitle, "纳税人识别号:", "序号")); head.add(Arrays.asList(bigTitle, nsrsbh, "发票代码")); head.add(Arrays.asList(bigTitle, "", "发票号码")); head.add(Arrays.asList(bigTitle, "", "开票日期")); head.add(Arrays.asList(bigTitle, "", "销方税号")); head.add(Arrays.asList(bigTitle, "", "销方名称")); head.add(Arrays.asList(bigTitle, "所属月份:", "金额")); head.add(Arrays.asList(bigTitle, ssyf, "税额")); head.add(Arrays.asList(bigTitle, "", "有效税额")); head.add(Arrays.asList(bigTitle, "", "勾选日期")); head.add(Arrays.asList(bigTitle, "", "发票类型")); head.add(Arrays.asList(bigTitle, "", "用途")); head.add(Arrays.asList(bigTitle, "", "发票状态")); head.add(Arrays.asList(bigTitle, "", "管理状态")); head.add(Arrays.asList(bigTitle, "单位:元", "信息来源")); return head; }
效果
上图的表头阔度不是下面的的自适应代码。
如果想通过实体类来设置二级表头,可以通过@ExcelProperty(value={"一级表头","二级表头"}),多级表头以此类推
EasyExcel.write(response.getOutputStream(), Download.class).sheet("导出模板").doWrite(data(byZtId));
通过调用registerWriteHandler来设置表格样式,我这里设置只是设置表头的自适应宽度,创建一个类来继承AbstractColumnWidthStyleStrategy抽象类
package cn.xxxx.xxxx.xxx.utils; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import org.apache.poi.ss.usermodel.Cell; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; public class Custemhandler extends AbstractColumnWidthStyleStrategy { private static final int MAX_COLUMN_WIDTH = 255; //the maximum column width in Excel is 255 characters public Custemhandler() { } @Override protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { if (isHead && cell.getRowIndex() != 0) { int columnWidth = cell.getStringCellValue().getBytes().length; if (columnWidth > MAX_COLUMN_WIDTH) { columnWidth = MAX_COLUMN_WIDTH; } else { columnWidth = columnWidth + 3; } writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256); } } private final static Logger logger = LoggerFactory.getLogger(Custemhandler.class); }
最后在doWrite()里面放要导出的数据即可
private List<List<String>> getExportData(List<ZjlrysIndexView> jthz) { List<List<String>> sumList = new ArrayList<>(); for (var row : jthz) { List<String> list = new ArrayList<>(); list.add(row.getZjxm()); list.add(String.valueOf(row.getZbY())); for (var xm : row.getZjlrysXms()) { if (xm.getId() == null) { list.add(""); } else { if (xm.getZjlrysb().getXsValue() == null || xm.getZjlrysb().getXsValue().compareTo(new BigDecimal("0")) == 0) { list.add(""); } else { list.add(xm.getZjlrysb().getXsValue().toString()); } } } sumList.add(list); } return sumList; }
总结
(1)表头的List<List<String>>,最外面的List是一列单元格的表头,里面的List的每一个元素代表这一列的每一行表头
(2)数据的List<List<String>>,最外面的List是每一行的数据,里面的List放一行每一列的数据。
参考链接: