FormulaEvaluator :: evaluateAllを呼び出した後にどのセルが変更されたかを効率的に判断する方法はありますか?ワークブック評価後に更新されたセルを効率よく決定する
IEvaluationListenerというインターフェースがありますが、これは有用かもしれませんが、外部からは利用できません(テスト専用です)。
FormulaEvaluator :: evaluateAllを呼び出した後にどのセルが変更されたかを効率的に判断する方法はありますか?ワークブック評価後に更新されたセルを効率よく決定する
IEvaluationListenerというインターフェースがありますが、これは有用かもしれませんが、外部からは利用できません(テスト専用です)。
evaluateAll
がどのように動作しているかを調べて、BaseFormulaEvaluator.evaluateAllFormulaCellsを見つけました。
このコードは評価されるすべてのセルにアクセスします。コピー&ペーストで簡単に使用できます。 evaluateAll
の間にはapache poi
の使用と同じですので、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();
}
}
この例では、第一シートにおけるA2
の値は、いくつかの式中の基準として使用されることを期待します。したがって、この値を変更すると、評価中に式セルに新しい値がもたらされます。