Bug 63845: Adjust handling of formula-cells to fix regression introduced in 4.1.0

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1875837 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2020-03-29 08:16:17 +00:00
parent f58aa530da
commit cc1b6557ee
6 changed files with 83 additions and 36 deletions

View File

@ -531,6 +531,12 @@ public class HSSFCell extends CellBase {
*/ */
@Override @Override
protected void setCellFormulaImpl(String formula) { protected void setCellFormulaImpl(String formula) {
// formula cells always have a value. If the cell is blank (either initially or after removing an
// array formula), set value to 0
if (getValueType() == CellType.BLANK) {
setCellValue(0);
}
assert formula != null; assert formula != null;
int row=_record.getRow(); int row=_record.getRow();
@ -566,7 +572,7 @@ public class HSSFCell extends CellBase {
case ERROR: case ERROR:
return CellValue.getError(getErrorCellValue()); return CellValue.getError(getErrorCellValue());
default: default:
throw new IllegalStateException(); throw new IllegalStateException("Unexpected cell-type " + valueType);
} }
} }
@ -585,7 +591,7 @@ public class HSSFCell extends CellBase {
setCellErrorValue(FormulaError.forInt(value.getErrorValue())); setCellErrorValue(FormulaError.forInt(value.getErrorValue()));
break; break;
default: default:
throw new IllegalStateException(); throw new IllegalStateException("Unexpected cell-type " + value.getCellType() + " for cell-value: " + value);
} }
} }

View File

@ -123,12 +123,6 @@ public abstract class CellBase implements Cell {
return; return;
} }
// formula cells always have a value. If the cell is blank (either initially or after removing an
// array formula), set value to 0
if (getValueType() == CellType.BLANK) {
setCellValue(0);
}
setCellFormulaImpl(formula); setCellFormulaImpl(formula);
} }

View File

@ -249,6 +249,7 @@ public class SXSSFCell extends CellBase {
((FormulaValue)_value).setValue(formula); ((FormulaValue)_value).setValue(formula);
} else { } else {
switch (getCellType()) { switch (getCellType()) {
case BLANK:
case NUMERIC: case NUMERIC:
_value = new NumericFormulaValue(formula, getNumericCellValue()); _value = new NumericFormulaValue(formula, getNumericCellValue());
break; break;
@ -266,12 +267,8 @@ public class SXSSFCell extends CellBase {
case ERROR: case ERROR:
_value = new ErrorFormulaValue(formula, getErrorCellValue()); _value = new ErrorFormulaValue(formula, getErrorCellValue());
break; break;
case _NONE: default:
// fall-through throw new IllegalStateException("Cannot set a formula for a cell of type " + getCellType());
case FORMULA:
// fall-through
case BLANK:
throw new AssertionError();
} }
} }
} }

View File

@ -20,8 +20,6 @@ package org.apache.poi.ss.usermodel;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.ITestDataProvider;
@ -47,14 +45,14 @@ public abstract class BaseTestXCell extends BaseTestCell {
Sheet sh = wb1.createSheet(); Sheet sh = wb1.createSheet();
Row row = sh.createRow(0); Row row = sh.createRow(0);
Cell cell = row.createCell(0); Cell cell = row.createCell(0);
String sval = "\u0000\u0002\u0012<>\t\n\u00a0 &\"POI\'\u2122"; String sval = "\u0000\u0002\u0012<>\t\n\u00a0 &\"POI'\u2122";
cell.setCellValue(sval); cell.setCellValue(sval);
Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1); Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
wb1.close(); wb1.close();
// invalid characters are replaced with question marks // invalid characters are replaced with question marks
assertEquals("???<>\t\n\u00a0 &\"POI\'\u2122", wb2.getSheetAt(0).getRow(0).getCell(0).getStringCellValue()); assertEquals("???<>\t\n\u00a0 &\"POI'\u2122", wb2.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
wb2.close(); wb2.close();
} }
} }

View File

