Задержка записи значений в файл Excel с формулой - PullRequest
0 голосов
/ 27 апреля 2019

Вариант использования: у меня есть калькулятор стоимости, реализованный в Excel. Мне нужно вставить огромное количество входных данных для ввода в ячейки ввода на листе и получить выходные данные с того же листа. У меня есть 3 листа Excel, размером примерно 3 МБ. Листы Excel имеют формат .xlsm.

Используемые технологии: Java 1.8 и Apache POI 4.0.1

Проблема: запись входных значений в файлы Excel размером более 3 МБ выполняется быстро (около 12 секунд занимает около 12 входов). Но то же самое действие для файла Excel, который <3MB слишком медленный (~ 10 секунд только для одного ввода). </p>

Мне кажется, что некоторые люди говорят, что используют SXSSFWorkbook. Я заменил XSSFWorkbook этим, но он дает мне исключение Null Pointer. Кроме того, это используется для больших листов Excel, размер которых превышает 100 МБ, верно?

Код для ввода значений:

    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();
    }

1 Ответ

0 голосов
/ 29 апреля 2019

Следующий код открывает книгу только один раз, вместо того, чтобы открывать и закрывать ее повторно для каждого введенного значения:

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 несколькими различными методами.

...