【问题标题】:How to save excel with formula in Apache Poi?如何在 Apache Poi 中使用公式保存 excel?
【发布时间】:2020-06-30 20:13:52
【问题描述】:

如果有一个带有公式的单元格并保存文件,那么手动关闭文件后,excel会要求保存更改?如何从程序中完全保存文件,因为没有这种保存,我无法通过读取文件获得正确的值。

当前文件保存:

        File file = new File("Test.xlsx");
        FileOutputStream out;
        try {
            out = new FileOutputStream(file);
            workbook.write(out);
            workbook.close();
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

公式更新:

        XSSFFormulaEvaluator.evaluateAllFormulaCells(workbook);
        workbook.setForceFormulaRecalculation(true);

公式:

XSSFCell irrCell = row1.createCell(0);
irrCell.setCellFormula("IFERROR(IRR(A2:C2),0)");

文件读取:

        try {
            workbook = new XSSFWorkbook(file);
            System.out.println(workbook.getSheetAt(0).getRow(0).getCell(0).getNumericCellValue());
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }

单元格值:-20000000、-1000、2399000

程序公式单元格值:0,文件公式单元格值:-0,653687014

【问题讨论】:

    标签: java excel apache-poi


    【解决方案1】:

    这是Microsoft 不遵守自己规则的情况之一。 IRR function 告诉:

    Microsoft Excel 使用迭代技术来计算 IRR。 从猜测开始,IRR 循环计算,直到 结果精确到 0.00001%。如果 IRR 找不到结果 在 20 次尝试后有效,#NUM!返回错误值。

    在大多数情况下,您不需要为 IRR 提供猜测 计算。如果省略guess,则假定为0.1(10 百分比)。

    这正是apache poiIRR 函数实现的。这就是为什么它会为您的数据样本获取#NUM! 错误。但Microsoft 似乎做了一些不同的事情。

    使用公式 IRR(A2:C2,-0.7),它有一个给定的 -0.7 猜测,apache poi 也能够评估 IRR 公式。

    要解决这个问题,可以按照IRR 函数描述中的说明进行操作:

    如果 IRR 给出 #NUM!错误值,或者如果结果不接近 如您所愿,请使用不同的猜测值重试。

    所以尝试从 -1.0 到 1.0 以 0.1 为步长的 guess,直到你得到一个值而不是 `#NUM!'错误。

    例子:

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    
    import org.apache.poi.ss.usermodel.*;
    
    class ExcelEvaluateIRRFunction {
     
     public static void main(String[] args) throws Exception {
      
      Workbook workbook = WorkbookFactory.create(new FileInputStream("./Excel.xlsx")); String filePath = "./ExcelNew.xlsx";
      FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
    
      Sheet sheet = workbook.getSheetAt(0);
      Row row = sheet.getRow(1); if (row == null) row = sheet.createRow(1);
      row.createCell(0).setCellValue(-20000000d);
      row.createCell(1).setCellValue(-1000d);
      row.createCell(2).setCellValue(2399000d);
    
      row = sheet.getRow(0); if (row == null) row = sheet.createRow(0);
      Cell cell = row.createCell(0);
    
      CellValue evaluatedValue = null;
      for (int i = -10; i < 10; i++) {
       double guess = i/10d;
       System.out.println(guess);
       cell.setCellFormula("IRR(A2:C2," + guess + ")");
       evaluator.clearAllCachedResultValues();
       evaluatedValue = evaluator.evaluate(cell);
       System.out.println(evaluatedValue);
       if (evaluatedValue.getCellType() != CellType.ERROR) break;
      }
    
      evaluator.evaluateFormulaCell(cell);
      System.out.println(cell.getNumericCellValue());
    
      FileOutputStream out = new FileOutputStream(filePath);
      workbook.write(out);
      out.close() ;
      workbook.close();
     }
    }
    

    另请参阅IRR in poi return NaN but correct value in excel 以获得相同问题的另一个示例。

    【讨论】: