导出Excel需要增加一个错误列, 通用类SheetWriteHandler

背景

如题

在业务中经常遇到这样的需求, 上传excel后对数据进行校验, 如果校验不通过, 需要提供excel下载, 并在后面一列提供错误原因.

常见的做法是在导出的方法中, 加一个字段然后在list中, 然后sheet写到返回流中. 但是如果需要统一样式就比较麻烦, 且每次都需要写这么一串代码.

SheetWriteHandler

我使用的阿里的EasyExcel. 它提供了一个处理器来处理sheet, 相当于拦截器


/**
 * intercepts handle sheet creation
 *
 * @author Jiaju Zhuang
 */
public interface SheetWriteHandler extends WriteHandler {
   

    /**
     * Called before create the sheet
     *
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder);

    /**
     * Called after the sheet is created
     *
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder);
}

于是我们可以在afterSheetCreate方法中做文章, 统一做处理, 包括实现其他的功能

写一个类来实现这个处理器


/**
 * 自定义拦截器.新增注释,第一行头加批注
 *
 */
@Slf4j
public class AddErrColWriteHandler implements SheetWriteHandler {
   

    /**
     * 第几行
     */
    private final Integer headIdx;

    private Integer colIdx;

    private final String errTitle;

    private Map<Integer, String> errMap;

    /**
     * @param headIdx 标题行,为了符合easyexcel的习惯,下标从1开始
     * @param colIdx  错误所在列. 下标从0开始. 如果没指定,自动取标题行的下一列
     * @param errTitle
     * @param errMap    错误信息,key是内容list的下标(为了方便list遍历时传值),最终它的行是 headIdx+errMap+1
     */
    public AddErrColWriteHandler(Integer headIdx, Integer colIdx, String errTitle, Map<Integer, String> errMap) {
   
        this.headIdx = headIdx-1;
        this.colIdx = colIdx;
        this.errTitle = errTitle;
        this.errMap = errMap;
    }

    /**
     * @param headIdx 标题行,为了符合easyexcel的习惯,下标从1开始
     * @param errTitle
     * @param errMap    错误信息,key是内容list的下标,从0开始(为了方便list遍历时传值),最终它的行是 headIdx+errMap+1
     */
    public AddErrColWriteHandler(Integer headIdx, String errTitle, Map<Integer, String> errMap) {
   
        this.headIdx = headIdx-1;
        this.errTitle = errTitle;
        this.errMap = errMap;
    }

    /**
     * 表格样式
     */
    private CellStyle cellStyle;
    private CellStyle cellStyleHeader;



    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
   

    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
   
        Row row = writeSheetHolder.getCachedSheet().getRow(headIdx);
        if (row == null) {
   
            row =  writeSheetHolder.getCachedSheet().createRow(headIdx);
        }
        if (colIdx == null){
   
            short lastCellNum = row.getLastCellNum();
            colIdx = (int) lastCellNum;
        }
        Cell cell = row.getCell(colIdx);
        if (cell == null) {
   
            cell = row.createCell(colIdx);
        }
        Workbook workbook = writeWorkbookHolder.getWorkbook();
        // 表头样式
        if (cellStyleHeader == null) {
   
            cellStyleHeader = workbook.createCellStyle();
            cellStyleHeader.setAlignment(HorizontalAlignment.CENTER);
            cellStyleHeader.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyleHeader.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            Font font = workbook.createFont();
            font.setFontName("微软雅黑");
            font.setColor((short) 10);
            font.setFontHeightInPoints((short) 12);
            cellStyleHeader.setFont(font);
        }
        cell.setCellStyle(cellStyleHeader);
        cell.setCellValue(errTitle);
        // 内容样式
        if (cellStyle == null) {
   
            cellStyle = workbook.createCellStyle();
//            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            Font font = workbook.createFont();
            font.setFontName("微软雅黑");
            font.setFontHeightInPoints((short) 12);
            cellStyle.setFont(font);
        }
        Sheet sheet = writeSheetHolder.getCachedSheet();
        for (Map.Entry<Integer, String> en : errMap.entrySet()) {
   
            int rowIdx = en.getKey() + headIdx + 1;
            Row row0 = sheet.getRow(rowIdx);
            if (row0 == null) {
   
                row0 = sheet.createRow(rowIdx);
            }
            // 第几列。我这里是1.正常业务根据需求传递
            Cell cell0 = row0.getCell(colIdx);
            if (cell0 == null) {
   
                cell0 = row0.createCell(colIdx);
            }
            cell0.setCellStyle(cellStyle);
            cell0.setCellValue(en.getValue());
        }
    }
}

使用

//在生成导出的数据list方法中
Map<Integer, String> errMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
   
	if(错误){
   
		errMap.put(i, errmsg);
	}

}


/**
   * @param title    错误列的标题名
   * @param headIdx  标题所在行,为了符合easyexcel的习惯,下标从1开始
   * @param errMsgMap 错误信息,key是内容list的下标,从0开始(为了方便list遍历时传值),最终它的行是 headIdx+errMap+1
*/

 EasyExcel.write(os)
                .withTemplate(is)
                .registerWriteHandler(new AddErrColWriteHandler(headIdx,title,errMsgMap))
                .sheet()
                .doWrite(new ArrayList());
    }));

相关推荐

  1. Excel表格导入/导出数据工具

    2023-12-06 19:52:01       30 阅读
  2. easy-poi实现动态(标题)、多sheet导出excel

    2023-12-06 19:52:01       24 阅读
  3. Android Studio导出Excel一些感悟

    2023-12-06 19:52:01       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-06 19:52:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-06 19:52:01       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-06 19:52:01       82 阅读
  4. Python语言-面向对象

    2023-12-06 19:52:01       91 阅读

热门阅读

  1. Curl 命令方式对elasticsearch备份和恢复

    2023-12-06 19:52:01       55 阅读
  2. OD机考真题搜集:矩阵中非1的元素个数

    2023-12-06 19:52:01       61 阅读
  3. Linux 定时关机 crontab

    2023-12-06 19:52:01       57 阅读
  4. UDP的特点及应用场景

    2023-12-06 19:52:01       57 阅读
  5. Python-元组详解

    2023-12-06 19:52:01       57 阅读
  6. 0X04

    0X04

    2023-12-06 19:52:01      43 阅读
  7. Springboot resource 下的excel

    2023-12-06 19:52:01       58 阅读
  8. OpenCV 使用方形棋盘进行相机校准

    2023-12-06 19:52:01       47 阅读
  9. MySQL海量数据配置优化教程

    2023-12-06 19:52:01       51 阅读
  10. Django rest froamwork-ModelSerializer

    2023-12-06 19:52:01       53 阅读