Формула Java POI XSSF VLookup

Я пытаюсь поставить простую формулу VLookup в моем ".xlsx " файл с использованием Java и Apache POI.
Эта формула имеет внешнюю ссылку, и это не работает для меня.

поэтому, чтобы дать вам более подробную информацию, я использую poi и poi-ooxml версии 3.13 и excel 2007.
Я помещаю формулу в ячейку таким образом (где ячейка-это ячейка):

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

а затем оцените формулу, я пробовал три разных способа, но не повезло. (ББ 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.ленг.IllegalArgumentException: недопустимый sheetIndex: -1

теперь, если я открою файл Excel, он дает мне предупреждение:

автоматическое обновление ссылок отключено

если я включу содержание, формула показывает результат правильно, и если я ничего не делаю, чем формула, приводящая к #N/A.
Теперь, если я выберу ячейку с формулой в ней и нажмите "строка формул" и нажмите "Ввод", формула покажет результат.

обновление:

Итак, я отключил предупреждающее сообщение, перейдя в параметры Excel, и он начал давать мне формулу внутри ячейки.
Но, когда я попытался получить значение результата от него, используя

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

он никогда не давал мне getCachedFormulaResultType as CELL_TYPE_STRING, оно всегда возвращается CELL_TYPE_NUMERIC. Он должен возвращать строковое значение. Я экспонирую URL и другое значение (слова, разделенные "|" - "кошка|собака|птица").

Я ценю любую помощь / предложение.

3 ответов


Ну, кажется, это работает. Вы должны относиться к 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 нельзя написать документ, добавить формулу в конкретное поле и выполнить оценку формулы на все еще не существующем документе. Трюк, который я использовал для его решения, был:

  1. запишите все данные и формулы в рабочую книгу
  2. добавить workbook.setForceFormulaRecalculation(true); перед закрытием этого документа
  3. напишите и закройте документ
  4. откройте тот же документ снова и только FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); evaluator.evaluateAll();
  5. пишите и еще раз закрыть!--6-->

Итак, поскольку у меня нет другого варианта, мне пришлось скопировать ссылочные данные в основную книгу (я знаю, что это не очень хорошая идея, если данные огромны), чтобы все работало.
Вот что я сделал:--2-->

  1. скопировать данные из внешней книги.
  2. создайте новый рабочий лист в главной книге(в которой вам нужно написать формулу) и вставьте ссылочные данные.
  3. теперь напишите формулу и на этот раз вместо использования внешней книги вновь созданный рабочий лист (с вставленными данными).
    Примечание: вам нужно сначала написать все данные (включая формулы), прежде чем отправиться на оценку формул.
  4. затем откройте книгу для чтения, если вы уже закрыли и оцените все формулы, подобные этому (wb-XSSFWorkbook):

XSSFFormulaEvaluator.evaluateAllFormulaCells (wb);