diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 9172584538..2374823a42 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 54206 - Ensure that shared formuals are updated when shifting rows in a spreadsheet Synchronize table headers with parent sheet in XSSF 54210 - Fixed rendering text in flipped shapes in PPT2PNG and PPTX2PNG diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java index 70ad5227fd..14415ae9b2 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -292,12 +292,14 @@ public final class ValueRecordsAggregate implements Iterablenull if not found */ - CTCellFormula getSharedFormula(int sid){ + @Internal + public CTCellFormula getSharedFormula(int sid){ return sharedFormulas.get(sid); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java index 40de77bcd4..245d7c1c19 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java @@ -28,10 +28,7 @@ import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.AreaPtg; import org.apache.poi.ss.formula.ptg.AreaErrPtg; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; import java.util.List; import java.util.ArrayList; @@ -156,7 +153,13 @@ public final class XSSFRowShifter { String shiftedFormula = shiftFormula(row, formula, shifter); if (shiftedFormula != null) { f.setStringValue(shiftedFormula); + if(f.getT() == STCellFormulaType.SHARED){ + int si = (int)f.getSi(); + CTCellFormula sf = row.getSheet().getSharedFormula(si); + sf.setStringValue(shiftedFormula); + } } + } if (f.isSetRef()) { //Range of cells which the formula applies to. diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java index 1612a09eaa..9146db7521 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java @@ -21,6 +21,7 @@ import junit.framework.TestCase; import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellReference; /** * Tests row shifting capabilities. @@ -41,8 +42,6 @@ public abstract class BaseTestSheetShiftRows extends TestCase { * After each shift, writes the workbook to file and reads back to * check. This ensures that if some changes code that breaks * writing or what not, they realize it. - * - * @param sampleName the sample file to test against */ public final void testShiftRows(){ // Read initial file in @@ -324,4 +323,61 @@ public abstract class BaseTestSheetShiftRows extends TestCase { assertEquals(expectedValue, cell.getNumericCellValue(), 0.0); assertEquals(expectedFormula, cell.getCellFormula()); } -} + + public final void testShiftSharedFormulasBug54206() { + Workbook wb = _testDataProvider.openSampleWorkbook("54206." + _testDataProvider.getStandardFileNameExtension()); + + Sheet sheet = wb.getSheetAt(0); + assertEquals("SUMIF($B$19:$B$82,$B4,G$19:G$82)", sheet.getRow(3).getCell(6).getCellFormula()); + assertEquals("SUMIF($B$19:$B$82,$B4,H$19:H$82)", sheet.getRow(3).getCell(7).getCellFormula()); + assertEquals("SUMIF($B$19:$B$82,$B4,I$19:I$82)", sheet.getRow(3).getCell(8).getCellFormula()); + + assertEquals("SUMIF($B$19:$B$82,$B15,G$19:G$82)", sheet.getRow(14).getCell(6).getCellFormula()); + assertEquals("SUMIF($B$19:$B$82,$B15,H$19:H$82)", sheet.getRow(14).getCell(7).getCellFormula()); + assertEquals("SUMIF($B$19:$B$82,$B15,I$19:I$82)", sheet.getRow(14).getCell(8).getCellFormula()); + + // now the whole block G4L:15 + for(int i = 3; i <= 14; i++){ + for(int j = 6; j <= 8; j++){ + String col = CellReference.convertNumToColString(j); + String expectedFormula = "SUMIF($B$19:$B$82,$B"+(i+1)+","+col+"$19:"+col+"$82)"; + assertEquals(expectedFormula, sheet.getRow(i).getCell(j).getCellFormula()); + } + } + + assertEquals("SUM(G24:I24)", sheet.getRow(23).getCell(9).getCellFormula()); + assertEquals("SUM(G25:I25)", sheet.getRow(24).getCell(9).getCellFormula()); + assertEquals("SUM(G26:I26)", sheet.getRow(25).getCell(9).getCellFormula()); + + sheet.shiftRows(24, sheet.getLastRowNum(), 4, true, false); + + assertEquals("SUMIF($B$19:$B$86,$B4,G$19:G$86)", sheet.getRow(3).getCell(6).getCellFormula()); + assertEquals("SUMIF($B$19:$B$86,$B4,H$19:H$86)", sheet.getRow(3).getCell(7).getCellFormula()); + assertEquals("SUMIF($B$19:$B$86,$B4,I$19:I$86)", sheet.getRow(3).getCell(8).getCellFormula()); + + assertEquals("SUMIF($B$19:$B$86,$B15,G$19:G$86)", sheet.getRow(14).getCell(6).getCellFormula()); + assertEquals("SUMIF($B$19:$B$86,$B15,H$19:H$86)", sheet.getRow(14).getCell(7).getCellFormula()); + assertEquals("SUMIF($B$19:$B$86,$B15,I$19:I$86)", sheet.getRow(14).getCell(8).getCellFormula()); + + // now the whole block G4L:15 + for(int i = 3; i <= 14; i++){ + for(int j = 6; j <= 8; j++){ + String col = CellReference.convertNumToColString(j); + String expectedFormula = "SUMIF($B$19:$B$86,$B"+(i+1)+","+col+"$19:"+col+"$86)"; + assertEquals(expectedFormula, sheet.getRow(i).getCell(j).getCellFormula()); + } + } + + assertEquals("SUM(G24:I24)", sheet.getRow(23).getCell(9).getCellFormula()); + + // shifted rows + assertTrue( sheet.getRow(24) == null || sheet.getRow(24).getCell(9) == null); + assertTrue( sheet.getRow(25) == null || sheet.getRow(25).getCell(9) == null); + assertTrue( sheet.getRow(26) == null || sheet.getRow(26).getCell(9) == null); + assertTrue( sheet.getRow(27) == null || sheet.getRow(27).getCell(9) == null); + + assertEquals("SUM(G29:I29)", sheet.getRow(28).getCell(9).getCellFormula()); + assertEquals("SUM(G30:I30)", sheet.getRow(29).getCell(9).getCellFormula()); + + } +} \ No newline at end of file diff --git a/test-data/spreadsheet/54206.xls b/test-data/spreadsheet/54206.xls new file mode 100644 index 0000000000..24da03b379 Binary files /dev/null and b/test-data/spreadsheet/54206.xls differ diff --git a/test-data/spreadsheet/54206.xlsx b/test-data/spreadsheet/54206.xlsx new file mode 100644 index 0000000000..bd8be74a0f Binary files /dev/null and b/test-data/spreadsheet/54206.xlsx differ