2016-01-29 307 views
6

我想将简单的VLookup公式放入使用Java和Apache POI的“.xlsx”文件中。
此公式具有外部参照,并不适合我。Java POI XSSF VLookup公式

所以,给你更多的细节我使用POI和POI-OOXML版本3.13和Excel 2007中
我把该公式单元格这种方式(其中cell是小区):

cell.setCellType(Cell.CELL_TYPE_FORMULA); 
cell.setCellFormula("StringContainingFormula"); 

然后评估公式,我尝试了三种不同的方式,但没有运气。 (wb是XSSFWorkbook)。

FormulaEvaluator mainWorkbookEvaluator = wb.getCreationHelper().createFormulaEvaluator(); 
Map<String,FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>(); 
workbooks.put("SpreadsheetName.xlsx", mainWorkbookEvaluator); 
mainWorkbookEvaluator.setupReferencedWorkbooks(workbooks); 
mainWorkbookEvaluator.evaluateAll(); 
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); 
       } 
      } 
     } 
    } 
} 
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb); 

的问题是,将其写入到Excel文件,然后在评估它引发错误:

java.lang.IllegalArgumentException: Invalid sheetIndex: -1

现在,如果我打开Excel文件,它给了我警告:

Automatic update of links has been disabled

如果我启用内容,公式显示的结果正确,如果我没有做任何事情比公式导致#N/A
现在,如果我选择其中的公式单元格,然后单击公式栏并按回车比公式显示结果。

更新:

所以,我通过进入Excel选项禁用警告消息,并开始给我在细胞内的公式。
但是,当我尝试使用

if (cell.getCachedFormulaResultType == Cell.CELL_TYPE_STRING) { 
    System.out.println("Last evaluated as \"" + cell.getRichStringCellValue() + "\""); 
} 

从它那里得到的结果值它从来没有给我的getCachedFormulaResultTypeCELL_TYPE_STRING,它总是返回CELL_TYPE_NUMERIC。它应该返回字符串值。我正在解释URL和其他值(单词“|” - “猫|鸟”)。

我感谢任何帮助/建议。

+0

可能是最好的检查[公式评估(https://开头的POI。 apache.org/spreadsheet/eval.html)文件仔细。也许像'wb.setForceFormulaRecalculation(true);'会帮助你? –

+0

此外,文档的说'createFormulaEvaluator'您参考的工作表。例如,'workbooks.put(“input.xls”,WorkbookFactory.create(“c:\ temp \ input22.xls”)。getCreationHelper()。createFormulaEvaluator());' –

+0

@Nicholas,非常感谢您的提示,但我找不到类似于'wb.setForceFormulaRecalculation(true);'和我已经尝试'createFormulaEvaluator'的引用,但没有运气。 – ManishChristian

回答

0

所以,我没有任何其他的选择,我哈d将引用的数据复制到主工作簿(我知道这不是个好主意,如果数据很大的话)可以使其工作。
所以我做的是:

  1. 从外部工作簿复制引用的数据。
  2. 在主工作簿(您需要编写公式)中创建新工作表并粘贴引用数据。
  3. 现在编写公式,这次而不是外部工作簿使用新创建的工作表(粘贴数据)。
    备注*:您需要先写入所有数据(包括公式),然后才能评估公式。
  4. 然后打开工作簿读,如果你已经关闭,并评估所有像这样的公式(WB是XSSFWorkbook):

XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);

1

好吧,它似乎工作。你必须轻轻地对待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(); 
+0

这不适合我。如果我在打开“Referenced”工作簿之前使用'setCellFormula'(没有完整的路径(就像你所做的那样)),它给了我错误'java.lang.RuntimeException:Book没有链接到文件名“ReferencedFileName.xlsx”'。如果我使用完整路径,它再次给我'无效的sheetIndex:-1'错误。 – ManishChristian

+0

就像我刚才提到的那样,在运行此代码之前,必须通过excel连接外部电子表格。有一个方法调用来链接POI('linkExternalWorkbook')中的电子表格,但没有实现。对此我无能为力。 –

+0

首先,非常感谢你@Nicholas的帮助。所以,用最短的方式,我们可以说目前这是不可行的吗?因为如果我们无法链接工作簿,那么没有任何参考外部工作簿的要点。 – ManishChristian

0

我最近有同样的问题。问题在于,用当前的POI,一个不能写文档,将公式添加到特定字段并对其进行公式评估,此时,仍然不存在文档。再次,只有

  1. 写的所有数据和公式到工作簿
  2. 关闭这个文件
  3. 写前加workbook.setForceFormulaRecalculation(true);和关闭文档
  4. 打开同一个文档:我使用的伎俩来解决它做FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); evaluator.evaluateAll();
  5. 写,并再次接近