在Excel单元格中使用外部引用的FormulaEvaluator.evaluateAll()将使用Apache POI返回RuntimeException
在过去的几天里,这一直使我疯狂。
请考虑两个Excel文件: a.xlsx和b.xlsx
以下是应该评估a.xlsx中单元格的代码,包括对b.xlsx的外部引用。
import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class Test { public static void main(String[] args) { try { FileInputStream file1 = new FileInputStream("C:\\Users\\Abid\\Desktop\\a.xlsx"); FileInputStream file2 = new FileInputStream("C:\\Users\\Abid\\Desktop\\b.xlsx"); XSSFWorkbook workbook1 = new XSSFWorkbook(file1); XSSFWorkbook workbook2 = new XSSFWorkbook(file2); FormulaEvaluator evaluator1 = workbook1.getCreationHelper().createFormulaEvaluator(); FormulaEvaluator evaluator2 = workbook2.getCreationHelper().createFormulaEvaluator(); Map<String, FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>(); workbooks.put("a.xlsx", evaluator1); workbooks.put("b.xlsx", evaluator2); evaluator1.setupReferencedWorkbooks(workbooks); evaluator1.evaluateAll(); file1.close(); file2.close(); workbook1.close(); workbook2.close(); } catch (IOException e) { e.printStackTrace(); } } }
不幸的是,这是我执行后得到的结果:
Exception in thread "main" java.lang.RuntimeException: Could not resolve external workbook name 'b.xlsx'. Workbook environment has not been set up. at org.apache.poi.ss.formula.OperationEvaluationContext.createExternSheetRefEvaluator(OperationEvaluationContext.java:113) at org.apache.poi.ss.formula.OperationEvaluationContext.createExternSheetRefEvaluator(OperationEvaluationContext.java:84) at org.apache.poi.ss.formula.OperationEvaluationContext.getRef3DEval(OperationEvaluationContext.java:313) at org.apache.poi.ss.formula.WorkbookEvaluator.getEvalForPtg(WorkbookEvaluator.java:634) at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:505) at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:263) at org.apache.poi.ss.formula.WorkbookEvaluator.evaluate(WorkbookEvaluator.java:205) at org.apache.poi.xssf.usermodel.BaseXSSFFormulaEvaluator.evaluateFormulaCellValue(BaseXSSFFormulaEvaluator.java:189) at org.apache.poi.xssf.usermodel.BaseXSSFFormulaEvaluator.evaluateFormulaCell(BaseXSSFFormulaEvaluator.java:117) at org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.evaluateAllFormulaCells(HSSFFormulaEvaluator.java:346) at org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.evaluateAllFormulaCells(HSSFFormulaEvaluator.java:337) at org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator.evaluateAll(XSSFFormulaEvaluator.java:105) at Test.main(Test.java:28) Caused by: org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment$WorkbookNotFoundException: Could not resolve external workbook name 'b.xlsx'. Workbook environment has not been set up. at org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.getWorkbookEvaluator(CollaboratingWorkbooksEnvironment.java:195) at org.apache.poi.ss.formula.WorkbookEvaluator.getOtherWorkbookEvaluator(WorkbookEvaluator.java:156) at org.apache.poi.ss.formula.OperationEvaluationContext.createExternSheetRefEvaluator(OperationEvaluationContext.java:111) ... 12 more
您需要使用Apache POI 3.15testing版3或更新版本,或者从2016年4月4日之后的git /之后的svn / build版本开始每晚构build/构build。 正如Apache POI更新日志中所述 ,这是一个后来修复的特定于XSSF的错误
如果使用构build/发行版以及修订版,则对XSSFFormulaEvaluator
evaluateAll()
调用现在将使用已经设置的任何引用的工作簿,就像HSSF一直XSSFFormulaEvaluator
一样。
这将工作没有问题与HSSF
(* .xls)。
但是apache poi是一团糟。 因此, XSSFFormulaEvaluator.evaluateAll()将简单地调用HSSFFormulaEvaluator.evaluateAllFormulaCells(_book);
。 但HSSFFormulaEvaluator.evaluateAllFormulaCells(Workbook wb)将创build一个新的 FormulaEvaluator
,它不涉及到环境中。
相反,它应该调用HSSFFormulaEvaluator.evaluateAllFormulaCells(工作簿wb,FormulaEvaluator评估者)并交出环境中涉及的FormulaEvaluator
。 但是这个方法是private
。
幸运的是,它并没有那么大和独立。 所以我们可以在我们的代码中使用这个方法:
import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.poi.ss.usermodel.*; public class TestEvaluateExtRef { private 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.getCellType() == Cell.CELL_TYPE_FORMULA) { evaluator.evaluateFormulaCell(c); } } } } } public static void main(String[] args) { try { Workbook workbook1 = WorkbookFactory.create(new FileInputStream("a.xlsx")); Workbook workbook2 = WorkbookFactory.create(new FileInputStream("b.xlsx")); FormulaEvaluator evaluator1 = workbook1.getCreationHelper().createFormulaEvaluator(); FormulaEvaluator evaluator2 = workbook2.getCreationHelper().createFormulaEvaluator(); Map<String, FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>(); workbooks.put("a.xlsx", evaluator1); workbooks.put("b.xlsx", evaluator2); workbook2.getSheetAt(0).getRow(0).getCell(0).setCellValue(new java.util.Random().nextDouble()); evaluator1.setupReferencedWorkbooks(workbooks); //evaluator1.evaluateAll(); evaluateAllFormulaCells(workbook1, evaluator1); System.out.println(workbook1.getSheetAt(0).getRow(0).getCell(0)); System.out.println(workbook1.getSheetAt(0).getRow(0).getCell(0).getNumericCellValue()); workbook1.close(); workbook2.close(); } catch (Exception e) { e.printStackTrace(); } } }
- 写入工作簿时获取java.lang.NullPointerException WorkBook.write(out)Apache POI
- 适用于所有单元格的Apache POI风格
- 通过apache poi读取excel文件(在classpath中)
- 读取限制访问的excel文件:没有这样的条目:“EncryptionInfo”,有:[EncryptedPackage,
- JAKARTA POI将整行删除到Excel(不仅仅是内容)
- 在excel中使用xssf库绘制带有箭头的行
- 如何使用Java将Excel(2003和2007版本)文件导入到MySQL?
- 在excel中使用apache poi在java中合并文本中心
- 在Java中渲染Excel表格报告的最佳实践是什么?