Java POI XSSF VLookup 公式
Java POI XSSF VLookup formula
我正在尝试使用 Java 和 Apache POI 将简单的 VLookup 公式放入我的“.xlsx”文件中。
这个公式有外部参考,对我不起作用。
因此,为了向您提供更多详细信息,我使用的是 poi 和 poi-ooxml 版本 3.13 和 excel 2007。
我以这种方式将公式放入单元格(其中单元格是一个单元格):
cell.setCellType(Cell.CELL_TYPE_FORMULA);
cell.setCellFormula("StringContainingFormula");
然后评估公式,我尝试了三种不同的方法但没有运气。 (wb 是 XSSFWorkbook)。
1
FormulaEvaluator mainWorkbookEvaluator = wb.getCreationHelper().createFormulaEvaluator();
Map<String,FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>();
workbooks.put("SpreadsheetName.xlsx", mainWorkbookEvaluator);
mainWorkbookEvaluator.setupReferencedWorkbooks(workbooks);
mainWorkbookEvaluator.evaluateAll();
2
XSSFEvaluationWorkbook.create(wb);
Workbook nwb = wb;
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
for (Sheet sheet : nwb) {
for (Row r : sheet) {
for (Cell c : r) {
if (c.getCellType() == Cell.CELL_TYPE_FORMULA) {
try {
//evaluator.evaluateFormulaCell(c);
evaluator.evaluate(c);
} catch (Exception e) {
System.out.println("Error occured in 'EvaluateFormulas' : " + e);
}
}
}
}
}
3
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
问题是,它写入 Excel 文件,然后在评估时抛出错误:
java.lang.IllegalArgumentException: Invalid sheetIndex: -1
现在如果我打开 Excel 文件,它会给我警告:
Automatic update of links has been disabled
如果我启用内容,公式会正确显示结果,如果我不做任何事情而不是公式导致 #N/A
.
现在,如果我 select 包含公式的单元格并单击公式栏并按回车键,则公式会显示结果。
更新:
因此,我通过进入 Excel 选项禁用了警告消息,它开始在单元格内给我公式。
但是,当我尝试使用
从中获取结果值时
if (cell.getCachedFormulaResultType == Cell.CELL_TYPE_STRING) {
System.out.println("Last evaluated as \"" + cell.getRichStringCellValue() + "\"");
}
它从来没有给我 getCachedFormulaResultType
作为 CELL_TYPE_STRING
,它总是 return CELL_TYPE_NUMERIC
。它应该是 return 字符串值。我正在扩展 URL 和其他值(由“|” - "cat|dog|bird" 分隔的单词)。
我很感激任何help/suggestion。
好吧,它似乎起作用了。你要温柔对待excel;如果先打开外部工作簿,然后再打开主工作簿,效果会更好。如果你不这样做,它会给出一条关于不安全链接的消息,但除此之外,一切似乎都很好。评估器仅适用于单个单元格,因此如果您想重新计算整个电子表格,则必须循环。此外,外部引用必须已经由 excel 链接,POI
尚未实现该功能。这是我在 github:
中输入的内容
// Open workbooks
Path pathBook1 = Paths.get("c:/users/karl/scsb/Vlookup/Book1.xlsx");
InputStream is = Files.newInputStream(pathBook1);
XSSFWorkbook book1 = new XSSFWorkbook(is);
// Add Linked Cell
// The workbook must already have been linked to Book2.xlsx by Excel
// The linkExternalWorkbook has not yet been implemented: SEE BUG #57184
Cell cell = book1.getSheetAt(0).createRow(2).createCell(0);
cell.setCellFormula("A2+[Book2.xlsx]Sheet1!A1");
// Create evaluator after the new cell has been added.
FormulaEvaluator mainEvaluator = book1.getCreationHelper().createFormulaEvaluator();
XSSFWorkbook book2 = new XSSFWorkbook("c:/users/karl/scsb/Vlookup/Book2.xlsx");
Map<String, FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>();
workbooks.put("Book1.xlsx", mainEvaluator);
workbooks.put("Book2.xlsx", book2.getCreationHelper().createFormulaEvaluator());
mainEvaluator.setupReferencedWorkbooks(workbooks);
// mainEvaluator.evaluateAll(); // doesn't work.
// XSSFFormulaEvaluator.evaluateAllFormulaCells(book1); // doesn't work.
mainEvaluator.evaluateFormulaCell(cell);
System.out.println(cell.getNumericCellValue());
book2.close();
// Close and write workbook 1
is.close();
OutputStream os = Files.newOutputStream(pathBook1);
book1.write(os);
os.close();
book1.close();
我最近遇到了同样的问题。问题是,对于当前的 POI,无法编写文档、将公式添加到特定字段并在此时仍不存在的文档上执行公式评估。我用来解决它的技巧是:
- 将所有数据和公式写入工作簿
- 在关闭此文档之前添加
workbook.setForceFormulaRecalculation(true);
- 编写并关闭文档
- 再次打开同一个文档,只做
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); evaluator.evaluateAll();
- 再次写入并关闭
因此,由于我没有任何其他选择,我不得不将引用的数据复制到主工作簿(我知道这不是个好主意,以防数据量很大)才能正常工作。
所以我所做的是:
- 从外部工作簿复制引用数据。
- 在主工作簿上创建新工作表(您需要在其中编写公式)并粘贴引用数据。
- 现在编写公式,这次使用新创建的工作表(粘贴数据)而不是外部工作簿。
注意*:你需要先把所有的数据(包括公式)都写好,然后再去计算公式。
- 如果您已经关闭,然后打开工作簿进行阅读,并像这样评估所有公式(wb 是 XSSFWorkbook):
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
我正在尝试使用 Java 和 Apache POI 将简单的 VLookup 公式放入我的“.xlsx”文件中。
这个公式有外部参考,对我不起作用。
因此,为了向您提供更多详细信息,我使用的是 poi 和 poi-ooxml 版本 3.13 和 excel 2007。
我以这种方式将公式放入单元格(其中单元格是一个单元格):
cell.setCellType(Cell.CELL_TYPE_FORMULA);
cell.setCellFormula("StringContainingFormula");
然后评估公式,我尝试了三种不同的方法但没有运气。 (wb 是 XSSFWorkbook)。
1
FormulaEvaluator mainWorkbookEvaluator = wb.getCreationHelper().createFormulaEvaluator();
Map<String,FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>();
workbooks.put("SpreadsheetName.xlsx", mainWorkbookEvaluator);
mainWorkbookEvaluator.setupReferencedWorkbooks(workbooks);
mainWorkbookEvaluator.evaluateAll();
2
XSSFEvaluationWorkbook.create(wb);
Workbook nwb = wb;
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
for (Sheet sheet : nwb) {
for (Row r : sheet) {
for (Cell c : r) {
if (c.getCellType() == Cell.CELL_TYPE_FORMULA) {
try {
//evaluator.evaluateFormulaCell(c);
evaluator.evaluate(c);
} catch (Exception e) {
System.out.println("Error occured in 'EvaluateFormulas' : " + e);
}
}
}
}
}
3
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
问题是,它写入 Excel 文件,然后在评估时抛出错误:
java.lang.IllegalArgumentException: Invalid sheetIndex: -1
现在如果我打开 Excel 文件,它会给我警告:
Automatic update of links has been disabled
如果我启用内容,公式会正确显示结果,如果我不做任何事情而不是公式导致 #N/A
.
现在,如果我 select 包含公式的单元格并单击公式栏并按回车键,则公式会显示结果。
更新:
因此,我通过进入 Excel 选项禁用了警告消息,它开始在单元格内给我公式。
但是,当我尝试使用
if (cell.getCachedFormulaResultType == Cell.CELL_TYPE_STRING) {
System.out.println("Last evaluated as \"" + cell.getRichStringCellValue() + "\"");
}
它从来没有给我 getCachedFormulaResultType
作为 CELL_TYPE_STRING
,它总是 return CELL_TYPE_NUMERIC
。它应该是 return 字符串值。我正在扩展 URL 和其他值(由“|” - "cat|dog|bird" 分隔的单词)。
我很感激任何help/suggestion。
好吧,它似乎起作用了。你要温柔对待excel;如果先打开外部工作簿,然后再打开主工作簿,效果会更好。如果你不这样做,它会给出一条关于不安全链接的消息,但除此之外,一切似乎都很好。评估器仅适用于单个单元格,因此如果您想重新计算整个电子表格,则必须循环。此外,外部引用必须已经由 excel 链接,POI
尚未实现该功能。这是我在 github:
// Open workbooks
Path pathBook1 = Paths.get("c:/users/karl/scsb/Vlookup/Book1.xlsx");
InputStream is = Files.newInputStream(pathBook1);
XSSFWorkbook book1 = new XSSFWorkbook(is);
// Add Linked Cell
// The workbook must already have been linked to Book2.xlsx by Excel
// The linkExternalWorkbook has not yet been implemented: SEE BUG #57184
Cell cell = book1.getSheetAt(0).createRow(2).createCell(0);
cell.setCellFormula("A2+[Book2.xlsx]Sheet1!A1");
// Create evaluator after the new cell has been added.
FormulaEvaluator mainEvaluator = book1.getCreationHelper().createFormulaEvaluator();
XSSFWorkbook book2 = new XSSFWorkbook("c:/users/karl/scsb/Vlookup/Book2.xlsx");
Map<String, FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>();
workbooks.put("Book1.xlsx", mainEvaluator);
workbooks.put("Book2.xlsx", book2.getCreationHelper().createFormulaEvaluator());
mainEvaluator.setupReferencedWorkbooks(workbooks);
// mainEvaluator.evaluateAll(); // doesn't work.
// XSSFFormulaEvaluator.evaluateAllFormulaCells(book1); // doesn't work.
mainEvaluator.evaluateFormulaCell(cell);
System.out.println(cell.getNumericCellValue());
book2.close();
// Close and write workbook 1
is.close();
OutputStream os = Files.newOutputStream(pathBook1);
book1.write(os);
os.close();
book1.close();
我最近遇到了同样的问题。问题是,对于当前的 POI,无法编写文档、将公式添加到特定字段并在此时仍不存在的文档上执行公式评估。我用来解决它的技巧是:
- 将所有数据和公式写入工作簿
- 在关闭此文档之前添加
workbook.setForceFormulaRecalculation(true);
- 编写并关闭文档
- 再次打开同一个文档,只做
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); evaluator.evaluateAll();
- 再次写入并关闭
因此,由于我没有任何其他选择,我不得不将引用的数据复制到主工作簿(我知道这不是个好主意,以防数据量很大)才能正常工作。
所以我所做的是:
- 从外部工作簿复制引用数据。
- 在主工作簿上创建新工作表(您需要在其中编写公式)并粘贴引用数据。
- 现在编写公式,这次使用新创建的工作表(粘贴数据)而不是外部工作簿。
注意*:你需要先把所有的数据(包括公式)都写好,然后再去计算公式。 - 如果您已经关闭,然后打开工作簿进行阅读,并像这样评估所有公式(wb 是 XSSFWorkbook):
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);