<changes>
<release version="3.5-beta7" date="2009-??-??">
- <action dev="POI-DEVELOPERS" type="fix">47535 - fixed WordExtractor to tolerate files with empty footnote block</action>
+ <action dev="POI-DEVELOPERS" type="fix">47540 - Fix for saving custom and extended OOXML properties</action>
+ <action dev="POI-DEVELOPERS" type="fix">47535 - Fixed WordExtractor to tolerate files with empty footnote block</action>
<action dev="POI-DEVELOPERS" type="fix">47517 - Fixed ExtractorFactory to support .xltx and .dotx files</action>
<action dev="POI-DEVELOPERS" type="add">45556 - Support for extraction of footnotes from docx files</action>
<action dev="POI-DEVELOPERS" type="add">45555 - Support for extraction of endnotes from docx files</action>
--- /dev/null
+/* ====================================================================
+ 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.examples;
+
+import java.io.FileOutputStream;
+
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.POIXMLProperties;
+
+/**
+ * How to set extended and custom properties
+ *
+ * @author Yegor Kozlov
+ */
+public class WorkbookProperties {
+
+ public static void main(String[]args) throws Exception {
+
+ XSSFWorkbook workbook = new XSSFWorkbook();
+ workbook.createSheet("Workbook Properties");
+
+ POIXMLProperties props = workbook.getProperties();
+
+ /**
+ * Extended properties are a predefined set of metadata properties
+ * that are specifically applicable to Office Open XML documents.
+ * Extended properties consist of 24 simple properties and 3 complex properties stored in the
+ * part targeted by the relationship of type
+ */
+ POIXMLProperties.ExtendedProperties ext = props.getExtendedProperties();
+ ext.getUnderlyingProperties().setCompany("Apache Software Foundation");
+ ext.getUnderlyingProperties().setTemplate("XSSF");
+
+ /**
+ * Custom properties enable users to define custom metadata properties
+ * through a set of well-defined data types. For example, a custom
+ * OLE Editor property of type string can be defined as follows:
+ *
+ * <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="Editor">
+ * <vt:lpwstr>John Smith</vt:lpwstr>
+ * </property>
+ */
+
+ POIXMLProperties.CustomProperties cust = props.getCustomProperties();
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
+ property = cust.getUnderlyingProperties().addNewProperty();
+
+ property.setFmtid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
+ property.setPid(2);
+ property.setName("Editor");
+ property.setLpwstr("John Smith");
+
+ FileOutputStream out = new FileOutputStream("workbook.xlsx");
+ workbook.write(out);
+ out.close();
+
+ }
+
+
+}
\ No newline at end of file
* Get the document properties. This gives you access to the
* core ooxml properties, and the extended ooxml properties.
*/
- public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException {
+ public POIXMLProperties getProperties() {
if(properties == null) {
- properties = new POIXMLProperties(pkg);
+ try {
+ properties = new POIXMLProperties(pkg);
+ } catch (Exception e){
+ throw new POIXMLException(e);
+ }
}
return properties;
}
//force all children to commit their changes into the underlying OOXML Package
onSave();
+ //save extended and custom properties
+ getProperties().commit();
+
getPackage().save(stream);
}
package org.apache.poi;
import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.HashMap;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlOptions;
+import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument;
/**
* Wrapper around the two different kinds of OOXML properties
private CoreProperties core;
private ExtendedProperties ext;
private CustomProperties cust;
-
- public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException {
+
+ private PackagePart extPart;
+ private PackagePart custPart;
+
+
+ private static final org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument NEW_EXT_INSTANCE;
+ private static final org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument NEW_CUST_INSTANCE;
+ static {
+ NEW_EXT_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance();
+ NEW_EXT_INSTANCE.addNewProperties();
+
+ NEW_CUST_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance();
+ NEW_CUST_INSTANCE.addNewProperties();
+ }
+
+ public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException {
this.pkg = docPackage;
// Core properties
PackageRelationshipCollection extRel =
pkg.getRelationshipsByType(POIXMLDocument.EXTENDED_PROPERTIES_REL_TYPE);
if(extRel.size() == 1) {
- org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse(
- pkg.getPart( extRel.getRelationship(0) ).getInputStream()
+ extPart = pkg.getPart( extRel.getRelationship(0));
+ org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse(
+ extPart.getInputStream()
);
ext = new ExtendedProperties(props);
} else {
- ext = new ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance());
- }
+ extPart = null;
+ ext = new ExtendedProperties((org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument)NEW_EXT_INSTANCE.copy());
+ }
// Custom properties
PackageRelationshipCollection custRel =
pkg.getRelationshipsByType(POIXMLDocument.CUSTOM_PROPERTIES_REL_TYPE);
if(custRel.size() == 1) {
- org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse(
- pkg.getPart( custRel.getRelationship(0) ).getInputStream()
+ custPart = pkg.getPart( custRel.getRelationship(0));
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse(
+ custPart.getInputStream()
);
cust = new CustomProperties(props);
} else {
- cust = new CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance());
+ custPart = null;
+ cust = new CustomProperties((org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument)NEW_CUST_INSTANCE.copy());
}
}
}
/**
- * Writes out the ooxml properties into the supplied,
- * new Package
+ * Commit changes to the underlying OPC package
*/
- public void write(OPCPackage pkg) {
- // TODO
+ public void commit() throws IOException{
+
+ if(extPart == null && !NEW_EXT_INSTANCE.toString().equals(ext.props.toString())){
+ try {
+ PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/app.xml");
+ pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties");
+ extPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.extended-properties+xml");
+ } catch (InvalidFormatException e){
+ throw new POIXMLException(e);
+ }
+ }
+ if(custPart == null && !NEW_CUST_INSTANCE.toString().equals(cust.props.toString())){
+ try {
+ PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/custom.xml");
+ pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
+ custPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.custom-properties+xml");
+ } catch (InvalidFormatException e){
+ throw new POIXMLException(e);
+ }
+ }
+ if(extPart != null){
+ XmlOptions xmlOptions = new XmlOptions(POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
+
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt");
+ xmlOptions.setSaveSuggestedPrefixes(map);
+
+ OutputStream out = extPart.getOutputStream();
+ ext.props.save(out, xmlOptions);
+ out.close();
+ }
+ if(custPart != null){
+ OutputStream out = custPart.getOutputStream();
+ cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
+ out.close();
+ }
}
/**
private org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props;
private ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props) {
this.props = props;
-
- if(props.getProperties() == null) {
- props.addNewProperties();
- }
}
public org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties getUnderlyingProperties() {
private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props;
private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) {
this.props = props;
-
- if(props.getProperties() == null) {
- props.addNewProperties();
- }
}
public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() {
--- /dev/null
+/* ====================================================================
+ 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;
+
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+
+import junit.framework.TestCase;
+
+/**
+ * Test setting extended and custom OOXML properties
+ */
+public class TestPOIXMLProperties extends TestCase {
+ public void testWorkbookExtendedProperties() throws Exception {
+ XSSFWorkbook workbook = new XSSFWorkbook();
+ POIXMLProperties props = workbook.getProperties();
+ assertNotNull(props);
+
+ org.apache.poi.POIXMLProperties.ExtendedProperties properties =
+ props.getExtendedProperties();
+
+ org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties
+ ctProps = properties.getUnderlyingProperties();
+
+
+ String appVersion = "3.5 beta";
+ String application = "POI";
+
+ ctProps.setApplication(application);
+ ctProps.setAppVersion(appVersion);
+
+ ctProps = null;
+ properties = null;
+ props = null;
+
+ XSSFWorkbook newWorkbook =
+ XSSFTestDataSamples.writeOutAndReadBack(workbook);
+
+ assertTrue(workbook != newWorkbook);
+
+
+ POIXMLProperties newProps = newWorkbook.getProperties();
+ assertNotNull(newProps);
+ org.apache.poi.POIXMLProperties.ExtendedProperties newProperties =
+ newProps.getExtendedProperties();
+
+ org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties
+ newCtProps = newProperties.getUnderlyingProperties();
+
+ assertEquals(application, newCtProps.getApplication());
+ assertEquals(appVersion, newCtProps.getAppVersion());
+
+
+ }
+
+
+ public void testWorkbookCustomProperties() throws Exception {
+ XSSFWorkbook workbook = new XSSFWorkbook();
+ POIXMLProperties props = workbook.getProperties();
+ assertNotNull(props);
+
+ org.apache.poi.POIXMLProperties.CustomProperties properties =
+ props.getCustomProperties();
+
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties
+ ctProps = properties.getUnderlyingProperties();
+
+
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
+ property = ctProps.addNewProperty();
+
+
+ String fmtid =
+ "{A1A1A1A1A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1A1A1A1A1}";
+ int pId = 1;
+ String name = "testProperty";
+ String stringValue = "testValue";
+
+
+ property.setFmtid(fmtid);
+ property.setPid(pId);
+ property.setName(name);
+ property.setBstr(stringValue);
+
+
+ property = null;
+ ctProps = null;
+ properties = null;
+ props = null;
+
+ XSSFWorkbook newWorkbook =
+ XSSFTestDataSamples.writeOutAndReadBack(workbook);
+
+ assertTrue(workbook != newWorkbook);
+
+
+ POIXMLProperties newProps = newWorkbook.getProperties();
+ assertNotNull(newProps);
+ org.apache.poi.POIXMLProperties.CustomProperties newProperties =
+ newProps.getCustomProperties();
+
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties
+ newCtProps = newProperties.getUnderlyingProperties();
+
+ assertEquals(1, newCtProps.getPropertyArray().length);
+
+
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
+ newpProperty = newCtProps.getPropertyArray()[0];
+
+ assertEquals(fmtid, newpProperty.getFmtid());
+ assertEquals(pId, newpProperty.getPid());
+ assertEquals(name, newpProperty.getName());
+ assertEquals(stringValue, newpProperty.getBstr());
+
+
+ }
+}
\ No newline at end of file