<changes>
<release version="3.8-beta4" date="2011-??-??">
+ <action dev="poi-developers" type="fix">51448 - Avoid exception when evaluating workbooks with more than 256 sheets </action>
<action dev="poi-developers" type="fix">51458 - Correct BitField wrapping when setting large values</action>
<action dev="poi-developers" type="add">51460 - Improve HSSF performance when loading very long rows, by switching the CellValue array to an iterator</action>
<action dev="poi-developers" type="fix">51444 - Prevent corrupted output when saving files created by LibreOffice 3.3 </action>
public static final class Loc {
- private final int _bookSheetColumn;
+ private final long _bookSheetColumn;
private final int _rowIndex;
_rowIndex = rowIndex;
}
- public static int toBookSheetColumn(int bookIndex, int sheetIndex, int columnIndex) {
- return ((bookIndex & 0x00FF) << 24) + ((sheetIndex & 0x00FF) << 16)
- + ((columnIndex & 0xFFFF) << 0);
+ public static long toBookSheetColumn(int bookIndex, int sheetIndex, int columnIndex) {
+ return ((bookIndex & 0xFFFFl) << 48) +
+ ((sheetIndex & 0xFFFFl) << 32) +
+ ((columnIndex & 0xFFFFl) << 0);
}
- public Loc(int bookSheetColumn, int rowIndex) {
+ public Loc(long bookSheetColumn, int rowIndex) {
_bookSheetColumn = bookSheetColumn;
_rowIndex = rowIndex;
}
public int hashCode() {
- return _bookSheetColumn + 17 * _rowIndex;
+ return (int)(_bookSheetColumn ^ (_bookSheetColumn >>> 32)) + 17 * _rowIndex;
}
public boolean equals(Object obj) {
public int getRowIndex() {
return _rowIndex;
}
+
public int getColumnIndex() {
- return _bookSheetColumn & 0x000FFFF;
+ return (int)(_bookSheetColumn & 0x000FFFF);
}
+
+ public int getSheetIndex() {
+ return (int)((_bookSheetColumn >> 32) & 0xFFFF);
+ }
+
+ public int getBookIndex() {
+ return (int)((_bookSheetColumn >> 48) & 0xFFFF);
+ }
}
private Map<Loc, PlainValueCellCacheEntry> _plainValueEntriesByLoc;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
import org.apache.poi.ss.formula.PlainCellCache.Loc;
-import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.*;
/**
* Tests {@link org.apache.poi.ss.formula.EvaluationCache}. Makes sure that where possible (previously calculated) cached
ps.println('"' + log[i] + "\",");
}
}
+
+ private static void testPlainValueCache(Workbook wb, int numberOfSheets) {
+
+ Row row;
+ Cell cell;
+
+ //create summary sheet
+ Sheet summary = wb.createSheet("summary");
+ wb.setActiveSheet(wb.getSheetIndex(summary));
+
+ //formula referring all sheets created below
+ row = summary.createRow(0);
+ Cell summaryCell = row.createCell(0);
+ summaryCell.setCellFormula("SUM(A2:A" + (numberOfSheets + 2) + ")");
+
+
+ //create sheets with cells having (different) numbers
+ // and add a row to summary
+ for (int i = 1; i < numberOfSheets; i++) {
+ Sheet sheet = wb.createSheet("new" + i);
+
+ row = sheet.createRow(0);
+ cell = row.createCell(0);
+ cell.setCellValue(i);
+
+ row = summary.createRow(i);
+ cell = row.createCell(0);
+ cell.setCellFormula("new" + i + "!A1");
+
+ }
+
+
+ //calculate
+ FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
+ evaluator.evaluateFormulaCell(summaryCell);
+ }
+
+
+ public void testPlainValueCache() {
+
+ Workbook wb = new HSSFWorkbook();
+ int numberOfSheets = 4098; // Bug 51448 reported that Evaluation Cache got messed up after 256 sheets
+
+ Row row;
+ Cell cell;
+
+ //create summary sheet
+ Sheet summary = wb.createSheet("summary");
+ wb.setActiveSheet(wb.getSheetIndex(summary));
+
+ //formula referring all sheets created below
+ row = summary.createRow(0);
+ Cell summaryCell = row.createCell(0);
+ summaryCell.setCellFormula("SUM(A2:A" + (numberOfSheets + 2) + ")");
+
+
+ //create sheets with cells having (different) numbers
+ // and add a row to summary
+ for (int i = 1; i < numberOfSheets; i++) {
+ Sheet sheet = wb.createSheet("new" + i);
+
+ row = sheet.createRow(0);
+ cell = row.createCell(0);
+ cell.setCellValue(i);
+
+ row = summary.createRow(i);
+ cell = row.createCell(0);
+ cell.setCellFormula("new" + i + "!A1");
+
+ }
+
+
+ //calculate
+ FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
+ evaluator.evaluateFormulaCell(summaryCell);
+ assertEquals(8394753.0, summaryCell.getNumericCellValue());
+ }
+
}
--- /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.formula;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
+import org.apache.poi.ss.formula.PlainCellCache.Loc;
+import org.apache.poi.ss.formula.eval.*;
+import org.apache.poi.ss.formula.ptg.Ptg;
+import org.apache.poi.ss.usermodel.CellValue;
+
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * @author Yegor Kozlov
+ */
+public class TestPlainCellCache extends TestCase {
+
+ /**
+ *
+ */
+ public void testLoc(){
+ PlainCellCache cache = new PlainCellCache();
+ for (int bookIndex = 0; bookIndex < 0x1000; bookIndex += 0x100) {
+ for (int sheetIndex = 0; sheetIndex < 0x1000; sheetIndex += 0x100) {
+ for (int rowIndex = 0; rowIndex < 0x100000; rowIndex += 0x1000) {
+ for (int columnIndex = 0; columnIndex < 0x4000; columnIndex += 0x100) {
+ Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
+ assertEquals(bookIndex, loc.getBookIndex());
+ assertEquals(sheetIndex, loc.getSheetIndex());
+ assertEquals(rowIndex, loc.getRowIndex());
+ assertEquals(columnIndex, loc.getColumnIndex());
+
+ Loc sameLoc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
+ assertEquals(loc.hashCode(), sameLoc.hashCode());
+ assertTrue(loc.equals(sameLoc));
+
+ assertNull(cache.get(loc));
+ PlainValueCellCacheEntry entry = new PlainValueCellCacheEntry(new NumberEval(0));
+ cache.put(loc, entry);
+ assertSame(entry, cache.get(loc));
+ cache.remove(loc);
+ assertNull(cache.get(loc));
+
+ cache.put(loc, entry);
+ }
+ cache.clear();
+ }
+ }
+
+ }
+ }
+}