aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Burch <nick@apache.org>2014-07-18 22:48:59 +0000
committerNick Burch <nick@apache.org>2014-07-18 22:48:59 +0000
commit2643dfdef447d25119bd9cc54b0e27600054bd0a (patch)
tree240e29a102c38c1a2b6ce9e4b30a2034a52fbc05
parent5449fca03a2545bbc5587ef553f4daeb0c49365f (diff)
downloadpoi-2643dfdef447d25119bd9cc54b0e27600054bd0a.tar.gz
poi-2643dfdef447d25119bd9cc54b0e27600054bd0a.zip
Initial support for XSSF External Links tables, which hold references to other workbooks referenced by formulas and names. #56744
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611828 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/model/ExternalLinksTable.java165
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java8
-rw-r--r--src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java25
-rw-r--r--src/ooxml/testcases/org/apache/poi/xssf/model/TestExternalLinksTable.java84
4 files changed, 280 insertions, 2 deletions
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
index 0000000000..22a0de9c45
--- /dev/null
+++ b/src/ooxml/java/org/apache/poi/xssf/model/ExternalLinksTable.java
@@ -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
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
index 037c41356f..70e755574b 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
@@ -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",
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
index 727989c2ed..f1025bce74 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
@@ -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
index 0000000000..b2c9aff148
--- /dev/null
+++ b/src/ooxml/testcases/org/apache/poi/xssf/model/TestExternalLinksTable.java
@@ -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());
+ }
+}