利用easyexcel生成excel文件-自定义单元格格式及样式
By:Roy.LiuLast updated:2020-12-03
前面测试了用easyexcel生成复杂的多表头excel文件,但如果用过POI的都知道,POI 是自己手动写代码生成CELL单元格,可以很灵活的设置样式及格式。在easyexcel中怎么实现呢?easyexcel提供了 CellWriteHandler 接口,但一般处理单元格的时候,是可以直接继承 bstractCellWriteHandler 来处理的,其实前面提到的动态定制多表头的列的宽度,就是一种实现,也是实现writehandler接口来实现的。
要定制化cell单元格样式及格式,最重要的方法就是去实现 afterCellDispose 这个方法的逻辑, 在前面测试导出订单的测试中,单价,数量,总金额应该是保存两位小数,并把背景色设置为天蓝色。效果如下:
实现如下效果的代码如下,其中重点关注就是 CustomCellWriteHandler 类。
package com.yihaomen.myexcel; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.AbstractCellWriteHandler; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import com.yihaomen.myexcel.domain.Detail; import com.yihaomen.myexcel.domain.Master; import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.ss.usermodel.*; import org.junit.Before; import org.junit.Test; import org.springframework.boot.test.context.SpringBootTest; import sun.security.x509.CertAttrSet; import java.io.File; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; @SpringBootTest public class WriteExcel_1 { private Master master; private List<Detail> details = new ArrayList<>(); /** * 初始化测试数据 */ @Before public void initData() { master = new Master(); master.setCustomer("特朗普集团"); master.setSheetNo("SO2020000011111"); master.setCreatedDate(new Date()); for(int i=0; i<100; i++) { Detail d = new Detail(); d.setProductId("product:" + i); d.setProductName("产品:" + i); d.setPrice(new BigDecimal("26.80")); d.setNumber(new BigDecimal("20.5")); d.setAmount(d.getPrice().multiply(d.getNumber())); d.setMemo("备注产品:" + i); details.add(d); } } /** * 仅仅输出明细数据到excel文件 */ @Test public void writeSimpleExcelForDetail() { String path = this.getClass().getResource("/").getPath(); System.out.println(path); String fileName = path + File.separator + "writeSimpleExcel.xlsx"; // 这里 需要指定写用哪个class去写,指定模板名称及数据 EasyExcel.write(fileName, Detail.class).sheet("sheet名称").doWrite(details); } /** * 仅仅输出明细数据到excel文件, 排除部分字段 */ @Test public void writeSimpleExcelExculdeColumns() { String path = this.getClass().getResource("/").getPath(); List<String> excludeColumns = new ArrayList<>(); excludeColumns.add("memo"); String fileName = path + File.separator + "writeSimpleExcel.xlsx"; // 这里 需要指定写用哪个class去写,指定模板名称及数据 EasyExcel.write(fileName, Detail.class).excludeColumnFiledNames(excludeColumns).sheet("sheet名称").doWrite(details); } /** * 仅仅输出明细数据到excel文件, 增加自定义的头部 */ @Test public void writeSimpleExcelWithHeader() { String path = this.getClass().getResource("/").getPath(); String fileName = path + File.separator + "writeSimpleExcel.xlsx"; // 准备 HEADER List<List<String>> list = getHeader(); // 这里 需要指定写用哪个class去写,指定模板名称及数据 EasyExcel.write(fileName).head(list) .registerWriteHandler(getStyleStrategy()) .registerWriteHandler(new CustomCellWriteHandler()) .sheet("sheet名称").doWrite(details); } private List<List<String>> getHeader() { /** * 打算展示成如下样子 * |客户:xxx 公司 (这一行需要合并单元格) * |单号: SO22222222222222| 日期: 2020-01-01 (分别需要合并单元格) * |产品ID|产品名称|价格|数量|总金额|备注| */ String customer = "客户: " + master.getCustomer(); String sheetNo = "单号: " + master.getSheetNo(); String dateStr = "日期: " + master.getCreatedDate(); List<List<String>> list = new ArrayList<List<String>>(); List<String> head0 = new ArrayList<String>(); head0.add(customer); head0.add(sheetNo); head0.add("产品ID"); List<String> head1 = new ArrayList<String>(); head1.add(customer); head1.add(sheetNo); head1.add("产品名称"); List<String> head2 = new ArrayList<String>(); head2.add(customer); head2.add(sheetNo); head2.add("价格"); List<String> head3 = new ArrayList<String>(); head3.add(customer); head3.add(sheetNo); head3.add("数量"); List<String> head4 = new ArrayList<String>(); head4.add(customer); head4.add(dateStr); head4.add("总金额"); List<String> head5 = new ArrayList<String>(); head5.add(customer); head5.add(dateStr); head5.add("备注"); list.add(head0); list.add(head1); list.add(head2); list.add(head3); list.add(head4); list.add(head5); return list; } private HorizontalCellStyleStrategy getStyleStrategy() { // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 设置对齐 headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); // 背景色, 设置为白色,也是默认颜色 headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); // 字体 WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short) 12); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 // contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 背景绿色 //contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); // 字体策略 WriteFont contentWriteFont = new WriteFont(); contentWriteFont.setFontHeightInPoints((short) 12); contentWriteCellStyle.setWriteFont(contentWriteFont); //设置 自动换行 contentWriteCellStyle.setWrapped(true); //设置 垂直居中 contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //设置 水平居中 // contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); //设置边框样式 contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); contentWriteCellStyle.setBorderTop(BorderStyle.THIN); contentWriteCellStyle.setBorderRight(BorderStyle.THIN); contentWriteCellStyle.setBorderBottom(BorderStyle.THIN); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); return horizontalCellStyleStrategy; } class CustomCellWriteHandler extends AbstractCellWriteHandler { @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { // 设置行高测试 int rowIndex = row.getRowNum(); System.out.println("当前行: " + rowIndex); short height = 600; row.setHeight(height); } @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { int rowIndex = cell.getRowIndex(); int cellIndex = cell.getColumnIndex(); // 自定义宽度处理 if (isHead && cell.getRowIndex() == 2) { int columnWidth = cell.getStringCellValue().getBytes().length; switch (cellIndex) { case 0: case 2: case 3: columnWidth = 10; break; case 1: columnWidth = 25; break; case 4: columnWidth = 15; break; case 5: columnWidth = 50; break; default: break; } if (columnWidth > 255) { columnWidth = 255; } writeSheetHolder.getSheet().setColumnWidth(cellIndex, columnWidth * 256); } // 自定义样式处理 if (rowIndex >= 3) { switch (cellIndex) { case 2: case 3: case 4: CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle(); cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.index); cellStyle.setFillBackgroundColor(IndexedColors.WHITE.index); cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); cellStyle.setBorderLeft(BorderStyle.THIN); cellStyle.setBorderTop(BorderStyle.THIN); cellStyle.setBorderRight(BorderStyle.THIN); cellStyle.setBorderBottom(BorderStyle.THIN); DataFormat dataFormat = cell.getSheet().getWorkbook().createDataFormat(); cellStyle.setDataFormat(dataFormat.getFormat("0.00")); cell.setCellStyle(cellStyle); System.out.println("set cell style"); break; default: break; } } } } }
From:一号门
COMMENTS