如何用EasyExcel轻松实现单元格的个性化导出?(上)

155 阅读3分钟

前言

近期,笔者面临一项新的需求:实现一个自定义表格导出功能,该功能能够将Excel文件的样式与用户自定义的表格样式相匹配。在评估了多种工具后,决定采用easyExcel来完成这项任务。然而,笔者发现easyExcel的官方示例并未涵盖一些关键功能,例如使用RGB值来分别设置单元格的背景和字体颜色。

通过广泛的研究和实践,终于找到了解决方案。现在,笔者将分享一段实用的代码示例,供您参考。请注意,这仅是一个参考示例,具体的实现可能需要根据您的具体需求进行调整。

依赖

 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>easyexcel</artifactId>
     <version>2.1.6</version>
 </dependency>
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>3.17</version>
 </dependency>
 ​
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml-schemas</artifactId>
     <version>3.17</version>
 </dependency>
 ​
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi</artifactId>
     <version>3.17</version>
 </dependency>
 <dependency>
     <groupId>commons-collections</groupId>
     <artifactId>commons-collections</artifactId>
     <version>3.2.2</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.83</version>
 </dependency>
 <dependency>
     <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
     <version>5.8.16</version>
 </dependency>

示例

 public class TestFileUtil {
     public static String getPath(){
         return "D:\testExcel\";
     }
 }
 ​
 @Test
 public void customHandlerWrite() {
     String fileName = TestFileUtil.getPath() + "customHandlerWrite" + ".xlsx";
     // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
     EasyExcel.write(fileName)
         // 富文本 不加这个会导致字体样式失效
         .inMemory(true) 
         .registerWriteHandler(new CustomCellWriteHandler())
         .registerWriteHandler(new ColumnStyleStrategy())
         .registerWriteHandler(new RowStyleStrategy())
         .sheet("模板")
         .doWrite(dataList());
 }
 ​
 private List<List<Object>> dataList() {
     List<List<Object>> list = new ArrayList<List<Object>>();
     for (int i = 0; i < 10; i++) {
         List<Object> data = new ArrayList<Object>();
         data.add("字符串");
         if (i % 3 != 0) {
             data.add(new Date());
             data.add(0.56);
         } else {
             data.add("字符串");
             data.add("");
         }
         list.add(data);
     }
     return list;
 }
 /**
  * 自定义拦截器。
  *
  */
 public class CustomCellWriteHandler implements CellWriteHandler {
 ​
     private static final Logger LOGGER = LoggerFactory.getLogger(CustomCellWriteHandler.class);
 ​
     @Override
     public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                                  Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
 ​
     }
 ​
     @Override
     public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                 Head head, Integer relativeRowIndex, Boolean isHead) {
 ​
     }
 ​
     @Override
     public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                  List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
         // 这里可以对cell进行任何操作
         LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
         
         // 筛选单元格
         if (cell.getRowIndex() > 0) {
             // 拿到poi的workbook
             // 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式
             // 不同单元格尽量传同一个 cellStyle
             Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
             CellStyle cellStyle = workbook.createCellStyle();
 ​
             // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
             cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
 ​
             //设置rgb颜色
             byte[] bgRgb = new byte[]{(byte) 57, 126, (byte) 240};
             // 设置居中
             cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
             cellStyle.setAlignment(HorizontalAlignment.CENTER);
             XSSFCellStyle xssfCellColorStyle = (XSSFCellStyle) cellStyle;
             xssfCellColorStyle.setFillForegroundColor(new XSSFColor(bgRgb, null));
 ​
             cell.setCellStyle(xssfCellColorStyle);
 ​
 //            // 设置字体RGB颜色
             cell.setCellType(CellType.STRING);
             String stringCellValue = cell.getStringCellValue();
             XSSFRichTextString richString = new XSSFRichTextString(cell.getStringCellValue());
             Font font = workbook.createFont();
             byte[] ftRgb = new byte[]{(byte) 255, 0, 0};
 ​
             XSSFFont xssfFont = (XSSFFont) font;
             xssfFont.setColor(new XSSFColor(ftRgb, null));
             // 设置字体大小
             BigDecimal fonsize = new BigDecimal("16.5").divide(new BigDecimal("1.5")).multiply(new BigDecimal("2"));
             font.setFontHeightInPoints(Short.parseShort(fonsize.toString()));
             // 设置粗体
             font.setBold(true);
 ​
             // 从哪到哪,你想设置成什么样的字体都行startIndex,endIndex,这里设置全部
             richString.applyFont(0, stringCellValue.length(), xssfFont);
             // 再设置回每个单元格里
             cell.setCellValue(richString);
         }
     }
 }
 public class ColumnStyleStrategy extends AbstractColumnWidthStyleStrategy {
     @Override
     protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
         Sheet sheet = writeSheetHolder.getSheet();
         int columnIndex = cell.getColumnIndex();
         if(columnIndex >= 1){
             // 列宽
             sheet.setColumnWidth(columnIndex, 9000);
         }else {
             // 列宽
             sheet.setColumnWidth(columnIndex, 3000);
         }
     }
 }
 public class RowStyleStrategy extends AbstractRowHeightStyleStrategy {
     @Override
     // 头行高
     protected void setHeadColumnHeight(Row row, int i) {
         int rowNum = row.getRowNum();
         row.setHeightInPoints(36f);
     }
     @Override
     // 内容行高
     protected void setContentColumnHeight(Row row, int i) {
         int rowNum = row.getRowNum();
         if(rowNum%2==0){
             row.setHeightInPoints(72f);
         }
     }
 }

效果如下所示

image.png

后言

此文仅为示例,后续会在需求完成后更新更完整的版本。