excel 模板 POI JAVA 中的公式重新计算

Formula recalculation in excel template POI JAVA

我有一个 Excel 模板文件,在某些单元格中包含公式,我打开它并使用 POI 填充值。问题是公式不会自动重新计算。但是,如果我打开此文件并单击具有值的单元格,它会重新计算该单元格。

我在 documentation 中找到了两种解决此问题的方法,但都没有帮助我。

重点是Excel会缓存之前计算的结果,需要触发重新计算才能更新。

  1. 使用 POI 的 FormulaEvaluator 重新评估公式

    workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();

  2. 将重新计算委托给 Excel。打开工作簿时,应用程序将执行完整的重新计算

    workbook.setForceFormulaRecalculation(true);

我的代码:

    public static String fillBook(String filename, String outFilename,  int sheetNumber, String[] params){ 
        String result = "";
        try {
            File file = new File(filename);

            Workbook workbook = null;
            workbook = WorkbookFactory.create(file);
            Sheet sheet = workbook.getSheetAt(sheetNumber);

            for (String param: params)
            {
                String[] paramArray = param.split("\u0001");
                String address = paramArray[0];
                String value;

                if (paramArray.length > 1)
                {
                    value = paramArray[1];
                } else {
                    value = "";
                }

                CellReference cellReference = new CellReference(address);
                Row row = sheet.getRow(cellReference.getRow());

                if (row == null) {
                    row = sheet.createRow(cellReference.getRow());
                }

                Cell cell = row.getCell(cellReference.getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                cell.setCellValue(value);
            }

            //workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();
            workbook.setForceFormulaRecalculation(true);

            FileOutputStream out = new FileOutputStream(outFilename);
            workbook.write(out);
            out.close();

        } catch (Exception e) {
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();

            result = e.toString() + " " + exceptionAsString;
        }
        return result;
    }

您不应在 Excel 中将所有单元格值设置为字符串值。当引用的单元格包含字符串值时,需要数值或日期值的公式将不起作用。

从您提供的代码开始,您设置的所有新值都是字符串值。因此,如果 String[] paramArray 包含“123”,例如,您将字符串“123”而不是数字 123 设置为单元格值。但是例如公式 SUM 不能对字符串求和。它仅对数值求和。因此,只有当您将其中包含“123”的单元格更改为 123 时,它才会起作用。所以将数值设置为数值。 Cell 中有一些方法可以做到这一点。 void setCellValue(double value) 例如。

日期值也是如此。这些还需要设置为单元格中的日期值,而不是简单地设置为字符串。

所以您需要一个与 String[] params 不同的对象来传递单元格值。该对象也必须能够存储数值。例如 List<Object>List<POJO>,其中 POJO 是任何一种存储信息的普通旧 Java 对象。然后使用 Cell 的不同 setCellValue 方法来设置字符串单元格值或数字单元格值或日期单元格值。

否则,在将 Cell 设置为 Cell 之前,您需要根据从 String[] params 获得的字符串创建一个数值 (double)。日期值相同 - 在将 Cell 设置为 Cell 之前,根据从 String[] params 获得的字符串创建一个日期值(CalendarLocalDateLocalDateTime)。但在我看来,这是更容易出错的方法。