Fix inconsistent whitespace/indents
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1695604 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
83bf96035c
commit
a87cdf35cd
@ -48,409 +48,405 @@ import org.apache.poi.ss.util.CellReference;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class TestFormulaEvaluatorBugs extends TestCase {
|
public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||||
|
private static final boolean OUTPUT_TEST_FILES = false;
|
||||||
|
private String tmpDirName;
|
||||||
|
|
||||||
private static final boolean OUTPUT_TEST_FILES = false;
|
protected void setUp() {
|
||||||
private String tmpDirName;
|
tmpDirName = System.getProperty("java.io.tmpdir");
|
||||||
|
}
|
||||||
|
|
||||||
protected void setUp() {
|
/**
|
||||||
tmpDirName = System.getProperty("java.io.tmpdir");
|
* An odd problem with evaluateFormulaCell giving the
|
||||||
}
|
* right values when file is opened, but changes
|
||||||
|
* to the source data in some versions of excel
|
||||||
|
* doesn't cause them to be updated. However, other
|
||||||
|
* versions of excel, and gnumeric, work just fine
|
||||||
|
* WARNING - tedious bug where you actually have to
|
||||||
|
* open up excel
|
||||||
|
*/
|
||||||
|
public void test44636() throws Exception {
|
||||||
|
// Open the existing file, tweak one value and
|
||||||
|
// re-calculate
|
||||||
|
|
||||||
/**
|
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44636.xls");
|
||||||
* An odd problem with evaluateFormulaCell giving the
|
HSSFSheet sheet = wb.getSheetAt(0);
|
||||||
* right values when file is opened, but changes
|
HSSFRow row = sheet.getRow(0);
|
||||||
* to the source data in some versions of excel
|
|
||||||
* doesn't cause them to be updated. However, other
|
|
||||||
* versions of excel, and gnumeric, work just fine
|
|
||||||
* WARNING - tedious bug where you actually have to
|
|
||||||
* open up excel
|
|
||||||
*/
|
|
||||||
public void test44636() throws Exception {
|
|
||||||
// Open the existing file, tweak one value and
|
|
||||||
// re-calculate
|
|
||||||
|
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44636.xls");
|
row.getCell(0).setCellValue(4.2);
|
||||||
HSSFSheet sheet = wb.getSheetAt(0);
|
row.getCell(2).setCellValue(25);
|
||||||
HSSFRow row = sheet.getRow(0);
|
|
||||||
|
|
||||||
row.getCell(0).setCellValue(4.2);
|
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
||||||
row.getCell(2).setCellValue(25);
|
assertEquals(4.2 * 25, row.getCell(3).getNumericCellValue(), 0.0001);
|
||||||
|
|
||||||
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
FileOutputStream out;
|
||||||
assertEquals(4.2 * 25, row.getCell(3).getNumericCellValue(), 0.0001);
|
if (OUTPUT_TEST_FILES) {
|
||||||
|
// Save
|
||||||
|
File existing = new File(tmpDirName, "44636-existing.xls");
|
||||||
|
out = new FileOutputStream(existing);
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
System.err.println("Existing file for bug #44636 written to " + existing.toString());
|
||||||
|
}
|
||||||
|
// Now, do a new file from scratch
|
||||||
|
wb = new HSSFWorkbook();
|
||||||
|
sheet = wb.createSheet();
|
||||||
|
|
||||||
FileOutputStream out;
|
row = sheet.createRow(0);
|
||||||
if (OUTPUT_TEST_FILES) {
|
row.createCell(0).setCellValue(1.2);
|
||||||
// Save
|
row.createCell(1).setCellValue(4.2);
|
||||||
File existing = new File(tmpDirName, "44636-existing.xls");
|
|
||||||
out = new FileOutputStream(existing);
|
|
||||||
wb.write(out);
|
|
||||||
out.close();
|
|
||||||
System.err.println("Existing file for bug #44636 written to " + existing.toString());
|
|
||||||
}
|
|
||||||
// Now, do a new file from scratch
|
|
||||||
wb = new HSSFWorkbook();
|
|
||||||
sheet = wb.createSheet();
|
|
||||||
|
|
||||||
row = sheet.createRow(0);
|
row = sheet.createRow(1);
|
||||||
row.createCell(0).setCellValue(1.2);
|
row.createCell(0).setCellFormula("SUM(A1:B1)");
|
||||||
row.createCell(1).setCellValue(4.2);
|
|
||||||
|
|
||||||
row = sheet.createRow(1);
|
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
||||||
row.createCell(0).setCellFormula("SUM(A1:B1)");
|
assertEquals(5.4, row.getCell(0).getNumericCellValue(), 0.0001);
|
||||||
|
|
||||||
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
if (OUTPUT_TEST_FILES) {
|
||||||
assertEquals(5.4, row.getCell(0).getNumericCellValue(), 0.0001);
|
// Save
|
||||||
|
File scratch = new File(tmpDirName, "44636-scratch.xls");
|
||||||
|
out = new FileOutputStream(scratch);
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
System.err.println("New file for bug #44636 written to " + scratch.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (OUTPUT_TEST_FILES) {
|
/**
|
||||||
// Save
|
* Bug 44297: 32767+32768 is evaluated to -1
|
||||||
File scratch = new File(tmpDirName, "44636-scratch.xls");
|
* Fix: IntPtg must operate with unsigned short. Reading signed short results in incorrect formula calculation
|
||||||
out = new FileOutputStream(scratch);
|
* if a formula has values in the interval [Short.MAX_VALUE, (Short.MAX_VALUE+1)*2]
|
||||||
wb.write(out);
|
*
|
||||||
out.close();
|
* @author Yegor Kozlov
|
||||||
System.err.println("New file for bug #44636 written to " + scratch.toString());
|
*/
|
||||||
}
|
public void test44297() {
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44297.xls");
|
||||||
* Bug 44297: 32767+32768 is evaluated to -1
|
|
||||||
* Fix: IntPtg must operate with unsigned short. Reading signed short results in incorrect formula calculation
|
|
||||||
* if a formula has values in the interval [Short.MAX_VALUE, (Short.MAX_VALUE+1)*2]
|
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
|
||||||
public void test44297() {
|
|
||||||
|
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44297.xls");
|
HSSFRow row;
|
||||||
|
HSSFCell cell;
|
||||||
|
|
||||||
HSSFRow row;
|
HSSFSheet sheet = wb.getSheetAt(0);
|
||||||
HSSFCell cell;
|
|
||||||
|
|
||||||
HSSFSheet sheet = wb.getSheetAt(0);
|
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(wb);
|
||||||
|
|
||||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(wb);
|
row = sheet.getRow(0);
|
||||||
|
cell = row.getCell(0);
|
||||||
|
assertEquals("31+46", cell.getCellFormula());
|
||||||
|
assertEquals(77, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(0);
|
row = sheet.getRow(1);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("31+46", cell.getCellFormula());
|
assertEquals("30+53", cell.getCellFormula());
|
||||||
assertEquals(77, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(83, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(1);
|
row = sheet.getRow(2);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("30+53", cell.getCellFormula());
|
assertEquals("SUM(A1:A2)", cell.getCellFormula());
|
||||||
assertEquals(83, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(160, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(2);
|
row = sheet.getRow(4);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("SUM(A1:A2)", cell.getCellFormula());
|
assertEquals("32767+32768", cell.getCellFormula());
|
||||||
assertEquals(160, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(65535, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(4);
|
row = sheet.getRow(7);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("32767+32768", cell.getCellFormula());
|
assertEquals("32744+42333", cell.getCellFormula());
|
||||||
assertEquals(65535, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(75077, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(7);
|
row = sheet.getRow(8);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("32744+42333", cell.getCellFormula());
|
assertEquals("327680/32768", cell.getCellFormula());
|
||||||
assertEquals(75077, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(10, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(8);
|
row = sheet.getRow(9);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("327680/32768", cell.getCellFormula());
|
assertEquals("32767+32769", cell.getCellFormula());
|
||||||
assertEquals(10, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(65536, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(9);
|
row = sheet.getRow(10);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("32767+32769", cell.getCellFormula());
|
assertEquals("35000+36000", cell.getCellFormula());
|
||||||
assertEquals(65536, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(71000, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
|
||||||
row = sheet.getRow(10);
|
row = sheet.getRow(11);
|
||||||
cell = row.getCell(0);
|
cell = row.getCell(0);
|
||||||
assertEquals("35000+36000", cell.getCellFormula());
|
assertEquals("-1000000-3000000", cell.getCellFormula());
|
||||||
assertEquals(71000, eva.evaluate(cell).getNumberValue(), 0);
|
assertEquals(-4000000, eva.evaluate(cell).getNumberValue(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
row = sheet.getRow(11);
|
/**
|
||||||
cell = row.getCell(0);
|
* Bug 44410: SUM(C:C) is valid in excel, and means a sum
|
||||||
assertEquals("-1000000-3000000", cell.getCellFormula());
|
* of all the rows in Column C
|
||||||
assertEquals(-4000000, eva.evaluate(cell).getNumberValue(), 0);
|
*/
|
||||||
}
|
public void test44410() {
|
||||||
|
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SingleLetterRanges.xls");
|
||||||
|
|
||||||
/**
|
HSSFSheet sheet = wb.getSheetAt(0);
|
||||||
* Bug 44410: SUM(C:C) is valid in excel, and means a sum
|
|
||||||
* of all the rows in Column C
|
|
||||||
*
|
|
||||||
* @author Nick Burch
|
|
||||||
*/
|
|
||||||
public void test44410() {
|
|
||||||
|
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SingleLetterRanges.xls");
|
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(wb);
|
||||||
|
|
||||||
HSSFSheet sheet = wb.getSheetAt(0);
|
// =index(C:C,2,1) -> 2
|
||||||
|
HSSFRow rowIDX = sheet.getRow(3);
|
||||||
|
// =sum(C:C) -> 6
|
||||||
|
HSSFRow rowSUM = sheet.getRow(4);
|
||||||
|
// =sum(C:D) -> 66
|
||||||
|
HSSFRow rowSUM2D = sheet.getRow(5);
|
||||||
|
|
||||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(wb);
|
// Test the sum
|
||||||
|
HSSFCell cellSUM = rowSUM.getCell(0);
|
||||||
|
|
||||||
// =index(C:C,2,1) -> 2
|
FormulaRecordAggregate frec = (FormulaRecordAggregate) cellSUM.getCellValueRecord();
|
||||||
HSSFRow rowIDX = sheet.getRow(3);
|
Ptg[] ops = frec.getFormulaRecord().getParsedExpression();
|
||||||
// =sum(C:C) -> 6
|
assertEquals(2, ops.length);
|
||||||
HSSFRow rowSUM = sheet.getRow(4);
|
assertEquals(AreaPtg.class, ops[0].getClass());
|
||||||
// =sum(C:D) -> 66
|
assertEquals(FuncVarPtg.class, ops[1].getClass());
|
||||||
HSSFRow rowSUM2D = sheet.getRow(5);
|
|
||||||
|
|
||||||
// Test the sum
|
// Actually stored as C1 to C65536
|
||||||
HSSFCell cellSUM = rowSUM.getCell(0);
|
// (last row is -1 === 65535)
|
||||||
|
AreaPtg ptg = (AreaPtg) ops[0];
|
||||||
|
assertEquals(2, ptg.getFirstColumn());
|
||||||
|
assertEquals(2, ptg.getLastColumn());
|
||||||
|
assertEquals(0, ptg.getFirstRow());
|
||||||
|
assertEquals(65535, ptg.getLastRow());
|
||||||
|
assertEquals("C:C", ptg.toFormulaString());
|
||||||
|
|
||||||
FormulaRecordAggregate frec = (FormulaRecordAggregate) cellSUM.getCellValueRecord();
|
// Will show as C:C, but won't know how many
|
||||||
Ptg[] ops = frec.getFormulaRecord().getParsedExpression();
|
// rows it covers as we don't have the sheet
|
||||||
assertEquals(2, ops.length);
|
// to hand when turning the Ptgs into a string
|
||||||
assertEquals(AreaPtg.class, ops[0].getClass());
|
assertEquals("SUM(C:C)", cellSUM.getCellFormula());
|
||||||
assertEquals(FuncVarPtg.class, ops[1].getClass());
|
|
||||||
|
|
||||||
// Actually stored as C1 to C65536
|
// But the evaluator knows the sheet, so it
|
||||||
// (last row is -1 === 65535)
|
// can do it properly
|
||||||
AreaPtg ptg = (AreaPtg) ops[0];
|
assertEquals(6, eva.evaluate(cellSUM).getNumberValue(), 0);
|
||||||
assertEquals(2, ptg.getFirstColumn());
|
|
||||||
assertEquals(2, ptg.getLastColumn());
|
|
||||||
assertEquals(0, ptg.getFirstRow());
|
|
||||||
assertEquals(65535, ptg.getLastRow());
|
|
||||||
assertEquals("C:C", ptg.toFormulaString());
|
|
||||||
|
|
||||||
// Will show as C:C, but won't know how many
|
// Test the index
|
||||||
// rows it covers as we don't have the sheet
|
// Again, the formula string will be right but
|
||||||
// to hand when turning the Ptgs into a string
|
// lacking row count, evaluated will be right
|
||||||
assertEquals("SUM(C:C)", cellSUM.getCellFormula());
|
HSSFCell cellIDX = rowIDX.getCell(0);
|
||||||
|
assertEquals("INDEX(C:C,2,1)", cellIDX.getCellFormula());
|
||||||
|
assertEquals(2, eva.evaluate(cellIDX).getNumberValue(), 0);
|
||||||
|
|
||||||
// But the evaluator knows the sheet, so it
|
// Across two colums
|
||||||
// can do it properly
|
HSSFCell cellSUM2D = rowSUM2D.getCell(0);
|
||||||
assertEquals(6, eva.evaluate(cellSUM).getNumberValue(), 0);
|
assertEquals("SUM(C:D)", cellSUM2D.getCellFormula());
|
||||||
|
assertEquals(66, eva.evaluate(cellSUM2D).getNumberValue(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Test the index
|
/**
|
||||||
// Again, the formula string will be right but
|
* Tests that we can evaluate boolean cells properly
|
||||||
// lacking row count, evaluated will be right
|
*/
|
||||||
HSSFCell cellIDX = rowIDX.getCell(0);
|
public void testEvaluateBooleanInCell_bug44508() {
|
||||||
assertEquals("INDEX(C:C,2,1)", cellIDX.getCellFormula());
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
assertEquals(2, eva.evaluate(cellIDX).getNumberValue(), 0);
|
HSSFSheet sheet = wb.createSheet();
|
||||||
|
wb.setSheetName(0, "Sheet1");
|
||||||
|
HSSFRow row = sheet.createRow(0);
|
||||||
|
HSSFCell cell = row.createCell(0);
|
||||||
|
|
||||||
// Across two colums
|
cell.setCellFormula("1=1");
|
||||||
HSSFCell cellSUM2D = rowSUM2D.getCell(0);
|
|
||||||
assertEquals("SUM(C:D)", cellSUM2D.getCellFormula());
|
|
||||||
assertEquals(66, eva.evaluate(cellSUM2D).getNumberValue(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||||
* Tests that we can evaluate boolean cells properly
|
try {
|
||||||
*/
|
fe.evaluateInCell(cell);
|
||||||
public void testEvaluateBooleanInCell_bug44508() {
|
} catch (NumberFormatException e) {
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
fail("Identified bug 44508");
|
||||||
HSSFSheet sheet = wb.createSheet();
|
}
|
||||||
wb.setSheetName(0, "Sheet1");
|
assertEquals(true, cell.getBooleanCellValue());
|
||||||
HSSFRow row = sheet.createRow(0);
|
}
|
||||||
HSSFCell cell = row.createCell(0);
|
|
||||||
|
|
||||||
cell.setCellFormula("1=1");
|
public void testClassCast_bug44861() {
|
||||||
|
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44861.xls");
|
||||||
|
|
||||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
// Check direct
|
||||||
try {
|
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
||||||
fe.evaluateInCell(cell);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
fail("Identified bug 44508");
|
|
||||||
}
|
|
||||||
assertEquals(true, cell.getBooleanCellValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testClassCast_bug44861() {
|
// And via calls
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44861.xls");
|
int numSheets = wb.getNumberOfSheets();
|
||||||
|
for (int i = 0; i < numSheets; i++) {
|
||||||
|
HSSFSheet s = wb.getSheetAt(i);
|
||||||
|
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb);
|
||||||
|
|
||||||
// Check direct
|
for (Iterator<Row> rows = s.rowIterator(); rows.hasNext();) {
|
||||||
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
HSSFRow r = (HSSFRow)rows.next();
|
||||||
|
for (Iterator<Cell> cells = r.cellIterator(); cells.hasNext();) {
|
||||||
|
HSSFCell c = (HSSFCell)cells.next();
|
||||||
|
eval.evaluateFormulaCell(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// And via calls
|
public void testEvaluateInCellWithErrorCode_bug44950() {
|
||||||
int numSheets = wb.getNumberOfSheets();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
for (int i = 0; i < numSheets; i++) {
|
HSSFSheet sheet = wb.createSheet("Sheet1");
|
||||||
HSSFSheet s = wb.getSheetAt(i);
|
HSSFRow row = sheet.createRow(1);
|
||||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb);
|
HSSFCell cell = row.createCell(0);
|
||||||
|
cell.setCellFormula("na()"); // this formula evaluates to an Excel error code '#N/A'
|
||||||
|
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||||
|
try {
|
||||||
|
fe.evaluateInCell(cell);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
if (e.getMessage().equals("You cannot get an error value from a non-error cell")) {
|
||||||
|
throw new AssertionFailedError("Identified bug 44950 b");
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Iterator<Row> rows = s.rowIterator(); rows.hasNext();) {
|
public void testDateWithNegativeParts_bug48528() {
|
||||||
HSSFRow r = (HSSFRow)rows.next();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
for (Iterator<Cell> cells = r.cellIterator(); cells.hasNext();) {
|
HSSFSheet sheet = wb.createSheet("Sheet1");
|
||||||
HSSFCell c = (HSSFCell)cells.next();
|
HSSFRow row = sheet.createRow(1);
|
||||||
eval.evaluateFormulaCell(c);
|
HSSFCell cell = row.createCell(0);
|
||||||
}
|
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testEvaluateInCellWithErrorCode_bug44950() {
|
// 5th Feb 2012 = 40944
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
// 1st Feb 2012 = 40940
|
||||||
HSSFSheet sheet = wb.createSheet("Sheet1");
|
// 5th Jan 2012 = 40913
|
||||||
HSSFRow row = sheet.createRow(1);
|
// 5th Dec 2011 = 40882
|
||||||
HSSFCell cell = row.createCell(0);
|
// 5th Feb 2011 = 40579
|
||||||
cell.setCellFormula("na()"); // this formula evaluates to an Excel error code '#N/A'
|
|
||||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
|
||||||
try {
|
|
||||||
fe.evaluateInCell(cell);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
if (e.getMessage().equals("You cannot get an error value from a non-error cell")) {
|
|
||||||
throw new AssertionFailedError("Identified bug 44950 b");
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDateWithNegativeParts_bug48528() {
|
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
|
||||||
HSSFSheet sheet = wb.createSheet("Sheet1");
|
|
||||||
HSSFRow row = sheet.createRow(1);
|
|
||||||
HSSFCell cell = row.createCell(0);
|
|
||||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
|
||||||
|
|
||||||
// 5th Feb 2012 = 40944
|
|
||||||
// 1st Feb 2012 = 40940
|
|
||||||
// 5th Jan 2012 = 40913
|
|
||||||
// 5th Dec 2011 = 40882
|
|
||||||
// 5th Feb 2011 = 40579
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2,1)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40940.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2,1+4)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40944.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2-1,1+4)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2,1-27)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2-2,1+4)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2,1-58)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
|
|
||||||
cell.setCellFormula("DATE(2012,2-12,1+4)");
|
|
||||||
fe.notifyUpdateCell(cell);
|
|
||||||
assertEquals(40579.0, fe.evaluate(cell).getNumberValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class EvalListener extends EvaluationListener {
|
cell.setCellFormula("DATE(2012,2,1)");
|
||||||
private int _countCacheHits;
|
fe.notifyUpdateCell(cell);
|
||||||
private int _countCacheMisses;
|
assertEquals(40940.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
public EvalListener() {
|
cell.setCellFormula("DATE(2012,2,1+4)");
|
||||||
_countCacheHits = 0;
|
fe.notifyUpdateCell(cell);
|
||||||
_countCacheMisses = 0;
|
assertEquals(40944.0, fe.evaluate(cell).getNumberValue());
|
||||||
}
|
|
||||||
public int getCountCacheHits() {
|
|
||||||
return _countCacheHits;
|
|
||||||
}
|
|
||||||
public int getCountCacheMisses() {
|
|
||||||
return _countCacheMisses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCacheHit(int sheetIndex, int srcRowNum, int srcColNum, ValueEval result) {
|
cell.setCellFormula("DATE(2012,2-1,1+4)");
|
||||||
_countCacheHits++;
|
fe.notifyUpdateCell(cell);
|
||||||
}
|
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
|
||||||
public void onStartEvaluate(EvaluationCell cell, ICacheEntry entry) {
|
|
||||||
_countCacheMisses++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
cell.setCellFormula("DATE(2012,2,1-27)");
|
||||||
* The HSSFFormula evaluator performance benefits greatly from caching of intermediate cell values
|
fe.notifyUpdateCell(cell);
|
||||||
*/
|
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
|
||||||
public void testSlowEvaluate45376() {
|
|
||||||
/*
|
|
||||||
* Note - to observe behaviour without caching, disable the call to
|
|
||||||
* updateValue() from FormulaCellCacheEntry.updateFormulaResult().
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Firstly set up a sequence of formula cells where each depends on the previous multiple
|
cell.setCellFormula("DATE(2012,2-2,1+4)");
|
||||||
// times. Without caching, each subsequent cell take about 4 times longer to evaluate.
|
fe.notifyUpdateCell(cell);
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
|
||||||
HSSFSheet sheet = wb.createSheet("Sheet1");
|
|
||||||
HSSFRow row = sheet.createRow(0);
|
|
||||||
for(int i=1; i<10; i++) {
|
|
||||||
HSSFCell cell = row.createCell(i);
|
|
||||||
char prevCol = (char) ('A' + i-1);
|
|
||||||
String prevCell = prevCol + "1";
|
|
||||||
// this formula is inspired by the offending formula of the attachment for bug 45376
|
|
||||||
// IF(DATE(YEAR(A1),MONTH(A1)+1,1)<=$D$3,DATE(YEAR(A1),MONTH(A1)+1,1),NA()) etc
|
|
||||||
String formula = "IF(DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1)<=$D$3," +
|
|
||||||
"DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1),NA())";
|
|
||||||
cell.setCellFormula(formula);
|
|
||||||
}
|
|
||||||
Calendar cal = new GregorianCalendar(2000, 0, 1, 0, 0, 0);
|
|
||||||
row.createCell(0).setCellValue(cal);
|
|
||||||
|
|
||||||
// Choose cell A9 instead of A10, so that the failing test case doesn't take too long to execute.
|
cell.setCellFormula("DATE(2012,2,1-58)");
|
||||||
HSSFCell cell = row.getCell(8);
|
fe.notifyUpdateCell(cell);
|
||||||
EvalListener evalListener = new EvalListener();
|
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
|
||||||
WorkbookEvaluator evaluator = WorkbookEvaluatorTestHelper.createEvaluator(wb, evalListener);
|
|
||||||
ValueEval ve = evaluator.evaluate(HSSFEvaluationTestHelper.wrapCell(cell));
|
|
||||||
int evalCount = evalListener.getCountCacheMisses();
|
|
||||||
if (evalCount > 10) {
|
|
||||||
// Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes
|
|
||||||
// much time (~3 sec on Core 2 Duo 2.2GHz)
|
|
||||||
// short-circuit-if optimisation cuts this down to 255 evaluations which is still too high
|
|
||||||
System.err.println("Cell A9 took " + evalCount + " intermediate evaluations");
|
|
||||||
throw new AssertionFailedError("Identifed bug 45376 - Formula evaluator should cache values");
|
|
||||||
}
|
|
||||||
// With caching, the evaluationCount is 8 which is exactly the
|
|
||||||
// number of formula cells that needed to be evaluated.
|
|
||||||
assertEquals(8, evalCount);
|
|
||||||
|
|
||||||
// The cache hits would be 24 if fully evaluating all arguments of the
|
cell.setCellFormula("DATE(2012,2-12,1+4)");
|
||||||
// "IF()" functions (Each of the 8 formulas has 4 refs to formula cells
|
fe.notifyUpdateCell(cell);
|
||||||
// which result in 1 cache miss and 3 cache hits). However with the
|
assertEquals(40579.0, fe.evaluate(cell).getNumberValue());
|
||||||
// short-circuit-if optimisation, 2 of the cell refs get skipped
|
}
|
||||||
// reducing this metric 8.
|
|
||||||
assertEquals(8, evalListener.getCountCacheHits());
|
|
||||||
|
|
||||||
// confirm the evaluation result too
|
private static final class EvalListener extends EvaluationListener {
|
||||||
assertEquals(ErrorEval.NA, ve);
|
private int _countCacheHits;
|
||||||
}
|
private int _countCacheMisses;
|
||||||
|
|
||||||
@SuppressWarnings("resource")
|
public EvalListener() {
|
||||||
|
_countCacheHits = 0;
|
||||||
|
_countCacheMisses = 0;
|
||||||
|
}
|
||||||
|
public int getCountCacheHits() {
|
||||||
|
return _countCacheHits;
|
||||||
|
}
|
||||||
|
public int getCountCacheMisses() {
|
||||||
|
return _countCacheMisses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCacheHit(int sheetIndex, int srcRowNum, int srcColNum, ValueEval result) {
|
||||||
|
_countCacheHits++;
|
||||||
|
}
|
||||||
|
public void onStartEvaluate(EvaluationCell cell, ICacheEntry entry) {
|
||||||
|
_countCacheMisses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HSSFFormula evaluator performance benefits greatly from caching of intermediate cell values
|
||||||
|
*/
|
||||||
|
public void testSlowEvaluate45376() {
|
||||||
|
/*
|
||||||
|
* Note - to observe behaviour without caching, disable the call to
|
||||||
|
* updateValue() from FormulaCellCacheEntry.updateFormulaResult().
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Firstly set up a sequence of formula cells where each depends on the previous multiple
|
||||||
|
// times. Without caching, each subsequent cell take about 4 times longer to evaluate.
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
HSSFSheet sheet = wb.createSheet("Sheet1");
|
||||||
|
HSSFRow row = sheet.createRow(0);
|
||||||
|
for(int i=1; i<10; i++) {
|
||||||
|
HSSFCell cell = row.createCell(i);
|
||||||
|
char prevCol = (char) ('A' + i-1);
|
||||||
|
String prevCell = prevCol + "1";
|
||||||
|
// this formula is inspired by the offending formula of the attachment for bug 45376
|
||||||
|
// IF(DATE(YEAR(A1),MONTH(A1)+1,1)<=$D$3,DATE(YEAR(A1),MONTH(A1)+1,1),NA()) etc
|
||||||
|
String formula = "IF(DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1)<=$D$3," +
|
||||||
|
"DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1),NA())";
|
||||||
|
cell.setCellFormula(formula);
|
||||||
|
}
|
||||||
|
Calendar cal = new GregorianCalendar(2000, 0, 1, 0, 0, 0);
|
||||||
|
row.createCell(0).setCellValue(cal);
|
||||||
|
|
||||||
|
// Choose cell A9 instead of A10, so that the failing test case doesn't take too long to execute.
|
||||||
|
HSSFCell cell = row.getCell(8);
|
||||||
|
EvalListener evalListener = new EvalListener();
|
||||||
|
WorkbookEvaluator evaluator = WorkbookEvaluatorTestHelper.createEvaluator(wb, evalListener);
|
||||||
|
ValueEval ve = evaluator.evaluate(HSSFEvaluationTestHelper.wrapCell(cell));
|
||||||
|
int evalCount = evalListener.getCountCacheMisses();
|
||||||
|
if (evalCount > 10) {
|
||||||
|
// Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes
|
||||||
|
// much time (~3 sec on Core 2 Duo 2.2GHz)
|
||||||
|
// short-circuit-if optimisation cuts this down to 255 evaluations which is still too high
|
||||||
|
System.err.println("Cell A9 took " + evalCount + " intermediate evaluations");
|
||||||
|
throw new AssertionFailedError("Identifed bug 45376 - Formula evaluator should cache values");
|
||||||
|
}
|
||||||
|
// With caching, the evaluationCount is 8 which is exactly the
|
||||||
|
// number of formula cells that needed to be evaluated.
|
||||||
|
assertEquals(8, evalCount);
|
||||||
|
|
||||||
|
// The cache hits would be 24 if fully evaluating all arguments of the
|
||||||
|
// "IF()" functions (Each of the 8 formulas has 4 refs to formula cells
|
||||||
|
// which result in 1 cache miss and 3 cache hits). However with the
|
||||||
|
// short-circuit-if optimisation, 2 of the cell refs get skipped
|
||||||
|
// reducing this metric 8.
|
||||||
|
assertEquals(8, evalListener.getCountCacheHits());
|
||||||
|
|
||||||
|
// confirm the evaluation result too
|
||||||
|
assertEquals(ErrorEval.NA, ve);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
public void test55747_55324() throws Exception {
|
public void test55747_55324() throws Exception {
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
HSSFFormulaEvaluator ev = wb.getCreationHelper().createFormulaEvaluator();
|
HSSFFormulaEvaluator ev = wb.getCreationHelper().createFormulaEvaluator();
|
||||||
HSSFSheet ws = wb.createSheet();
|
HSSFSheet ws = wb.createSheet();
|
||||||
HSSFRow row = ws.createRow(0);
|
HSSFRow row = ws.createRow(0);
|
||||||
HSSFCell cell;
|
HSSFCell cell;
|
||||||
|
|
||||||
// Our test value
|
// Our test value
|
||||||
cell = row.createCell(0);
|
cell = row.createCell(0);
|
||||||
cell.setCellValue("abc");
|
cell.setCellValue("abc");
|
||||||
|
|
||||||
// Lots of IF cases
|
// Lots of IF cases
|
||||||
|
|
||||||
cell = row.createCell(1);
|
cell = row.createCell(1);
|
||||||
cell.setCellFormula("IF(A1<>\"\",MID(A1,1,2),\"X\")");//if(expr,func,val)
|
cell.setCellFormula("IF(A1<>\"\",MID(A1,1,2),\"X\")");//if(expr,func,val)
|
||||||
|
|
||||||
cell = row.createCell(2);
|
cell = row.createCell(2);
|
||||||
cell.setCellFormula("IF(A1<>\"\",\"A\",\"B\")");// if(expr,val,val)
|
cell.setCellFormula("IF(A1<>\"\",\"A\",\"B\")");// if(expr,val,val)
|
||||||
|
|
||||||
cell = row.createCell(3);
|
cell = row.createCell(3);
|
||||||
cell.setCellFormula("IF(A1=\"\",\"X\",MID(A1,1,2))");//if(expr,val,func),
|
cell.setCellFormula("IF(A1=\"\",\"X\",MID(A1,1,2))");//if(expr,val,func),
|
||||||
|
|
||||||
cell = row.createCell(4);
|
cell = row.createCell(4);
|
||||||
cell.setCellFormula("IF(A1<>\"\",\"X\",MID(A1,1,2))");//if(expr,val,func),
|
cell.setCellFormula("IF(A1<>\"\",\"X\",MID(A1,1,2))");//if(expr,val,func),
|
||||||
|
|
||||||
cell = row.createCell(5);
|
cell = row.createCell(5);
|
||||||
cell.setCellFormula("IF(A1=\"\",MID(A1,1,2),MID(A1,2,2))");//if(exp,func,func)
|
cell.setCellFormula("IF(A1=\"\",MID(A1,1,2),MID(A1,2,2))");//if(exp,func,func)
|
||||||
cell = row.createCell(6);
|
cell = row.createCell(6);
|
||||||
cell.setCellFormula("IF(A1<>\"\",MID(A1,1,2),MID(A1,2,2))");//if(exp,func,func)
|
cell.setCellFormula("IF(A1<>\"\",MID(A1,1,2),MID(A1,2,2))");//if(exp,func,func)
|
||||||
|
|
||||||
cell = row.createCell(7);
|
cell = row.createCell(7);
|
||||||
cell.setCellFormula("IF(MID(A1,1,2)<>\"\",\"A\",\"B\")");//if(func_expr,val,val)
|
cell.setCellFormula("IF(MID(A1,1,2)<>\"\",\"A\",\"B\")");//if(func_expr,val,val)
|
||||||
|
|
||||||
// And some MID ones just to check
|
// And some MID ones just to check
|
||||||
row = ws.createRow(1);
|
row = ws.createRow(1);
|
||||||
cell = row.createCell(1);
|
cell = row.createCell(1);
|
||||||
@ -461,14 +457,14 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||||||
cell.setCellFormula("MID(A1,2,1)");
|
cell.setCellFormula("MID(A1,2,1)");
|
||||||
cell = row.createCell(4);
|
cell = row.createCell(4);
|
||||||
cell.setCellFormula("MID(A1,3,1)");
|
cell.setCellFormula("MID(A1,3,1)");
|
||||||
|
|
||||||
// Evaluate
|
// Evaluate
|
||||||
ev.evaluateAll();
|
ev.evaluateAll();
|
||||||
|
|
||||||
// Save and re-load
|
// Save and re-load
|
||||||
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
ws = wb.getSheetAt(0);
|
ws = wb.getSheetAt(0);
|
||||||
|
|
||||||
// Check the MID Ptgs in Row 2 have V RefPtgs for A1
|
// Check the MID Ptgs in Row 2 have V RefPtgs for A1
|
||||||
row = ws.getRow(1);
|
row = ws.getRow(1);
|
||||||
for (int i=1; i<=4; i++) {
|
for (int i=1; i<=4; i++) {
|
||||||
@ -479,21 +475,21 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||||||
assertEquals("MID", ((FuncPtg)ptgs[3]).getName());
|
assertEquals("MID", ((FuncPtg)ptgs[3]).getName());
|
||||||
assertRefPtgA1('V', ptgs, 0);
|
assertRefPtgA1('V', ptgs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now check the IF formulas
|
// Now check the IF formulas
|
||||||
row = ws.getRow(0);
|
row = ws.getRow(0);
|
||||||
|
|
||||||
// H1, MID is used in the expression IF checks, so A1 should be V
|
// H1, MID is used in the expression IF checks, so A1 should be V
|
||||||
cell = row.getCell(CellReference.convertColStringToIndex("H"));
|
cell = row.getCell(CellReference.convertColStringToIndex("H"));
|
||||||
assertRefPtgA1('V', getPtgs(cell), 0);
|
assertRefPtgA1('V', getPtgs(cell), 0);
|
||||||
|
|
||||||
// E1, MID is used in the FALSE route, so:
|
// E1, MID is used in the FALSE route, so:
|
||||||
// A1 should be V in the IF check
|
// A1 should be V in the IF check
|
||||||
// A1 should be R in the FALSE route
|
// A1 should be R in the FALSE route
|
||||||
cell = row.getCell(CellReference.convertColStringToIndex("E"));
|
cell = row.getCell(CellReference.convertColStringToIndex("E"));
|
||||||
assertRefPtgA1('V', getPtgs(cell), 0);
|
assertRefPtgA1('V', getPtgs(cell), 0);
|
||||||
assertRefPtgA1('R', getPtgs(cell), 6);
|
assertRefPtgA1('R', getPtgs(cell), 6);
|
||||||
|
|
||||||
// Check that, for B1, D1, F1 and G1, the references to A1
|
// Check that, for B1, D1, F1 and G1, the references to A1
|
||||||
// from all of IF check, True and False are V
|
// from all of IF check, True and False are V
|
||||||
cell = row.getCell(CellReference.convertColStringToIndex("B"));
|
cell = row.getCell(CellReference.convertColStringToIndex("B"));
|
||||||
@ -537,19 +533,19 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||||||
//FileOutputStream out = new FileOutputStream("/tmp/test.xls");
|
//FileOutputStream out = new FileOutputStream("/tmp/test.xls");
|
||||||
//wb.write(out);
|
//wb.write(out);
|
||||||
//out.close();
|
//out.close();
|
||||||
}
|
}
|
||||||
private Ptg[] getPtgs(HSSFCell cell) {
|
private Ptg[] getPtgs(HSSFCell cell) {
|
||||||
assertEquals(HSSFCell.CELL_TYPE_FORMULA, cell.getCellType());
|
assertEquals(HSSFCell.CELL_TYPE_FORMULA, cell.getCellType());
|
||||||
assertEquals(FormulaRecordAggregate.class, cell.getCellValueRecord().getClass());
|
assertEquals(FormulaRecordAggregate.class, cell.getCellValueRecord().getClass());
|
||||||
FormulaRecordAggregate agg = (FormulaRecordAggregate)cell.getCellValueRecord();
|
FormulaRecordAggregate agg = (FormulaRecordAggregate)cell.getCellValueRecord();
|
||||||
FormulaRecord rec = agg.getFormulaRecord();
|
FormulaRecord rec = agg.getFormulaRecord();
|
||||||
return rec.getParsedExpression();
|
return rec.getParsedExpression();
|
||||||
}
|
}
|
||||||
private void assertRefPtgA1(char rv, Ptg[] ptgs, int at) {
|
private void assertRefPtgA1(char rv, Ptg[] ptgs, int at) {
|
||||||
Ptg ptg = ptgs[at];
|
Ptg ptg = ptgs[at];
|
||||||
assertEquals(RefPtg.class, ptg.getClass());
|
assertEquals(RefPtg.class, ptg.getClass());
|
||||||
assertEquals(0, ((RefPtg)ptg).getRow());
|
assertEquals(0, ((RefPtg)ptg).getRow());
|
||||||
assertEquals(0, ((RefPtg)ptg).getColumn());
|
assertEquals(0, ((RefPtg)ptg).getColumn());
|
||||||
assertEquals(rv, ((RefPtg)ptg).getRVAType());
|
assertEquals(rv, ((RefPtg)ptg).getRVAType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user