0

用例:我有一个用 excel 实现的成本计算器。我必须在工作表的输入单元格中插入大量输入,并从同一个工作表中获取输出。我有 3 张类似的 excel 表,大小约为 3MB。excel 工作表为 .xlsm 格式。

使用的技术:Java 1.8 和 Apache POI 4.0.1

问题:将输入值写入大于 3MB 的 excel 文件非常快(大约 12 次输入大约需要 10 秒)。但是对 <3MB 的 excel 文件执行相同的操作太慢(仅一个输入约 10 秒)。

我似乎有些人在这里说要使用 SXSSFWorkbook。我用它替换了 XSSFWorkbook,但它给了我空指针异常。此外,这用于 100MB 以上的大型 Excel 工作表,对吗?

写入值的代码:

    public void setData1(String filePath, String sheetName, int rowNum, int colNum, Object data) throws IOException {
        File file = new File(filePath); 
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            Messages.terminate(file.getName() + " file is missing.");
        }
        Workbook workbook = new XSSFWorkbook(fis);
        Sheet sheet = workbook.getSheet(sheetName);
        Row row = sheet.getRow(rowNum);
        Cell cell = row.getCell(colNum);
        if(data instanceof Integer) {
            cell.setCellValue((int)data);
        }
        else if (data instanceof String) {
            cell.setCellValue(String.valueOf((String) data));
        }
        else if(data instanceof Double) {
            if((double)data == Math.floor((double)data)) {
                cell.setCellValue((int)Math.floor((double)data));
            }
            else {
                cell.setCellValue((double)data);
            }
        }
        FileOutputStream fos = new FileOutputStream(new File(filePath));
        BaseFormulaEvaluator.evaluateAllFormulaCells(workbook);
        workbook.write(fos);
        workbook.close();
        fos.close();
        fis.close();
    }
4

1 回答 1

0

以下代码仅打开工作簿一次,而不是为输入的每个值重复打开和关闭它:

public void setData1(Workbook workbook, FileOutputStream fos, String filePath, String sheetName, int rowNum, int colNum, Object data) throws IOException {
    Sheet sheet = workbook.getSheet(sheetName);
    Row row = sheet.getRow(rowNum);
    Cell cell = row.getCell(colNum);
    if(data instanceof Integer) {
        cell.setCellValue((int)data);
    }
    else if (data instanceof String) {
        cell.setCellValue(String.valueOf((String) data));
    }
    else if(data instanceof Double) {
        if((double)data == Math.floor((double)data)) {
            cell.setCellValue((int)Math.floor((double)data));
        }
        else {
            cell.setCellValue((double)data);
        }
    }
    BaseFormulaEvaluator.evaluateAllFormulaCells(workbook); //I don't have enough context here, but if it does not cause any logical problems, move this line to *
    workbook.write(fos);
}

public void callsSetData1() {
    object Data = new Object()
    File file = new File(filePath); 
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(file);
    } catch (FileNotFoundException e) {
        Messages.terminate(file.getName() + " file is missing.");
    }
    Workbook workbook = new XSSFWorkbook(fis);
    FileOutputStream fos = new FileOutputStream(new File(filePath));
    //*
    for(i = 0; i < 10; i++) {
        setData1(workbook, fos, "R:\andom\File\Path", "randomSheetName",0,0, data); //I'm assuming you are calling setData1() multiple times, as I do not have the code of the method that calls it, I've just used a for-loop for now
    }
    workbook.close();
    fos.close();
    fis.close();
}

我建议您还提供您调用的方法的代码setData1。由于我没有那个,callsSetData1可能包含一些逻辑错误。

关键是您应该只在调用的方法中打开和关闭工作簿一次,setData1并将其作为参数传递。这应该有助于延迟。

setData1唯一的小缺点是,如果您调用多个不同的方法,您将有更多的代码行。

于 2019-04-29T14:57:04.190 回答