diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java
index 0e00c7d94..3a8fd56d0 100755
--- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java
+++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java
@@ -47,24 +47,15 @@ public class WorkbookProperties {
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:
- *
- *
- * John Smith
- *
+ * Custom properties enable users to define custom metadata properties.
*/
POIXMLProperties.CustomProperties cust = props.getCustomProperties();
- org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
- property = cust.getUnderlyingProperties().addNewProperty();
+ cust.addProperty("Author", "John Smith");
+ cust.addProperty("Year", 2009);
+ cust.addProperty("Price", 45.50);
+ cust.addProperty("Available", true);
- 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();
diff --git a/src/ooxml/java/org/apache/poi/POIXMLProperties.java b/src/ooxml/java/org/apache/poi/POIXMLProperties.java
index 1ccf73674..c62b57db3 100644
--- a/src/ooxml/java/org/apache/poi/POIXMLProperties.java
+++ b/src/ooxml/java/org/apache/poi/POIXMLProperties.java
@@ -34,6 +34,7 @@ import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.util.Nullable;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
+import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
/**
* Wrapper around the two different kinds of OOXML properties
@@ -150,8 +151,14 @@ public class POIXMLProperties {
out.close();
}
if(custPart != null){
+ XmlOptions xmlOptions = new XmlOptions(POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
+
+ Map map = new HashMap();
+ map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt");
+ xmlOptions.setSaveSuggestedPrefixes(map);
+
OutputStream out = custPart.getOutputStream();
- cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
+ cust.props.save(out, xmlOptions);
out.close();
}
}
@@ -271,10 +278,16 @@ public class POIXMLProperties {
}
/**
- * Custom document properties
+ * Custom document properties
*/
public class CustomProperties {
- private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props;
+ /**
+ * Each custom property element contains an fmtid attribute
+ * with the same GUID value ({D5CDD505-2E9C-101B-9397-08002B2CF9AE}).
+ */
+ public static final String FORMAT_ID = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
+
+ private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props;
private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) {
this.props = props;
}
@@ -282,5 +295,91 @@ public class POIXMLProperties {
public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() {
return props.getProperties();
}
- }
+
+ /**
+ * Add a new property
+ *
+ * @param name the property name
+ * @throws IllegalArgumentException if a property with this name already exists
+ */
+ private CTProperty add(String name) {
+ if(contains(name)) {
+ throw new IllegalArgumentException("A property with this name " +
+ "already exists in the custom properties");
+ }
+
+ CTProperty p = props.getProperties().addNewProperty();
+ int pid = nextPid();
+ p.setPid(pid);
+ p.setFmtid(FORMAT_ID);
+ p.setName(name);
+ return p;
+ }
+
+ /**
+ * Add a new string property
+ *
+ * @throws IllegalArgumentException if a property with this name already exists
+ */
+ public void addProperty(String name, String value){
+ CTProperty p = add(name);
+ p.setLpwstr(value);
+ }
+
+ /**
+ * Add a new double property
+ *
+ * @throws IllegalArgumentException if a property with this name already exists
+ */
+ public void addProperty(String name, double value){
+ CTProperty p = add(name);
+ p.setR8(value);
+ }
+
+ /**
+ * Add a new integer property
+ *
+ * @throws IllegalArgumentException if a property with this name already exists
+ */
+ public void addProperty(String name, int value){
+ CTProperty p = add(name);
+ p.setI4(value);
+ }
+
+ /**
+ * Add a new boolean property
+ *
+ * @throws IllegalArgumentException if a property with this name already exists
+ */
+ public void addProperty(String name, boolean value){
+ CTProperty p = add(name);
+ p.setBool(value);
+ }
+
+ /**
+ * Generate next id that uniquely relates a custom property
+ *
+ * @return next property id starting with 2
+ */
+ protected int nextPid(){
+ int propid = 1;
+ for(CTProperty p : props.getProperties().getPropertyArray()){
+ if(p.getPid() > propid) propid = p.getPid();
+ }
+ return propid + 1;
+ }
+
+ /**
+ * Check if a property with this name already exists in the collection of custom properties
+ *
+ * @param name the name to check
+ * @return whether a property with the given name exists in the custom properties
+ */
+ public boolean contains(String name){
+ for(CTProperty p : props.getProperties().getPropertyArray()){
+ if(p.getName().equals(name)) return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
index ba9cfe92a..1aac08740 100644
--- a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
+++ b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
@@ -27,6 +27,7 @@ import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties;
/**
* Test setting extended and custom OOXML properties
@@ -85,69 +86,57 @@ public final class TestPOIXMLProperties extends TestCase {
}
- public void testWorkbookCustomProperties() {
- XSSFWorkbook workbook = new XSSFWorkbook();
- POIXMLProperties props = workbook.getProperties();
- assertNotNull(props);
+ /**
+ * Test usermodel API for setting custom properties
+ */
+ public void testCustomProperties() {
+ POIXMLDocument wb = new XSSFWorkbook();
- org.apache.poi.POIXMLProperties.CustomProperties properties =
- props.getCustomProperties();
+ POIXMLProperties.CustomProperties customProps = wb.getProperties().getCustomProperties();
+ customProps.addProperty("test-1", "string val");
+ customProps.addProperty("test-2", 1974);
+ customProps.addProperty("test-3", 36.6);
+ //adding a duplicate
+ try {
+ customProps.addProperty("test-3", 36.6);
+ fail("expected exception");
+ } catch(IllegalArgumentException e){
+ assertEquals("A property with this name already exists in the custom properties", e.getMessage());
+ }
+ customProps.addProperty("test-4", true);
- org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties
- ctProps = properties.getUnderlyingProperties();
+ wb = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb);
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties ctProps =
+ wb.getProperties().getCustomProperties().getUnderlyingProperties();
+ assertEquals(4, ctProps.sizeOfPropertyArray());
+ org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty p;
+ p = ctProps.getPropertyArray(0);
+ assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
+ assertEquals("test-1", p.getName());
+ assertEquals("string val", p.getLpwstr());
+ assertEquals(2, p.getPid());
- org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
- property = ctProps.addNewProperty();
+ p = ctProps.getPropertyArray(1);
+ assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
+ assertEquals("test-2", p.getName());
+ assertEquals(1974, p.getI4());
+ assertEquals(3, p.getPid());
+ p = ctProps.getPropertyArray(2);
+ assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
+ assertEquals("test-3", p.getName());
+ assertEquals(36.6, p.getR8());
+ assertEquals(4, p.getPid());
- String fmtid =
- "{A1A1A1A1A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1A1A1A1A1}";
- int pId = 1;
- String name = "testProperty";
- String stringValue = "testValue";
+ p = ctProps.getPropertyArray(3);
+ assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
+ assertEquals("test-4", p.getName());
+ assertEquals(true, p.getBool());
+ assertEquals(5, p.getPid());
+ }
-
- 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());
-
-
- }
-
- public void testDocumentProperties() {
+ public void testDocumentProperties() {
String category = _coreProperties.getCategory();
assertEquals("test", category);
String contentStatus = "Draft";