From 3d4acce3a7e82e1e04fd228b5fa5d3b845472145 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Sat, 30 Dec 2017 16:34:57 +0000 Subject: [PATCH] Bug 58106: when a cell with a 'master' shared formula is removed, the next cell in the range becomes the master git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1819623 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/xssf/usermodel/XSSFCell.java | 4 ++ .../apache/poi/xssf/usermodel/XSSFSheet.java | 35 +++++++++++++- .../poi/xssf/usermodel/TestXSSFCell.java | 44 ++++++++++++++++++ test-data/spreadsheet/58106.xlsx | Bin 0 -> 9111 bytes 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 test-data/spreadsheet/58106.xlsx diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index 941e03711c..27c8dd5bb2 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -559,6 +559,7 @@ public final class XSSFCell implements Cell { if (formula == null) { wb.onDeleteFormula(this); if (_cell.isSetF()) { + _row.getSheet().onDeleteFormula(this); _cell.unsetF(); } return; @@ -963,6 +964,9 @@ public final class XSSFCell implements Cell { notifyArrayFormulaChanging(); } if(prevType == CellType.FORMULA && cellType != CellType.FORMULA) { + if (_cell.isSetF()) { + _row.getSheet().onDeleteFormula(this); + } getSheet().getWorkbook().onDeleteFormula(this); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 8ca7d2b1ef..8c81736952 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -4455,7 +4455,40 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { removeRelation(part.getDocumentPart(), true); } } - + + /** + * when a cell with a 'master' shared formula is removed, the next cell in the range becomes the master + */ + protected void onDeleteFormula(XSSFCell cell){ + + CTCellFormula f = cell.getCTCell().getF(); + if (f != null && f.getT() == STCellFormulaType.SHARED && f.isSetRef() && f.getStringValue() != null) { + + CellRangeAddress ref = CellRangeAddress.valueOf(f.getRef()); + if(ref.getNumberOfCells() > 1){ + DONE: + for(int i = cell.getRowIndex(); i <= ref.getLastRow(); i++){ + XSSFRow row = getRow(i); + if(row != null) for(int j = cell.getColumnIndex(); j <= ref.getLastColumn(); j++){ + XSSFCell nextCell = row.getCell(j); + if(nextCell != null && nextCell != cell){ + CTCellFormula nextF = nextCell.getCTCell().getF(); + nextF.setStringValue(nextCell.getCellFormula()); + CellRangeAddress nextRef = new CellRangeAddress( + nextCell.getRowIndex(), ref.getLastRow(), + nextCell.getColumnIndex(), ref.getLastColumn()); + nextF.setRef(nextRef.formatAsString()); + + sharedFormulas.put((int)nextF.getSi(), nextF); + break DONE; + } + } + } + } + + } + } + /** * Determine the OleObject which links shapes with embedded resources * diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java index 0735456e5c..d69ab95cfb 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java @@ -48,6 +48,7 @@ import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.SharedStringsTable; import org.junit.Test; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; @@ -701,4 +702,47 @@ public final class TestXSSFCell extends BaseTestXCell { } } + + @Test + public void testBug58106RemoveSharedFormula() throws Exception { + try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("58106.xlsx")) { + XSSFSheet sheet = wb.getSheetAt(0); + XSSFRow row = sheet.getRow(12); + XSSFCell cell = row.getCell(1); + CTCellFormula f = cell.getCTCell().getF(); + assertEquals("B13:G13", f.getRef()); + assertEquals("SUM(B1:B3)", f.getStringValue()); + assertEquals(0, f.getSi()); + assertEquals(STCellFormulaType.SHARED, f.getT()); + for(char i = 'C'; i <= 'G'; i++){ + XSSFCell sc =row.getCell(i-'A'); + CTCellFormula sf = sc.getCTCell().getF(); + assertFalse(sf.isSetRef()); + assertEquals("", sf.getStringValue()); + assertEquals(0, sf.getSi()); + assertEquals(STCellFormulaType.SHARED, sf.getT()); + } + assertEquals("B13:G13", sheet.getSharedFormula(0).getRef()); + + cell.setCellType(CellType.NUMERIC); + + assertFalse(cell.getCTCell().isSetF()); + + XSSFCell nextFormulaMaster = row.getCell(2); + assertEquals("C13:G13", nextFormulaMaster.getCTCell().getF().getRef()); + assertEquals("SUM(C1:C3)", nextFormulaMaster.getCTCell().getF().getStringValue()); + assertEquals(0, nextFormulaMaster.getCTCell().getF().getSi()); + for(char i = 'D'; i <= 'G'; i++){ + XSSFCell sc =row.getCell(i-'A'); + CTCellFormula sf = sc.getCTCell().getF(); + assertFalse(sf.isSetRef()); + assertEquals("", sf.getStringValue()); + assertEquals(0, sf.getSi()); + assertEquals(STCellFormulaType.SHARED, sf.getT()); + } + assertEquals("C13:G13", sheet.getSharedFormula(0).getRef()); + + } + + } } \ No newline at end of file diff --git a/test-data/spreadsheet/58106.xlsx b/test-data/spreadsheet/58106.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..805d698eb97192d852eda421370be3e57b8e4ee9 GIT binary patch literal 9111 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 Y)10b;5nw0-0MKARBp6ViQ2zM$KO9wc8vp