final class HSSFEvaluationSheet implements EvaluationSheet {
private final HSSFSheet _hs;
- private int _lastDefinedRow = -1;
public HSSFEvaluationSheet(HSSFSheet hs) {
_hs = hs;
- _lastDefinedRow = _hs.getLastRowNum();
}
public HSSFSheet getHSSFSheet() {
*/
@Override
public int getLastRowNum() {
- return _lastDefinedRow;
+ return _hs.getLastRowNum();
}
@Override
*/
@Override
public void clearAllCachedResultValues() {
- _lastDefinedRow = _hs.getLastRowNum();
}
}
@Internal
final class SXSSFEvaluationSheet implements EvaluationSheet {
private final SXSSFSheet _xs;
- private int _lastDefinedRow = -1;
public SXSSFEvaluationSheet(SXSSFSheet sheet) {
_xs = sheet;
- _lastDefinedRow = _xs.getLastRowNum();
}
public SXSSFSheet getSXSSFSheet() {
*/
@Override
public int getLastRowNum() {
- return _lastDefinedRow;
+ return _xs.getLastRowNum();
}
@Override
*/
@Override
public void clearAllCachedResultValues() {
- _lastDefinedRow = _xs.getLastRowNum();
}
}
private final XSSFSheet _xs;
private Map<CellKey, EvaluationCell> _cellCache;
- private int _lastDefinedRow = -1;
public XSSFEvaluationSheet(XSSFSheet sheet) {
_xs = sheet;
- _lastDefinedRow = _xs.getLastRowNum();
}
public XSSFSheet getXSSFSheet() {
*/
@Override
public int getLastRowNum() {
- return _lastDefinedRow;
+ return _xs.getLastRowNum();
}
/* (non-JavaDoc), inherit JavaDoc from EvaluationWorkbook
@Override
public void clearAllCachedResultValues() {
_cellCache = null;
- _lastDefinedRow = _xs.getLastRowNum();
}
@Override
public EvaluationCell getCell(int rowIndex, int columnIndex) {
// shortcut evaluation if reference is outside the bounds of existing data
// see issue #61841 for impact on VLOOKUP in particular
- if (rowIndex > _lastDefinedRow) return null;
-
+ if (rowIndex > getLastRowNum()) {
+ return null;
+ }
+
// cache for performance: ~30% speedup due to caching
if (_cellCache == null) {
_cellCache = new HashMap<>(_xs.getLastRowNum() * 3);
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTablePart;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableParts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheetSource;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
@Override
public int getLastRowNum() {
+ // _rows.getLastKey() (O(logN)) or caching last row (O(1))?
+ // A test with 1_000_000 rows shows that querying getLastRowNum with lastKey() implementation takes ~40 ms,
+ // and ~1.2 ms with cached implementation. 40 ms is negligible compared to the time of evaluation a million
+ // cells, and the lastKey implementation is much more elegant and less error prone than caching.
return _rows.isEmpty() ? 0 : _rows.lastKey();
}
--- /dev/null
+/* ====================================================================
+ 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.streaming;
+
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.BaseTestXEvaluationSheet;
+import org.apache.poi.ss.usermodel.Sheet;
+
+import java.util.AbstractMap;
+import java.util.Map;
+
+public class TestSXSSFEvaluationSheet extends BaseTestXEvaluationSheet {
+ @Override
+ protected Map.Entry<Sheet, EvaluationSheet> getInstance() {
+ SXSSFSheet sheet = new SXSSFWorkbook().createSheet();
+ return new AbstractMap.SimpleEntry<>(sheet, new SXSSFEvaluationSheet(sheet));
+ }
+}
==================================================================== */
package org.apache.poi.xssf.usermodel;
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.BaseTestXEvaluationSheet;
+import org.apache.poi.ss.usermodel.Sheet;
import org.junit.Test;
+import java.util.AbstractMap;
+import java.util.Map;
+
import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-public class TestXSSFEvaluationSheet {
+public class TestXSSFEvaluationSheet extends BaseTestXEvaluationSheet {
@Test
public void test() throws Exception {
// other things
assertEquals(sheet, evalsheet.getXSSFSheet());
}
-}
\ No newline at end of file
+
+ @Override
+ protected Map.Entry<Sheet, EvaluationSheet> getInstance() {
+ XSSFSheet sheet = new XSSFWorkbook().createSheet();
+ return new AbstractMap.SimpleEntry<>(sheet, new XSSFEvaluationSheet(sheet));
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.hssf.usermodel;
+
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.BaseTestXEvaluationSheet;
+import org.apache.poi.ss.usermodel.Sheet;
+
+import java.util.AbstractMap;
+import java.util.Map;
+
+public class TestHSSFEvaluationSheet extends BaseTestXEvaluationSheet {
+ @Override
+ protected Map.Entry<Sheet, EvaluationSheet> getInstance() {
+ HSSFSheet sheet = new HSSFWorkbook().createSheet();
+ return new AbstractMap.SimpleEntry<>(sheet, new HSSFEvaluationSheet(sheet));
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.usermodel;
+
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public abstract class BaseTestXEvaluationSheet {
+ /**
+ * Get a pair of underlying sheet and evaluation sheet.
+ */
+ protected abstract Map.Entry<Sheet, EvaluationSheet> getInstance();
+
+ @Test
+ public void lastRowNumIsUpdatedFromUnderlyingSheet_bug62993() {
+ Map.Entry<Sheet, EvaluationSheet> sheetPair = getInstance();
+ Sheet underlyingSheet = sheetPair.getKey();
+ EvaluationSheet instance = sheetPair.getValue();
+
+ assertEquals(0, instance.getLastRowNum());
+
+ underlyingSheet.createRow(0);
+ underlyingSheet.createRow(1);
+ underlyingSheet.createRow(2);
+ assertEquals(2, instance.getLastRowNum());
+
+ underlyingSheet.removeRow(underlyingSheet.getRow(2));
+ assertEquals(1, instance.getLastRowNum());
+ }
+}