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
ecd2511317
commit
37f153c03a
@ -34,6 +34,7 @@
|
||||
|
||||
<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>
|
||||
|
@ -28,7 +28,7 @@ final class PlainCellCache {
|
||||
|
||||
public static final class Loc {
|
||||
|
||||
private final int _bookSheetColumn;
|
||||
private final long _bookSheetColumn;
|
||||
|
||||
private final int _rowIndex;
|
||||
|
||||
@ -37,18 +37,19 @@ final class PlainCellCache {
|
||||
_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) {
|
||||
@ -60,9 +61,18 @@ final class PlainCellCache {
|
||||
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;
|
||||
|
@ -46,7 +46,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
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
|
||||
@ -696,4 +696,82 @@ public class TestEvaluationCache extends TestCase {
|
||||
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
Block a user