mirror of https://github.com/apache/poi.git
Bug 51448 - Avoid exception when evaluating workbooks with more than 256 sheets
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1142181 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3fc8c3b1b7
commit
16bee58c25
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.8-beta4" date="2011-??-??">
|
<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="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="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>
|
<action dev="poi-developers" type="fix">51444 - Prevent corrupted output when saving files created by LibreOffice 3.3 </action>
|
||||||
|
|
|
@ -28,7 +28,7 @@ final class PlainCellCache {
|
||||||
|
|
||||||
public static final class Loc {
|
public static final class Loc {
|
||||||
|
|
||||||
private final int _bookSheetColumn;
|
private final long _bookSheetColumn;
|
||||||
|
|
||||||
private final int _rowIndex;
|
private final int _rowIndex;
|
||||||
|
|
||||||
|
@ -37,18 +37,19 @@ final class PlainCellCache {
|
||||||
_rowIndex = rowIndex;
|
_rowIndex = rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int toBookSheetColumn(int bookIndex, int sheetIndex, int columnIndex) {
|
public static long toBookSheetColumn(int bookIndex, int sheetIndex, int columnIndex) {
|
||||||
return ((bookIndex & 0x00FF) << 24) + ((sheetIndex & 0x00FF) << 16)
|
return ((bookIndex & 0xFFFFl) << 48) +
|
||||||
+ ((columnIndex & 0xFFFF) << 0);
|
((sheetIndex & 0xFFFFl) << 32) +
|
||||||
|
((columnIndex & 0xFFFFl) << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Loc(int bookSheetColumn, int rowIndex) {
|
public Loc(long bookSheetColumn, int rowIndex) {
|
||||||
_bookSheetColumn = bookSheetColumn;
|
_bookSheetColumn = bookSheetColumn;
|
||||||
_rowIndex = rowIndex;
|
_rowIndex = rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return _bookSheetColumn + 17 * _rowIndex;
|
return (int)(_bookSheetColumn ^ (_bookSheetColumn >>> 32)) + 17 * _rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
|
@ -60,9 +61,18 @@ final class PlainCellCache {
|
||||||
public int getRowIndex() {
|
public int getRowIndex() {
|
||||||
return _rowIndex;
|
return _rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getColumnIndex() {
|
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;
|
private Map<Loc, PlainValueCellCacheEntry> _plainValueEntriesByLoc;
|
||||||
|
|
|
@ -46,7 +46,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.hssf.util.CellReference;
|
import org.apache.poi.hssf.util.CellReference;
|
||||||
import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
|
import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
|
||||||
import org.apache.poi.ss.formula.PlainCellCache.Loc;
|
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
|
* Tests {@link org.apache.poi.ss.formula.EvaluationCache}. Makes sure that where possible (previously calculated) cached
|
||||||
|
@ -696,4 +696,82 @@ public class TestEvaluationCache extends TestCase {
|
||||||
ps.println('"' + log[i] + "\",");
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* ====================================================================
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue