EasyExcel修改表头样式(POI样式)与设置渐变色

737 阅读2分钟

先上代码

main方法代码

EasyExcel.write()
       .file(Files.newOutputStream(Paths.get("test.xlsx"))).sheet("sheet1")
       .registerWriteHandler(new CellStyleWriteHandler())
       .head(new ArrayList<List<String>>() {{
          add(Collections.singletonList("ID"));
          add(Collections.singletonList("Name"));
       }})
       .doWrite(new ArrayList<List<String>>() {{
          add(Arrays.asList("123", "789"));
          add(Arrays.asList("465", "987"));
       }});

CellStyleWriteHandler类代码

import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTGradientFill;

public class CellStyleWriteHandler implements CellWriteHandler {

    private XSSFCellStyle headCellStyle = null;
    private XSSFCellStyle contentCellStyle = null;

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
       Sheet sheet = context.getWriteSheetHolder().getSheet();
       Cell cell = context.getCell();
       // 拿到poi的workbook
       Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
       if (!BooleanUtils.isNotTrue(context.getHead())) {
          if (Utils.isEmpty(headCellStyle)) {
             //设置首行冻结
             sheet.createFreezePane(0, 1, 0, 1);
             // 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式
             // 不同单元格尽量传同一个 cellStyle
             headCellStyle = (XSSFCellStyle) workbook.createCellStyle();
             // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
             headCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
             Font cellFont = workbook.createFont();
             cellFont.setFontName("Arial");
             cellFont.setBold(true);
             cellFont.setFontHeightInPoints((short) 10);
             headCellStyle.setFont(cellFont);
             // 水平居中
             headCellStyle.setAlignment(HorizontalAlignment.CENTER);
             //垂直居中
             headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
             //自动换行
             headCellStyle.setWrapText(true);
             //边框
             headCellStyle.setBorderLeft(BorderStyle.MEDIUM);
             headCellStyle.setBorderRight(BorderStyle.MEDIUM);
             headCellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex());
             headCellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex());

             //设置渐变色
             //get fill index used in this CellStyle
             int fillIdx = (int) headCellStyle.getCoreXf().getFillId();

             //get the low level CTFill used in this CellStyle
             CTFill ctfill = ((SXSSFWorkbook) workbook).getXSSFWorkbook().getStylesSource().getFillAt(fillIdx).getCTFill();

             //unset the pattern fill
             ctfill.unsetPatternFill();

             CTGradientFill ctgradientfill = ctfill.addNewGradientFill();
             ctgradientfill.setDegree(90.0);
             ctgradientfill.addNewStop().setPosition(0.0);
             ctgradientfill.getStopArray(0).addNewColor().setRgb(new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF});
             ctgradientfill.addNewStop().setPosition(1);
             ctgradientfill.getStopArray(1).addNewColor().setRgb(new byte[]{(byte) 0xF3, (byte) 0xDD, (byte) 0xDC});
          }
          cell.setCellStyle(headCellStyle);
          //设置首行行高
          cell.getRow().setHeight((short) (20 * 20));
          //设置列宽
          sheet.setColumnWidth(cell.getColumnIndex(), (int) (14.5 * 256));

          // 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到
          // cell里面去 会导致自己设置的不一样
          context.getFirstCellData().setWriteCellStyle(null);
       } else {
          //设置内容行高
          cell.getRow().setHeight((short) (13 * 20));
          if (Utils.isEmpty(contentCellStyle)) {
             contentCellStyle = (XSSFCellStyle) workbook.createCellStyle();
             Font cellFont = workbook.createFont();
             cellFont.setFontName("Arial");
             cellFont.setFontHeightInPoints((short) 9);
             contentCellStyle.setFont(cellFont);
             //垂直居中
             contentCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
             //自动换行
             contentCellStyle.setWrapText(true);
          }
          cell.setCellStyle(contentCellStyle);
          //设置内容行高
          cell.getRow().setHeight((short) (12.5 * 20));
       }
    }
}

最终效果

image.png

pom依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.4</version>
</dependency>

常见问题

main方法中主要注意第三行的registerWriteHandler方法、这里注入的CellStyleWriteHandler中实现了单元格样式的配置、具体使用方式请参考EasyExcel官方文档

表头样式不生效

注意查看你是否缺少CellStyleWriteHandler类第73行代码、这里的代码用于清空EasyExcel默认表头样式。

CTFill类找不到

检查pom文件是否引入了ooxml-schemas、具体详情请参考这篇文章java - Apache poi 将渐变颜色应用于单元格 - 堆栈溢出 (stackoverflow.com)

为何记录本文

  1. 再做修改表头背景色时虽然看过EasyExcel官网、但是发现只能用IndexedColors、最后掉入POI样式不生效的坑、在里面挣扎了一天、找了各种写法、最后还是在官方文档中找到解决方案、需要使用context.getFirstCellData().setWriteCellStyle(null);去除默认样式、第一次看文档时其实已经快看到这了、往下多翻几行就是。所以在这里记录一下、希望各位引以为戒。
  2. 关于使用POI实现渐变背景色、试了几个AI发现都是在乱回答、百度也搜不到准确的结果、最后还是用bing国际版用英文关键词poi Gradient excel才搜到结果、希望这篇文章能收录到国内搜索引里吧、顺便喂给AI、让未来有同样需求的兄弟们少走点弯路。