在调用FormulaEvaluator :: evaluateAll后,是否有一种有效的方法来确定哪些单元格已更改?
我可以看到有一个IEvaluationListener接口可能很有用,但它在外部不可用(似乎仅用于测试)。
答案 0 :(得分:1)
我查找了evaluateAll
的工作原理并找到了BaseFormulaEvaluator.evaluateAllFormulaCells。
此代码可以访问所有已评估的单元格。它只需复制/粘贴即可使用。由于它与apache poi
使用的evaluateAll
相同,因此它应与[{1}}一样高效。
在评估之前,您可以获得单元格的旧值,在评估之后,您可以获得单元格的新值。因此,您可以确定评估是否已更改某些内容。当然,这些变化会影响表现,但我认为没有办法避免这种情况。
evaluateAll
此示例期望第一个工作表中的import org.apache.poi.ss.usermodel.*;
import java.io.InputStream;
import java.io.FileInputStream;
class ExcelEvaluateAllFormulas {
public static void evaluateAllFormulaCells(Workbook wb) {
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
evaluateAllFormulaCells(wb, evaluator);
}
protected static void evaluateAllFormulaCells(Workbook wb, FormulaEvaluator evaluator) {
for(int i=0; i<wb.getNumberOfSheets(); i++) {
Sheet sheet = wb.getSheetAt(i);
for(Row r : sheet) {
for (Cell c : r) {
if (c.getCellTypeEnum() == CellType.FORMULA) {
CellType celltype = c.getCachedFormulaResultTypeEnum();
Object oldvalue = null;
if (celltype == CellType.NUMERIC) {
oldvalue = c.getNumericCellValue();
} else if (celltype == CellType.BOOLEAN) {
oldvalue = c.getBooleanCellValue();
} else if (celltype == CellType.STRING) {
oldvalue = c.getStringCellValue();
} else if (celltype == CellType.ERROR) {
oldvalue = "Err: " + c.getErrorCellValue();
}
if (oldvalue == null) oldvalue = "no value";
System.out.print(c.getSheet().getSheetName() + "!" + c.getAddress() + ":old value:" + oldvalue);
celltype = evaluator.evaluateFormulaCellEnum(c);
Object newvalue = null;
if (celltype == CellType.NUMERIC) {
newvalue = c.getNumericCellValue();
} else if (celltype == CellType.BOOLEAN) {
newvalue = c.getBooleanCellValue();
} else if (celltype == CellType.STRING) {
newvalue = c.getStringCellValue();
} else if (celltype == CellType.ERROR) {
newvalue = "Err: " + c.getErrorCellValue();
}
if (newvalue == null) newvalue = "no value";
System.out.println("->new value:" + newvalue);
if (oldvalue.equals(newvalue)) {
System.out.println("Value has not changed.");
} else {
System.out.println("Value has changed.");
}
}
}
}
}
}
public static void main(String[] args) throws Exception{
InputStream inp = new FileInputStream("ExcelWithFormulas.xlsx");
Workbook workbook = WorkbookFactory.create(inp);
workbook.getSheetAt(0).getRow(1).getCell(0).setCellValue(0.5);
evaluateAllFormulaCells(workbook);
workbook.close();
}
}
值在某些公式中用作参考。因此,在评估时,更改此值会导致公式单元格中的新值。