dynamic添加外部(Cross-Workbook)引用

在我们的项目中,我们有不同版本的Excel表格,它们相互引用:

C:\ V1 \ Sample.xls //没有引用

C:\ V2 \ Sample.xls //引用V1

C:\ V3 \ Sample.xls //引用V2

单元格值示例:

=MID('C:\V1\[Sample.xls]Sheet1'!$AB2;21;1) 

现在我想用apache POI来评估V3的公式,我在这里find了下面的例子

 // Create a FormulaEvaluator to use FormulaEvaluator mainWorkbookEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); // Track the workbook references Map<String,FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>(); // Add this workbook workbooks.put("report.xlsx", mainWorkbookEvaluator); // Add two others workbooks.put("input.xls", WorkbookFactory.create("c:\temp\input22.xls").getCreationHelper().createFormulaEvaluator()); workbooks.put("lookups.xlsx", WorkbookFactory.create("/home/poi/data/tmp-lookups.xlsx").getCreationHelper().createFormulaEvaluator()); // Attach them mainWorkbookEvaluator.setupReferencedWorkbooks(workbooks); // Evaluate mainWorkbookEvaluator.evaluateAll(); 

现在我的问题:我不知道文件的位置,因此我需要从主工作簿中获取所有引用 ,然后自动(可能recursion)添加它们,而不是像上面的示例中的静态。 有没有一个函数来获取引用,或者有没有人知道一个方法来实现这一目标?

此外,我想知道是否必须将所有FormulaEvaluator添加到V3,或者是否必须将V2添加到V3和V1到V2才能正常工作?

我目前已经实现了setIgnoreMissingWorkbooks(true),但是值会改变,我们不想手动打开每个excel文件来更新引用我想要实现这个解决scheme。 任何帮助表示赞赏

要获取所有外部引用,请使用以下方法:

 private static Set<String> getReferencedWorkbooks(Workbook workbook) { Set<String> workbookNames = new HashSet<>(); final EvaluationWorkbook evalWorkbook; if (workbook instanceof HSSFWorkbook) { evalWorkbook = HSSFEvaluationWorkbook.create((HSSFWorkbook) workbook); } else if (workbook instanceof XSSFWorkbook) { evalWorkbook = XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook); } else { throw new IllegalStateException(); } for (int i = 0; i < workbook.getNumberOfSheets(); i++) { Sheet sheet = workbook.getSheetAt(i); final EvaluationSheet evalSheet = evalWorkbook.getSheet(i); for (Row r : sheet) { for (Cell c : r) { if (c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) { final EvaluationCell cell = evalSheet.getCell(c.getRowIndex(), c.getColumnIndex()); final Ptg[] formulaTokens = evalWorkbook.getFormulaTokens(cell); for (Ptg formulaToken : formulaTokens) { final int externalSheetIndex; if (formulaToken instanceof Ref3DPtg) { Ref3DPtg refToken = (Ref3DPtg) formulaToken; externalSheetIndex = refToken.getExternSheetIndex(); } else if (formulaToken instanceof Ref3DPxg) { Ref3DPxg refToken = (Ref3DPxg) formulaToken; externalSheetIndex = refToken.getExternalWorkbookNumber(); } else { externalSheetIndex = -1; } if (externalSheetIndex >= 0) { final ExternalSheet externalSheet = evalWorkbook.getExternalSheet(externalSheetIndex); workbookNames.add(externalSheet.getWorkbookName()); } } } } } } return workbookNames; } 

如果您的所有工作簿都是XLSX / XLSM,则可以使用以下代码:

 private static Set<String> getReferencedWorkbooksXssf(XSSFWorkbook workbook) { Set<String> workbookNames = new HashSet<>(); final List<ExternalLinksTable> externalLinksTable = workbook.getExternalLinksTable(); for (ExternalLinksTable linksTable : externalLinksTable) { final String linkedFileName = linksTable.getLinkedFileName(); workbookNames.add(linkedFileName); } return workbookNames; }