当前位置: 首页 > 知识库问答 >
问题:

在Excel(XLSX)中聚焦并确认公式后,才计算公式单元格

红存
2023-03-14

因此,我使用Apache POI(在最新的稳定版本5.0.0中使用poi-ooxml),并打开一个现有的Excel(XSLX)文件进行编辑(它基本上是一个模板文件,用于填充其他数据)。我添加了多行新数据并再次导出Excel。所有的工作都很好,只要我只添加规则的内容单元格。

现在,我有一列想要添加一个公式单元格,我使用以下代码(对于本例,您可以放心,它通常编译/运行并在末尾生成一个填充的Excel文件)来执行此操作:

File excelFileToRead = new File(<some filename here>);
InputStream inp = new FileInputStream(excelFileToRead);
Workbook wb = WorkbookFactory.create(inp);
Sheet sheet = wb.getSheetAt(0);
Row dateRangeRow = sheet.getRow(0);

// fill first cell with some date
Cell cell = row.getCell(0);
if(cell == null) row.createCell(0)
Date someDate = new Date();
cell.setCellValue(someDate);

// add formula to second cell to display the week number
Cell formCell = row.getCell(1);
if(formCell == null) row.createCell(1);
String columnName = CellReference.convertNumToColString(cell);
cell.setCellFormula("WEEKNUM(" + columnName + (cell.getRowIndex()+1) + ")");

// evaluate all formula fields before saving
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);

//some routine to save as a file follows here, not exactly relevant here

当我简单地单击Excel中的fomula编辑器并再次移除焦点时,它会正确地计算公式,单元格显示正确的周数。

以前我读过的Excel中的已有公式有一些问题,当我将数据添加到工作表中时,它们没有更新,但这可以通过调用xssfformulaevaluator.evaluateAllFormulacells(wb)来解决;由于某种原因,它不会影响我自定义创建的公式单元格。

我还尝试在创建后单独评估新创建的公式单元格:

FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
formulaEvaluator.evaluateFormulaCell(formCell);

这在这里也没有产生任何变化。

注意:我发现了一个旧的线程(在POI5.0.0发布之前),它似乎讨论了同样的问题,但是对于一个旧的POI版本,也如上面所述,我遵循了调用evaluateAllFormulaCells(...)的一般实践在保存之前,甚至在每次公式单元格创建之后调用evaluateFormulaCell(cell):Apache POI公式不求值

共有1个答案

陆才俊
2023-03-14

这是由于Apache POI在计算WEEKNUM函数时出现了一个bug造成的。

如果省略[return_type],则ist总是计算为#valueerror。但是,即使您设置了[return_type],它的计算结果也不总是正确的。

如果这样做,您可以看到以下内容:

...
FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
CellValue cellValue = formulaEvaluator.evaluate(formCell);
System.out.println(cellValue);
...

如果A1包含日期9/27/2021B1包含公式=weeknum(A1),则Apache POIformulaevaluator将其计算为#value。如果B1包含公式=weeknum(A1,1),则Apache POI将其计算为39,但Excel将其计算为40

要解决此bug,可以在打开文件时强制Excel计算所有公式。这可以使用wb.setForceFormulareCalculation(true);完成。然后Excel计算公式,因此结果是正确的。

完整的例子来重现这个问题:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.formula.BaseFormulaEvaluator;

import java.util.GregorianCalendar;

class CreateExcelFormulaWEEKNUM {

 public static void main(String[] args) throws Exception {

  try (
       //Workbook wb  = WorkbookFactory.create(new FileInputStream("./ExcelIn.xls")); FileOutputStream fileout = new FileOutputStream("./ExcelOut.xls");
       Workbook wb  = WorkbookFactory.create(new FileInputStream("./ExcelIn.xlsx")); FileOutputStream fileout = new FileOutputStream("./ExcelOut.xlsx");
        ) {

   Sheet sheet = wb.getSheetAt(0);

   Row row = sheet.getRow(0); if (row == null) row = sheet.createRow(0);
   Cell cell = row.getCell(0); if (cell == null) cell = row.createCell(0);
   cell.setCellValue(new GregorianCalendar(2021, 8, 27));
   CellReference cellReference = new CellReference(cell);
   
   Cell formCell = row.getCell(1); if(formCell == null) formCell = row.createCell(1);
   formCell.setCellFormula("WEEKNUM(" + cellReference.formatAsString() + ")"); // FormulaEvaluator evaluates to #VALUE because of [return_type] is not set
   //formCell.setCellFormula("WEEKNUM(" + cellReference.formatAsString() + ", 1)"); // FormulaEvaluator evaluates to 39 which is wrong as Excel evaluates to 40
   
   FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
   CellValue cellValue = formulaEvaluator.evaluate(formCell);
   System.out.println(cellValue);
   
   BaseFormulaEvaluator.evaluateAllFormulaCells(wb);
  
   wb.setForceFormulaRecalculation(true);

   wb.write(fileout);
  }

 }
}

 类似资料:
  • 我正在使用apache POI更改excel表中的单元格。更改值后,与已更改的单元格对应的公式的单元格不会更新。 当我进入excel并单击带有公式的单元格,然后在函数栏中单击时,公式会更新。 A1仍然等于3,直到我点击那个单元格。 刷新工作簿或工作表也不起作用。这是excel或POI的问题吗?有人能想出一个变通办法吗?

  • 我的代码设置了很多单元格值。最后,在生成excel文件之前,需要评估每个单元格中的公式。对于大多数床单来说,一切都很顺利。 但是,有一个单元格正在引发异常。该单元格正在计算其后面的一系列单元格和其他工作表中的参考单元格的平均值。我猜当第一个单元格试图计算平均值时,后面的单元格尚未计算。 这是那个单元格上的公式 我怀疑是因为单元格int限制了其他工作表中的引用单元格。例如,D2具有以下公式。 所以我

  • 但这无济于事。有什么想法吗?

  • 我能够使用Apache POI读写单元格值。阅读时,我首先进行评估,这样我就得到了正确的数值。我的用例要求我读取一个工作表,替换工作表中的几个值,然后读取工作表中包含依赖于我刚才替换的单元格的单元格的另一部分。 包含一个公式:。包含,包含。当我计算时,我正确地得到。现在,如果我用POI api将替换为,我希望当我再次阅读时,我会看到。我不...现在计算为。 救命啊!

  • 本文向大家介绍AUC的计算公式相关面试题,主要包含被问及AUC的计算公式时的应答技巧和注意事项,需要的朋友参考一下 参考回答: M为正样本数,N为负样本数。Rank的值代表能够产生前大后小这样的组合数,但是其中包含了(正,正)的情况,所以要减去正例的个数所以可得上述公式。

  • 我正在开发一个上传excel文件并将其值插入数据库的应用程序。 我的代码如下: 所以当我上传一个像下面这样的excel文件时,它会工作并将其数据插入db。 但是,当我上传像以下这样的excel文件时,db不会更新。 我可以问你如何解决这个问题,所以即使单元格的值是=ROUNDUP((600),2),而不是600,它仍然更新db。 提前谢谢你。