]> source.dussan.org Git - poi.git/commitdiff
improved XSSFWorkbook.removeSheetAt, see Bugzilla 47737 and 47813
authorYegor Kozlov <yegor@apache.org>
Sat, 12 Sep 2009 16:01:18 +0000 (16:01 +0000)
committerYegor Kozlov <yegor@apache.org>
Sat, 12 Sep 2009 16:01:18 +0000 (16:01 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@814176 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChartSheet.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java
test-data/spreadsheet/47737.xlsx [new file with mode: 0755]
test-data/spreadsheet/47813.xlsx [new file with mode: 0755]

index 632065a8ffc39f9cd911b462d0913a7c2216601a..c409671616d4fd064d9634ee766eabccb547af38 100644 (file)
@@ -33,6 +33,8 @@
 
     <changes>
         <release version="3.5-beta7" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">47813 - fixed problems with XSSFWorkbook.removeSheetAt when workbook contains chart</action>
+           <action dev="POI-DEVELOPERS" type="fix">47737 - adjust sheet indices of named ranges when deleting sheets</action>
            <action dev="POI-DEVELOPERS" type="fix">47770 - built-in positive formats don't need starting '('</action>
            <action dev="POI-DEVELOPERS" type="add">47771 - Added method setFunction(boolean) for defined names</action>
            <action dev="POI-DEVELOPERS" type="add">47768 - Implementation of Excel "Days360" and "Npv" functions</action>
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChartSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChartSheet.java
new file mode 100755 (executable)
index 0000000..607249e
--- /dev/null
@@ -0,0 +1,65 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.poi.POIXMLException;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.xmlbeans.XmlException;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
+
+/**
+ * High level representation of of Sheet Parts that are of type 'chartsheet'.
+ *
+ * TODO: current verion extends XSSFSheet although both should extend AbstractSheet
+ *
+ * @author Yegor Kozlov
+ */
+public class XSSFChartSheet extends XSSFSheet  {
+
+    protected CTChartsheet chartsheet;
+
+    protected XSSFChartSheet(PackagePart part, PackageRelationship rel) {
+        super(part, rel);
+    }
+
+    protected void read(InputStream is) throws IOException {
+        try {
+            chartsheet = ChartsheetDocument.Factory.parse(is).getChartsheet();
+        } catch (XmlException e){
+            throw new POIXMLException(e);
+        }
+    }
+
+    /**
+     * Provide access to the CTWorksheet bean holding this sheet's data
+     *
+     * @return the CTWorksheet bean holding this sheet's data
+     */
+    public CTChartsheet getCTChartsheet() {
+        return chartsheet;
+    }
+
+    @Override
+    protected void commit() throws IOException {
+
+    }
+
+}
\ No newline at end of file
index 42cd41a3e3e4ffa3bef8c157e42ae88e8dd6836a..ad3f98812df415aa632e1fdb2136ae54b7610ae5 100644 (file)
@@ -90,6 +90,12 @@ public final class XSSFRelation extends POIXMLRelation {
                        "/xl/worksheets/sheet#.xml",
                        XSSFSheet.class
        );
+    public static final XSSFRelation CHARTSHEET = new XSSFRelation(
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
+            "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet",
+            "/xl/chartsheets/sheet#.xml",
+            XSSFChartSheet.class
+    );
        public static final XSSFRelation SHARED_STRINGS = new XSSFRelation(
                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
                        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
index 622104e8a59ecb913598099dbc7dfae04d14eae2..e761146d3e211c00929dc85b970b1e3f4250804e 100644 (file)
@@ -781,10 +781,40 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
     public void removeSheetAt(int index) {
         validateSheetIndex(index);
 
+        onSheetDelete(index);
+
         XSSFSheet sheet = getSheetAt(index);
         removeRelation(sheet);
-        this.sheets.remove(index);
-        this.workbook.getSheets().removeSheet(index);
+        sheets.remove(index);
+    }
+
+    /**
+     * Gracefully remove references to the sheet being deleted
+     *
+     * @param index the 0-based index of the sheet to delete
+     */
+    private void onSheetDelete(int index) {
+        //delete the CTSheet reference from workbook.xml
+        workbook.getSheets().removeSheet(index);
+
+        //calculation chain is auxilary, remove it as it may contain orfan references to deleted cells
+        if(calcChain != null) {
+            removeRelation(calcChain);
+            calcChain = null;
+        }
+
+        //adjust indices of names ranges
+        for (Iterator<XSSFName> it = namedRanges.iterator(); it.hasNext();) {
+            XSSFName nm = it.next();
+            CTDefinedName ct = nm.getCTName();
+            if(!ct.isSetLocalSheetId()) continue;
+            if (ct.getLocalSheetId() == index) {
+                it.remove();
+            } else if (ct.getLocalSheetId() > index){
+                // Bump down by one, so still points at the same sheet
+                ct.setLocalSheetId(ct.getLocalSheetId()-1);
+            }
+        }
     }
 
     /**
index 9db76c04f908f07e7e1b710c52f9f1515a151e9c..b25cd26c9cec02355e4f17256384309a6f124109 100644 (file)
@@ -304,4 +304,56 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook {
 
                assertEquals(crc0.getValue(), crc1.getValue());
        }
+
+    /**
+     * When deleting a sheet make sure that we adjust sheet indices of named ranges
+     */
+    public void testBug47737() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("47737.xlsx");
+        assertEquals(2, wb.getNumberOfNames());
+        assertNotNull(wb.getCalculationChain());
+
+        XSSFName nm0 = wb.getNameAt(0);
+        assertTrue(nm0.getCTName().isSetLocalSheetId());
+        assertEquals(0, nm0.getCTName().getLocalSheetId());
+        
+        XSSFName nm1 = wb.getNameAt(1);
+        assertTrue(nm1.getCTName().isSetLocalSheetId());
+        assertEquals(1, nm1.getCTName().getLocalSheetId());
+
+        wb.removeSheetAt(0);
+        assertEquals(1, wb.getNumberOfNames());
+        XSSFName nm2 = wb.getNameAt(0);
+        assertTrue(nm2.getCTName().isSetLocalSheetId());
+        assertEquals(0, nm2.getCTName().getLocalSheetId());
+        //calculation chain is removed as well
+        assertNull(wb.getCalculationChain());
+
+    }
+
+    /**
+     * Problems with XSSFWorkbook.removeSheetAt when workbook contains chart
+     */
+    public void testBug47813() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("47813.xlsx");
+        assertEquals(3, wb.getNumberOfSheets());
+        assertNotNull(wb.getCalculationChain());
+
+        assertEquals("Numbers", wb.getSheetName(0));
+        //the second sheet is of type 'chartsheet'
+        assertEquals("Chart", wb.getSheetName(1));
+        assertTrue(wb.getSheetAt(1) instanceof XSSFChartSheet);
+        assertEquals("SomeJunk", wb.getSheetName(2));
+
+        wb.removeSheetAt(2);
+        assertEquals(2, wb.getNumberOfSheets());
+        assertNull(wb.getCalculationChain());
+
+        wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
+        assertEquals(2, wb.getNumberOfSheets());
+        assertNull(wb.getCalculationChain());
+
+        assertEquals("Numbers", wb.getSheetName(0));
+        assertEquals("Chart", wb.getSheetName(1));
+    }
 }
diff --git a/test-data/spreadsheet/47737.xlsx b/test-data/spreadsheet/47737.xlsx
new file mode 100755 (executable)
index 0000000..5737a59
Binary files /dev/null and b/test-data/spreadsheet/47737.xlsx differ
diff --git a/test-data/spreadsheet/47813.xlsx b/test-data/spreadsheet/47813.xlsx
new file mode 100755 (executable)
index 0000000..5ab22e3
Binary files /dev/null and b/test-data/spreadsheet/47813.xlsx differ