Skip to content

[Bug] 在升级FastExcel从1.2.0到1.3.0后出现的,在处理多个sheet的Excel写入时发生了数组越界异常。 #657

@yinzhiyu-hot

Description

@yinzhiyu-hot

Search before asking

  • I searched in the issues and found nothing similar.

Fesod version

1.3.0

JDK version

1.8

Operating system

Windows 11

Steps To Reproduce

部分代码如下:

private static void writeExcelWithMultiSheet(ExcelWriter excelWriter, List<SheetConfig<?>> sheetDataList, int batchSize) {
//checkSheetConfigData(sheetDataList);

try {
    for (int sheetNo = 0, sheetDataListSize = sheetDataList.size(); sheetNo < sheetDataListSize; sheetNo++) {
        SheetConfig<?> sheetConfig = sheetDataList.get(sheetNo);
        String sheetName = sheetConfig.getSheetName();
        List dataList = sheetConfig.getDataList();
        Class<?> headClass = sheetConfig.getHeadClass();

        // 校验数据列表与表头类匹配性(包含空列表的处理)
        if (dataList.isEmpty()) {
            throw new IllegalArgumentException("数据列表不能为空");
        }
        if (!headClass.isAssignableFrom(dataList.get(0).getClass())) {
            throw new IllegalArgumentException("数据列表与表头类不匹配");
        }
        // 计算总批次数,向上取整(dataList非空,避免除零)
        int totalBatches = (dataList.size() + batchSize - 1) / batchSize;
        try {
            ExcelWriterSheetBuilder builder = FastExcel.writerSheet(sheetNo, sheetName);
            builderComponentRegister(builder);

            // 生成完整列头,支持多级表头
            List<List<String>> allHeaders = getAllHeaders(headClass, dataList);
            builder.head(allHeaders);
            WriteSheet writeSheet = builder.build();

            // 合并基础数据和动态数据
            List<List<Object>> mergedData = mergeDataWithField(headClass, dataList);

            writeData(excelWriter, writeSheet, mergedData, batchSize, totalBatches);
        } catch (Exception e) {
            log.error("写入Excel文件时发生异常,Sheet名称: {}", sheetName, e);
            throw e;
        }
    }
} finally {
    if (CLEAR.get()) {
        clear();
    }
}

}

private static void writeData(ExcelWriter excelWriter, WriteSheet writeSheet, List data, int batchSize, int totalBatches) {
if (ObjectUtil.isEmpty(data)) {
// 写入空文件数据
excelWriter.write(data, writeSheet);
} else {
for (int i = 0; i < data.size(); i += batchSize) {
// 当前批次加1
int currentBatch = (i / batchSize) + 1;
// 计算当前批次的结束索引,避免越界
int end = Math.min(i + batchSize, data.size());
// 获取当前批次的数据子集
List batchList = data.subList(i, end);
// 写入当前批次数据
excelWriter.write(batchList, writeSheet);

    }
} 

}

public static class SheetConfig {

/** Sheet名称 */
private final String sheetName;

/** 数据列表 */
private final List<T> dataList;

/** 表头类 */
private final Class<T> headClass;

/**
 * 构造函数,初始化Sheet配置信息
 * @remark 通过指定Sheet名称、数据列表和表头类来创建一个Sheet配置实例
 * @param sheetName  Sheet的名称
 * @param dataList   数据列表,包含要写入Sheet的数据
 * @param headClass  表头对应的Class类型,用于定义数据结构
 **/
public SheetConfig(String sheetName, List<T> dataList, Class<T> headClass) {
    this.sheetName = sheetName;
    this.dataList = dataList;
    this.headClass = headClass;
}

/**
 * 获取Sheet名称
 * @remark 返回当前Sheet配置的名称
 * @return String Sheet名称
 **/
public String getSheetName() {
    return sheetName;
}

/**
 * 获取数据列表
 * @remark 返回当前Sheet配置中的数据列表
 * @return List<T> 数据列表
 **/
public List<T> getDataList() {
    return dataList;
}

/**
 * 获取表头类
 * @remark 返回当前Sheet配置中定义的表头类
 * @return Class<T> 表头类
 **/
public Class<T> getHeadClass() {
    return headClass;
}

}

Current Behavior

Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:424)
at java.util.ArrayList.remove(ArrayList.java:501)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.setSheetOrder(XSSFWorkbook.java:1736)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.setSheetOrder(SXSSFWorkbook.java:623)
at cn.idev.excel.write.handler.impl.WriteSheetWorkbookWriteHandler.afterWorkbookDispose(WriteSheetWorkbookWriteHandler.java:48)
at cn.idev.excel.write.handler.WorkbookWriteHandler.afterWorkbookDispose(WorkbookWriteHandler.java:49)
at cn.idev.excel.write.handler.chain.WorkbookHandlerExecutionChain.afterWorkbookDispose(WorkbookHandlerExecutionChain.java:47)
at cn.idev.excel.write.handler.chain.WorkbookHandlerExecutionChain.afterWorkbookDispose(WorkbookHandlerExecutionChain.java:49)
at cn.idev.excel.util.WriteHandlerUtils.afterWorkbookDispose(WriteHandlerUtils.java:71)
at cn.idev.excel.context.WriteContextImpl.finish(WriteContextImpl.java:457)
at cn.idev.excel.write.ExcelBuilderImpl.finish(ExcelBuilderImpl.java:97)
at cn.idev.excel.ExcelWriter.finish(ExcelWriter.java:140)
at cn.idev.excel.ExcelWriter.close(ExcelWriter.java:155)
at cn.sample.base.common.utils.FastExcelUtils.writeExcelWithMultiSheet(FastExcelUtils.java:1369)

Expected Behavior

写入文件成功

Anything else?

No response

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationgood first issueGood for newcomersquestionFurther information is requested

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions