在我们的项目中,我们有不同版本的excelsheets相互引用:
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的公式,我发现以下示例here
// 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();
现在我的问题:我不知道文件的位置,因此需要从mainworkbook获取所有引用然后自动(并且可能递归地)添加它们,而不是像上面的例子。是否有函数来获取引用或有没有人知道实现此目的的方法?
此外,我想知道我是否必须将所有FormulaEvaluator添加到V3或者我是否必须将V2添加到V3并将V1添加到V2以使其工作?
我目前已实现setIgnoreMissingWorkbooks(true),但由于值会发生变化,我们不想手动打开每个excel文件来更新我想要实现此解决方案的引用。任何帮助表示赞赏
答案 0 :(得分:1)
要获取所有外部引用,请使用以下方法:
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;
}