Fix bug #56502 - When shifting XSSF rows with formula cells, if the formula can't be parsed, log + leave it unchanged rather than failing

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1614916 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2014-07-31 15:07:27 +00:00
parent 5f5d8f496e
commit 4bfe3c6784
3 changed files with 45 additions and 6 deletions

View File

@ -20,6 +20,7 @@ package org.apache.poi.xssf.usermodel.helpers;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.ss.formula.FormulaParseException;
import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaParser;
import org.apache.poi.ss.formula.FormulaRenderer; import org.apache.poi.ss.formula.FormulaRenderer;
import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.FormulaShifter;
@ -30,6 +31,8 @@ import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook; import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.xssf.usermodel.XSSFName; import org.apache.poi.xssf.usermodel.XSSFName;
@ -43,9 +46,10 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatti
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
/** /**
* @author Yegor Kozlov * Helper for shifting rows up or down
*/ */
public final class XSSFRowShifter { public final class XSSFRowShifter {
private static POILogger logger = POILogFactory.getLogger(XSSFRowShifter.class);
private final XSSFSheet sheet; private final XSSFSheet sheet;
public XSSFRowShifter(XSSFSheet sh) { public XSSFRowShifter(XSSFSheet sh) {
@ -194,12 +198,19 @@ public final class XSSFRowShifter {
XSSFWorkbook wb = sheet.getWorkbook(); XSSFWorkbook wb = sheet.getWorkbook();
int sheetIndex = wb.getSheetIndex(sheet); int sheetIndex = wb.getSheetIndex(sheet);
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
String shiftedFmla = null; try {
if (shifter.adjustFormula(ptgs, sheetIndex)) { Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); String shiftedFmla = null;
if (shifter.adjustFormula(ptgs, sheetIndex)) {
shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
}
return shiftedFmla;
} catch (FormulaParseException fpe) {
// Log, but don't change, rather than breaking
logger.log(POILogger.WARN, "Error shifting formula on row ", row.getRowNum(), fpe);
return formula;
} }
return shiftedFmla;
} }
public void updateConditionalFormatting(FormulaShifter shifter) { public void updateConditionalFormatting(FormulaShifter shifter) {

View File

@ -1787,6 +1787,10 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
checkValue(excel, eval.getStringValue() + ".0"); checkValue(excel, eval.getStringValue() + ".0");
} }
/**
* New hyperlink with no initial cell reference, still need
* to be able to change it
*/
@Test @Test
public void testBug56527() { public void testBug56527() {
XSSFWorkbook wb = new XSSFWorkbook(); XSSFWorkbook wb = new XSSFWorkbook();
@ -1816,6 +1820,30 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
assertEquals(5, hyperlink.getLastRow()); assertEquals(5, hyperlink.getLastRow());
assertEquals(3, hyperlink.getLastColumn()); assertEquals(3, hyperlink.getLastColumn());
} }
/**
* Shifting rows with a formula that references a
* function in another file
*/
@Test
public void bug56502() throws Exception {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56502.xlsx");
Sheet sheet = wb.getSheetAt(0);
Cell cFunc = sheet.getRow(3).getCell(0);
assertEquals("[1]!LUCANET(\"Ist\")", cFunc.getCellFormula());
Cell cRef = sheet.getRow(3).createCell(1);
cRef.setCellFormula("A3");
// Shift it down one row
sheet.shiftRows(1, sheet.getLastRowNum(), 1);
// Check the new formulas: Function won't change, Reference will
cFunc = sheet.getRow(4).getCell(0);
assertEquals("[1]!LUCANET(\"Ist\")", cFunc.getCellFormula());
cRef = sheet.getRow(4).getCell(1);
assertEquals("A4", cRef.getCellFormula());
}
private void checkValue(XSSFWorkbook excel, String expect) { private void checkValue(XSSFWorkbook excel, String expect) {
XSSFFormulaEvaluator evaluator = new XSSFFormulaEvaluator(excel); XSSFFormulaEvaluator evaluator = new XSSFFormulaEvaluator(excel);

Binary file not shown.