@ -3494,4 +3494,52 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
LOG.log(POILogger.INFO, Duration.between(start, Instant.now())); LOG.log(POILogger.INFO, Duration.between(start, Instant.now()));
} }
} }
@Test
public void testBug63845() throws IOException {
try (Workbook wb = new XSSFWorkbook()) {
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0, CellType.FORMULA);
cell.setCellFormula("SUM(B1:E1)");
assertNull("Element 'v' should not be set for formulas unless the value was calculated",
((XSSFCell) cell).getCTCell().getV());
try (Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb)) {
Cell cellBack = wbBack.getSheetAt(0).getRow(0).getCell(0);
assertNull("Element 'v' should not be set for formulas unless the value was calculated",
((XSSFCell) cellBack).getCTCell().getV());
wbBack.getCreationHelper().createFormulaEvaluator().evaluateInCell(cellBack);
assertEquals("Element 'v' should be set now as the formula was calculated manually",
"0.0", ((XSSFCell) cellBack).getCTCell().getV());
}
}
}
@Test
public void testBug63845_2() throws IOException {
try (Workbook wb = new XSSFWorkbook()) {
Sheet sheet = wb.createSheet("test");
Row row = sheet.createRow(0);
row.createCell(0).setCellValue(2);
row.createCell(1).setCellValue(5);
row.createCell(2).setCellFormula("A1+B1");
try (Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb)) {
Cell cellBack = wbBack.getSheetAt(0).getRow(0).getCell(2);
assertNull("Element 'v' should not be set for formulas unless the value was calculated",
((XSSFCell) cellBack).getCTCell().getV());
wbBack.getCreationHelper().createFormulaEvaluator().evaluateInCell(cellBack);
assertEquals("Element 'v' should be set now as the formula was calculated manually",
"7.0", ((XSSFCell) cellBack).getCTCell().getV());
}
}
}
} }

View File

@ -1352,7 +1352,8 @@ public abstract class BaseTestCell {
cell.setCellFormula("\"foo\""); cell.setCellFormula("\"foo\"");
assertEquals(CellType.FORMULA, cell.getCellType()); assertEquals(CellType.FORMULA, cell.getCellType());
assertEquals(CellType.BOOLEAN, cell.getCachedFormulaResultType()); assertEquals(CellType.BOOLEAN, cell.getCachedFormulaResultType());
assertTrue(cell.getBooleanCellValue()); assertTrue("Expected a boolean cell-value, but had 'false'",
cell.getBooleanCellValue());
} }
} }
@ -1369,7 +1370,8 @@ public abstract class BaseTestCell {
cell.setCellFormula("\"bar\""); cell.setCellFormula("\"bar\"");
assertEquals(CellType.FORMULA, cell.getCellType()); assertEquals(CellType.FORMULA, cell.getCellType());
assertEquals(CellType.BOOLEAN, cell.getCachedFormulaResultType()); assertEquals(CellType.BOOLEAN, cell.getCachedFormulaResultType());
assertTrue(cell.getBooleanCellValue()); assertTrue("Expected a boolean cell-value, but had 'false'",
cell.getBooleanCellValue());
} }
} }
@ -1387,8 +1389,10 @@ public abstract class BaseTestCell {
cell.getSheet().setArrayFormula("\"bar\"", CellRangeAddress.valueOf("A1")); cell.getSheet().setArrayFormula("\"bar\"", CellRangeAddress.valueOf("A1"));
assertEquals(CellType.FORMULA, cell.getCellType()); assertEquals(CellType.FORMULA, cell.getCellType());
assertEquals(CellType.BOOLEAN, cell.getCachedFormulaResultType()); assertEquals("Expected a boolean cell-value, but had " + cell.getCachedFormulaResultType(),
assertTrue(cell.getBooleanCellValue()); CellType.BOOLEAN, cell.getCachedFormulaResultType());
assertTrue("Expected a boolean cell-value, but had 'false'",
cell.getBooleanCellValue());
} }
} }