]> source.dussan.org Git - poi.git/commitdiff
Initial support for XSSF External Links tables, which hold references to other workbo...
authorNick Burch <nick@apache.org>
Fri, 18 Jul 2014 22:48:59 +0000 (22:48 +0000)
committerNick Burch <nick@apache.org>
Fri, 18 Jul 2014 22:48:59 +0000 (22:48 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611828 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/model/ExternalLinksTable.java [new file with mode: 0644]
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/model/TestExternalLinksTable.java [new file with mode: 0644]

diff --git a/src/ooxml/java/org/apache/poi/xssf/model/ExternalLinksTable.java b/src/ooxml/java/org/apache/poi/xssf/model/ExternalLinksTable.java
new file mode 100644 (file)
index 0000000..22a0de9
--- /dev/null
@@ -0,0 +1,165 @@
+/* ====================================================================
+   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.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.xmlbeans.XmlException;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTExternalDefinedName;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTExternalLink;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTExternalSheetName;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.ExternalLinkDocument;
+
+/**
+ * Holds details of links to parts of other workbooks (eg named ranges),
+ *  along with the most recently seen values for what they point to.
+ */
+public class ExternalLinksTable extends POIXMLDocumentPart {
+    private CTExternalLink link;
+
+    public ExternalLinksTable() {
+        super();
+        link = CTExternalLink.Factory.newInstance();
+    }
+
+    public ExternalLinksTable(PackagePart part, PackageRelationship rel) throws IOException {
+        super(part, rel);
+        readFrom(part.getInputStream());
+    }
+
+    public void readFrom(InputStream is) throws IOException {
+        try {
+            ExternalLinkDocument doc = ExternalLinkDocument.Factory.parse(is);
+            link = doc.getExternalLink();
+        } catch (XmlException e) {
+            throw new IOException(e.getLocalizedMessage());
+        }
+    }
+    public void writeTo(OutputStream out) throws IOException {
+        ExternalLinkDocument doc = ExternalLinkDocument.Factory.newInstance();
+        doc.setExternalLink(link);
+        doc.save(out, DEFAULT_XML_OPTIONS);
+    }
+
+    @Override
+    protected void commit() throws IOException {
+        PackagePart part = getPackagePart();
+        OutputStream out = part.getOutputStream();
+        writeTo(out);
+        out.close();
+    }
+
+    /**
+     * Returns the underlying xmlbeans object for the external
+     *  link table
+     */
+    public CTExternalLink getCTExternalLink(){
+        return link;
+    }
+
+    @SuppressWarnings("deprecation")
+    public List<String> getSheetNames() {
+        CTExternalSheetName[] sheetNames = 
+                link.getExternalBook().getSheetNames().getSheetNameArray();
+        List<String> names = new ArrayList<String>(sheetNames.length);
+        for (CTExternalSheetName name : sheetNames) {
+            names.add(name.getVal());
+        }
+        return names;
+    }
+    
+    @SuppressWarnings("deprecation")
+    public List<Name> getDefinedNames() {
+        CTExternalDefinedName[] extNames = 
+                link.getExternalBook().getDefinedNames().getDefinedNameArray();
+        List<Name> names = new ArrayList<Name>(extNames.length);
+        for (CTExternalDefinedName extName : extNames) {
+            names.add(new ExternalName(extName));
+        }
+        return names;
+    }
+    
+    
+    // TODO Last seen data
+
+    
+    protected class ExternalName implements Name {
+        private CTExternalDefinedName name;
+        protected ExternalName(CTExternalDefinedName name) {
+            this.name = name;
+        }
+
+        public String getNameName() {
+            return name.getName();
+        }
+        public void setNameName(String name) {
+            this.name.setName(name);
+        }
+
+        public String getSheetName() {
+            int sheetId = getSheetIndex();
+            if (sheetId >= 0) {
+                return getSheetNames().get(sheetId);
+            } else {
+                return null;
+            }
+        }
+        public int getSheetIndex() {
+            if (name.isSetSheetId()) {
+                return (int)name.getSheetId();
+            }
+            return -1;
+        }
+        public void setSheetIndex(int sheetId) {
+            name.setSheetId(sheetId);
+        }
+
+        public String getRefersToFormula() {
+            // Return, without the leading =
+            return name.getRefersTo().substring(1);
+        }
+        public void setRefersToFormula(String formulaText) {
+            // Save with leading =
+            name.setRefersTo('=' + formulaText);
+        }
+
+        public boolean isFunctionName() {
+            return false;
+        }
+        public boolean isDeleted() {
+            return false;
+        }
+
+        public String getComment() {
+            return null;
+        }
+        public void setComment(String comment) {
+            throw new IllegalStateException("Not Supported");
+        }
+        public void setFunction(boolean value) {
+            throw new IllegalStateException("Not Supported");
+        }
+    }
+}
\ No newline at end of file
index 037c41356f03437970b1b25b3a5f8684b0a440c4..70e755574b0178659448581324980401f0e14032 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.xssf.model.CalculationChain;
 import org.apache.poi.xssf.model.CommentsTable;
+import org.apache.poi.xssf.model.ExternalLinksTable;
 import org.apache.poi.xssf.model.MapInfo;
 import org.apache.poi.xssf.model.SharedStringsTable;
 import org.apache.poi.xssf.model.SingleXmlCells;
@@ -305,6 +306,13 @@ public final class XSSFRelation extends POIXMLRelation {
         CalculationChain.class
     );
 
+    public static final XSSFRelation EXTERNAL_LINKS = new XSSFRelation(
+        "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
+        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
+        "/xl/externalLinks/externalLink#.xmll",
+        ExternalLinksTable.class
+    );
+
     public static final XSSFRelation PRINTER_SETTINGS = new XSSFRelation(
         "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings",
         "http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings",
index 727989c2ed3514518aa3464c6819898785fbca11..f1025bce74a0b9985d702d502a9f4a9be229c644 100644 (file)
@@ -63,6 +63,7 @@ import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.PackageHelper;
 import org.apache.poi.xssf.model.CalculationChain;
+import org.apache.poi.xssf.model.ExternalLinksTable;
 import org.apache.poi.xssf.model.MapInfo;
 import org.apache.poi.xssf.model.SharedStringsTable;
 import org.apache.poi.xssf.model.StylesTable;
@@ -154,6 +155,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
      * TODO
      */
     private CalculationChain calcChain;
+    
+    /**
+     * External Links, for referencing names or cells in other workbooks
+     */
+    private ExternalLinksTable externalLinks;
 
     /**
      * A collection of custom XML mappings
@@ -283,6 +289,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
                 else if(p instanceof StylesTable) stylesSource = (StylesTable)p;
                 else if(p instanceof ThemesTable) theme = (ThemesTable)p;
                 else if(p instanceof CalculationChain) calcChain = (CalculationChain)p;
+                else if(p instanceof ExternalLinksTable) externalLinks = (ExternalLinksTable)p;
                 else if(p instanceof MapInfo) mapInfo = (MapInfo)p;
                 else if (p instanceof XSSFSheet) {
                     shIdMap.put(p.getPackageRelationship().getId(), (XSSFSheet)p);
@@ -1591,7 +1598,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
     }
 
     /**
-     * Return the CalculationChain object for this workbook
+     * Return the {@link CalculationChain} object for this workbook
      * <p>
      *   The calculation chain object specifies the order in which the cells in a workbook were last calculated
      * </p>
@@ -1599,9 +1606,23 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
      * @return the <code>CalculationChain</code> object or <code>null</code> if not defined
      */
     @Internal
-    public CalculationChain getCalculationChain(){
+    public CalculationChain getCalculationChain() {
         return calcChain;
     }
+    
+    /**
+     * Returns the {@link ExternalLinksTable} object for this workbook.
+     * 
+     * <p>The external links table specifies details of named ranges etc
+     *  that are referenced from other workbooks, along with the last seen
+     *  values of what they point to.</p>
+     *
+     * @return the <code>ExternalLinksTable</code> object or <code>null</code> if not defined
+     */
+    @Internal
+    public ExternalLinksTable getExternalLinksTable() {
+        return externalLinks;
+    }
 
     /**
      *
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/model/TestExternalLinksTable.java b/src/ooxml/testcases/org/apache/poi/xssf/model/TestExternalLinksTable.java
new file mode 100644 (file)
index 0000000..b2c9aff
--- /dev/null
@@ -0,0 +1,84 @@
+/* ====================================================================
+   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.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+public final class TestExternalLinksTable {
+    @Test
+    public void none() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("SampleSS.xlsx");
+        assertEquals(null, wb.getExternalLinksTable());
+    }
+    
+    @Test
+    public void basicRead() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("ref-56737.xlsx");
+        assertNotNull(wb.getExternalLinksTable());
+        Name name = null;
+        
+        ExternalLinksTable links = wb.getExternalLinksTable();
+        assertEquals(3, links.getSheetNames().size());
+        assertEquals(2, links.getDefinedNames().size());
+        
+        assertEquals("Uses",    links.getSheetNames().get(0));
+        assertEquals("Defines", links.getSheetNames().get(1));
+        assertEquals("56737",   links.getSheetNames().get(2));
+        
+        name = links.getDefinedNames().get(0);
+        assertEquals("NR_Global_B2", name.getNameName());
+        assertEquals(-1, name.getSheetIndex());
+        assertEquals(null, name.getSheetName());
+        assertEquals("'Defines'!$B$2", name.getRefersToFormula());
+        
+        name = links.getDefinedNames().get(1);
+        assertEquals("NR_To_A1", name.getNameName());
+        assertEquals(1, name.getSheetIndex());
+        assertEquals("Defines", name.getSheetName());
+        assertEquals("'Defines'!$A$1", name.getRefersToFormula());
+    }
+    
+    @Test
+    public void basicReadWriteRead() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("ref-56737.xlsx");
+        Name name = wb.getExternalLinksTable().getDefinedNames().get(1);
+        name.setNameName("Testing");
+        name.setRefersToFormula("$A$1");
+        
+        wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
+        ExternalLinksTable links = wb.getExternalLinksTable();
+        
+        name = links.getDefinedNames().get(0);
+        assertEquals("NR_Global_B2", name.getNameName());
+        assertEquals(-1, name.getSheetIndex());
+        assertEquals(null, name.getSheetName());
+        assertEquals("'Defines'!$B$2", name.getRefersToFormula());
+        
+        name = links.getDefinedNames().get(1);
+        assertEquals("Testing", name.getNameName());
+        assertEquals(1, name.getSheetIndex());
+        assertEquals("Defines", name.getSheetName());
+        assertEquals("$A$1", name.getRefersToFormula());
+    }
+}