git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1894680 13f79535-47bb-0310-9956-ffa450edef68tags/REL_5_2_0
@@ -17,6 +17,9 @@ | |||
package org.apache.poi.xssf.usermodel; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import org.apache.poi.ss.formula.EvaluationCell; | |||
import org.apache.poi.ss.formula.EvaluationSheet; | |||
import org.apache.poi.ss.formula.FormulaParser; | |||
@@ -29,8 +32,8 @@ import org.apache.poi.util.Internal; | |||
*/ | |||
@Internal | |||
public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { | |||
private XSSFEvaluationSheet[] _sheetCache; | |||
private final Map<XSSFSheet, XSSFEvaluationSheet> _sheetCache = new HashMap<>(); | |||
public static XSSFEvaluationWorkbook create(XSSFWorkbook book) { | |||
if (book == null) { | |||
return null; | |||
@@ -48,9 +51,9 @@ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { | |||
@Override | |||
public void clearAllCachedResultValues() { | |||
super.clearAllCachedResultValues(); | |||
_sheetCache = null; | |||
_sheetCache.clear(); | |||
} | |||
@Override | |||
public int getSheetIndex(EvaluationSheet evalSheet) { | |||
XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet(); | |||
@@ -59,25 +62,22 @@ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { | |||
@Override | |||
public EvaluationSheet getSheet(int sheetIndex) { | |||
// Performance optimization: build sheet cache the first time this is called | |||
// to avoid re-creating the XSSFEvaluationSheet each time a new cell is evaluated | |||
// verify index and let the method in _uBook throw the exception so we report | |||
// it the same way as in other places | |||
if (sheetIndex < 0 || sheetIndex >= _uBook.getNumberOfSheets()) { | |||
// this will throw an exception now as the index is out of bounds | |||
_uBook.getSheetAt(sheetIndex); | |||
} | |||
// Performance optimization: build sheet cache for each sheet to avoid re-creating | |||
// the XSSFEvaluationSheet each time a new cell is evaluated | |||
// EvaluationWorkbooks make not guarantee to synchronize changes made to | |||
// the underlying workbook after the EvaluationWorkbook is created. | |||
if (_sheetCache == null) { | |||
final int numberOfSheets = _uBook.getNumberOfSheets(); | |||
_sheetCache = new XSSFEvaluationSheet[numberOfSheets]; | |||
for (int i=0; i < numberOfSheets; i++) { | |||
_sheetCache[i] = new XSSFEvaluationSheet(_uBook.getSheetAt(i)); | |||
} | |||
} | |||
if (sheetIndex < 0 || sheetIndex >= _sheetCache.length) { | |||
// do this to reuse the out-of-bounds logic and message from XSSFWorkbook | |||
_uBook.getSheetAt(sheetIndex); | |||
} | |||
return _sheetCache[sheetIndex]; | |||
final XSSFSheet sheet = _uBook.getSheetAt(sheetIndex); | |||
return _sheetCache.computeIfAbsent(sheet, rows -> new XSSFEvaluationSheet(sheet)); | |||
} | |||
@Override | |||
@Override | |||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) { | |||
final XSSFCell cell = ((XSSFEvaluationCell)evalCell).getXSSFCell(); | |||
final int sheetIndex = _uBook.getSheetIndex(cell.getSheet()); |
@@ -0,0 +1,80 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.xssf.usermodel; | |||
import static org.junit.jupiter.api.Assertions.assertEquals; | |||
import org.apache.poi.ss.usermodel.Cell; | |||
import org.apache.poi.ss.usermodel.FormulaEvaluator; | |||
import org.apache.poi.ss.usermodel.Row; | |||
import org.apache.poi.ss.usermodel.Sheet; | |||
import org.apache.poi.ss.usermodel.Workbook; | |||
import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.junit.jupiter.api.Test; | |||
class TestXSSFEvaluationWorkbook { | |||
@Test | |||
void testRefToBlankCellInArrayFormula() { | |||
Workbook wb = new XSSFWorkbook(); | |||
FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); | |||
verifySheet(wb, formulaEvaluator); | |||
verifySheet(wb, formulaEvaluator); | |||
wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); | |||
} | |||
private void verifySheet(Workbook wb, FormulaEvaluator formulaEvaluator) { | |||
Sheet sheet = wb.createSheet(); | |||
Row row = sheet.createRow(0); | |||
Cell cellA1 = row.createCell(0); | |||
Cell cellB1 = row.createCell(1); | |||
Cell cellC1 = row.createCell(2); | |||
Row row2 = sheet.createRow(1); | |||
Cell cellA2 = row2.createCell(0); | |||
Cell cellB2 = row2.createCell(1); | |||
Cell cellC2 = row2.createCell(2); | |||
Row row3 = sheet.createRow(2); | |||
Cell cellA3 = row3.createCell(0); | |||
Cell cellB3 = row3.createCell(1); | |||
Cell cellC3 = row3.createCell(2); | |||
cellA1.setCellValue("1"); | |||
// cell B1 intentionally left blank | |||
cellC1.setCellValue("3"); | |||
cellA2.setCellFormula("A1"); | |||
cellB2.setCellFormula("B1"); | |||
cellC2.setCellFormula("C1"); | |||
sheet.setArrayFormula("A1:C1", CellRangeAddress.valueOf("A3:C3")); | |||
formulaEvaluator.evaluateAll(); | |||
assertEquals("1", cellA2.getStringCellValue()); | |||
assertEquals(0,cellB2.getNumericCellValue(), 0.00001); | |||
assertEquals("3",cellC2.getStringCellValue()); | |||
assertEquals("1", cellA3.getStringCellValue()); | |||
assertEquals(0,cellB3.getNumericCellValue(), 0.00001); | |||
assertEquals("3",cellC3.getStringCellValue()); | |||
} | |||
} |