[alibaba/easyexcel]【导出】写入表单bug

2024-06-20 980 views
7

版本号:1.1.2-beta5 主要问题:

  1. 写同一个excel文件,若使用不同的writer分次写,会报出IO Exception;
  2. 通过同一个writer,向不同的sheet对象写数据,结果全写到第一个sheet中去了。

我的场景有点复杂:

  1. 写入的表单数据会分成好几种类别,不同的类别使用不同的样式,写到不同的表单;同一个样式的数据超过行数后也需要写到下一个表单。
  2. 流程: 1)实现WriteHandler,将所有种类表单样式传入handler。 2)在整个程序的上下文中,只通过上述handler创建一次ExcelWriter。根据业务场景,当写到不同种类表单时,切换handler中的样式模板; 3)当数据超过限制,以及切换不同种类表单时,new出新的sheet,使用步骤2的ExcelWriter写入; 4) 得到的excel文件只在同一个表单

部分代码:

/**
 * 按照种类写入excel,一个种类可能会写入多个sheet表单
 *
 * @param filePath   excel文件路径
 * @param kindModels 表单种类
 * @throws FileNotFoundException 异常信息
 */
private void writeExcel(String filePath, List<SheetKindModel> kindModels) throws FileNotFoundException {
    List<List<ExcelFieldVo>> excelFieldVos = getDiffKindSheet(kindModels);

    OutputStream outputStream = new FileOutputStream(filePath);
    StringExcelHandler handler = new StringExcelHandler(excelFieldVos);
    ExcelWriter writer = new ExcelWriter(null, outputStream, ExcelTypeEnum.XLSX, true, handler);
    int kindIndex = 0;
    int sheetNum = 0;

    for (SheetKindModel sheetKindModel : kindModels) {
        if (CollectionUtils.isNotEmpty(sheetKindModel.getData())) {
            // 切换sheet种类
            handler.switchSheetKind(kindIndex);

            // 分batchNum次批量插入excel
            int batchNum = batchWriteExcel(excelFieldVos, writer, kindIndex, sheetNum, sheetKindModel);

            sheetNum += batchNum;
            kindIndex++;
        }
    }
    writer.finish();
}

private int batchWriteExcel(List<List<ExcelFieldVo>> excelFieldVos, ExcelWriter writer, int kindIndex, int sheetNum, SheetKindModel sheetKindModel) {
    List<JSONObject> rowData = sheetKindModel.getData();
    int size = rowData.size();

    // excel单张表单最多1048576行,去掉零头,1048570
    int batchNum = (int) Math.ceil((double) size / GalaxyConstant.MAX_EXCEL_NUM);

    List<List<String>> header = Lists.newArrayListWithExpectedSize(excelFieldVos.size());
    for (ExcelFieldVo excelFieldVo : excelFieldVos.get(kindIndex)) {
        header.add(Collections.singletonList(excelFieldVo.getHeaderName()));
    }

    for (int i = 0; i < batchNum; i++) {
        int startIndex = GalaxyConstant.MAX_EXCEL_NUM * i;
        int endIndex = i == (batchNum - 1) ? size : GalaxyConstant.MAX_EXCEL_NUM * (i + 1);
        List<JSONObject> batchRowData = rowData.subList(startIndex, endIndex);

        Sheet oneSheet = new Sheet(sheetNum + i, 1);
        oneSheet.setSheetName(sheetKindModel.getPrefix() + (i + 1));
        oneSheet.setHead(header);

        List<List<String>> data = Lists.newArrayListWithExpectedSize(batchRowData.size());

        for (JSONObject jsonObject : batchRowData) {
            List<String> oneRow = Lists.newArrayListWithExpectedSize(excelFieldVos.size());
            for (ExcelFieldVo excelFieldVo : excelFieldVos.get(kindIndex)) {
                oneRow.add(jsonObject.getString(excelFieldVo.getFieldAlias()));
            }
            data.add(oneRow);
        }
        writer.write0(data, oneSheet);

    }
    return batchNum;
}

结果:

image

回答

0

@jipengfei-jpf 已解决,试出来的。。。。 sheet表单中的sheetNo,0代表写第一个表单,1竟然也代表写第一个表单。。。

4

看到了同样的问题 https://github.com/alibaba/easyexcel/issues/416 poi都是从1开始的,easyexcel我看rowIndex columnIndex都是从0开始的;而表单0代表全部,1代表第一个表单,确实让人困惑。

9

这个已经在最新版本修复,所有的东西 index都是0