Initial support for XSSF Charts. Provides easy access to the underlying CTChart object via the Sheet Drawing, but no high level interface onto the chart contents as yet.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1090442 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2011-04-08 20:51:52 +00:00
parent 7ec533f37d
commit 09470f80ba
6 changed files with 247 additions and 5 deletions

View File

@ -34,6 +34,7 @@
<changes> <changes>
<release version="3.8-beta3" date="2011-??-??"> <release version="3.8-beta3" date="2011-??-??">
<action dev="poi-developers" type="add">Initial support for XSSF Charts. Provides easy access to the underlying CTChart object via the Sheet Drawing, but no high level interface onto the chart contents as yet.</action>
<action dev="poi-developers" type="fix">50884 - XSSF and HSSF freeze panes now behave the same</action> <action dev="poi-developers" type="fix">50884 - XSSF and HSSF freeze panes now behave the same</action>
<action dev="poi-developers" type="add">Support for adding a table to a XSSFSheet</action> <action dev="poi-developers" type="add">Support for adding a table to a XSSFSheet</action>
<action dev="poi-developers" type="add">Improve HSMF MAPIMessage access to the HTML and RTF versions of the message body (where available)</action> <action dev="poi-developers" type="add">Improve HSMF MAPIMessage access to the HTML and RTF versions of the message body (where available)</action>

View File

@ -0,0 +1,147 @@
/* ====================================================================
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.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChartSpace;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle;
import org.openxmlformats.schemas.drawingml.x2006.chart.ChartSpaceDocument;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
* Represents a SpreadsheetML Chart
*/
public final class XSSFChart extends POIXMLDocumentPart {
/**
* Root element of the SpreadsheetML Chart part
*/
private CTChartSpace chartSpace;
/**
* The Chart within that
*/
private CTChart chart;
/**
* Create a new SpreadsheetML chart
*/
protected XSSFChart() {
super();
createChart();
}
/**
* Construct a SpreadsheetML chart from a package part
*
* @param part the package part holding the chart data,
* the content type must be <code>application/vnd.openxmlformats-officedocument.drawingml.chart+xml</code>
* @param rel the package relationship holding this chart,
* the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart
*/
protected XSSFChart(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
super(part, rel);
chartSpace = ChartSpaceDocument.Factory.parse(part.getInputStream()).getChartSpace();
chart = chartSpace.getChart();
}
/**
* Construct a new CTChartSpace bean. By default, it's just an empty placeholder for chart objects
*
* @return a new CTChartSpace bean
*/
private void createChart() {
chartSpace = CTChartSpace.Factory.newInstance();
chart = chartSpace.addNewChart();
}
/**
* Return the underlying CTChartSpace bean, the root element of the SpreadsheetML Chart part.
*
* @return the underlying CTChartSpace bean
*/
@Internal
public CTChartSpace getCTChartSpace(){
return chartSpace;
}
/**
* Return the underlying CTChart bean, within the Chart Space
*
* @return the underlying CTChart bean
*/
@Internal
public CTChart getCTChart(){
return chart;
}
@Override
protected void commit() throws IOException {
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
Map<String, String> map = new HashMap<String, String>();
map.put(XSSFDrawing.NAMESPACE_A, "a");
map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
xmlOptions.setSaveSuggestedPrefixes(map);
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
chartSpace.save(out, xmlOptions);
out.close();
}
/**
* Returns the title, or null if none is set
*/
public XSSFRichTextString getTitle() {
if(! chart.isSetTitle()) {
return null;
}
// TODO Do properly
CTTitle title = chart.getTitle();
StringBuffer text = new StringBuffer();
XmlObject[] t = title
.selectPath("declare namespace a='"+XSSFDrawing.NAMESPACE_A+"' .//a:t");
for (int m = 0; m < t.length; m++) {
NodeList kids = t[m].getDomNode().getChildNodes();
for (int n = 0; n < kids.getLength(); n++) {
if (kids.item(n) instanceof Text) {
text.append(kids.item(n).getNodeValue());
}
}
}
return new XSSFRichTextString(text.toString());
}
}

View File

@ -19,20 +19,22 @@ package org.apache.poi.xssf.usermodel;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.util.Internal;
import org.apache.poi.xssf.model.CommentsTable;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.util.Internal;
import org.apache.poi.xssf.model.CommentsTable;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector;
@ -55,6 +57,8 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
*/ */
private CTDrawing drawing; private CTDrawing drawing;
private boolean isNew; private boolean isNew;
protected static final String NAMESPACE_A = "http://schemas.openxmlformats.org/drawingml/2006/main";
/** /**
* Create a new SpreadsheetML drawing * Create a new SpreadsheetML drawing
@ -111,7 +115,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
*/ */
if(isNew) xmlOptions.setSaveSyntheticDocumentElement(new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr")); if(isNew) xmlOptions.setSaveSyntheticDocumentElement(new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr"));
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a"); map.put(NAMESPACE_A, "a");
map.put(STRelationshipId.type.getName().getNamespaceURI(), "r"); map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
xmlOptions.setSaveSuggestedPrefixes(map); xmlOptions.setSaveSuggestedPrefixes(map);
@ -262,6 +266,19 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing {
shape.setRow(ca.getRow1()); shape.setRow(ca.getRow1());
return shape; return shape;
} }
/**
* Returns all charts in this drawing.
*/
public List<XSSFChart> getCharts() {
List<XSSFChart> charts = new ArrayList<XSSFChart>();
for(POIXMLDocumentPart part : getRelations()) {
if(part instanceof XSSFChart) {
charts.add((XSSFChart)part);
}
}
return charts;
}
/** /**
* Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells. * Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells.

View File

@ -91,12 +91,12 @@ public final class XSSFRelation extends POIXMLRelation {
"/xl/worksheets/sheet#.xml", "/xl/worksheets/sheet#.xml",
XSSFSheet.class XSSFSheet.class
); );
public static final XSSFRelation CHARTSHEET = new XSSFRelation( public static final XSSFRelation CHARTSHEET = new XSSFRelation(
"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet",
"/xl/chartsheets/sheet#.xml", "/xl/chartsheets/sheet#.xml",
XSSFChartSheet.class XSSFChartSheet.class
); );
public static final XSSFRelation SHARED_STRINGS = new XSSFRelation( public static final XSSFRelation SHARED_STRINGS = new XSSFRelation(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
@ -121,6 +121,12 @@ public final class XSSFRelation extends POIXMLRelation {
"/xl/drawings/vmlDrawing#.vml", "/xl/drawings/vmlDrawing#.vml",
XSSFVMLDrawing.class XSSFVMLDrawing.class
); );
public static final XSSFRelation CHART = new XSSFRelation(
"application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
"/xl/charts/chart#.xml",
XSSFChart.class
);
public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation( public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation(
"application/xml", "application/xml",

View File

@ -0,0 +1,58 @@
/* ====================================================================
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 junit.framework.TestCase;
import org.apache.poi.xssf.XSSFTestDataSamples;
public final class TestXSSFChart extends TestCase {
public void testGetAccessors() {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithThreeCharts.xlsx");
XSSFSheet s1 = wb.getSheetAt(0);
XSSFSheet s2 = wb.getSheetAt(1);
XSSFSheet s3 = wb.getSheetAt(2);
assertEquals(0, s1.getRelations().size());
assertEquals(1, s2.getRelations().size());
assertEquals(1, s3.getRelations().size());
}
public void testGetCharts() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithThreeCharts.xlsx");
XSSFSheet s1 = wb.getSheetAt(0);
XSSFSheet s2 = wb.getSheetAt(1);
XSSFSheet s3 = wb.getSheetAt(2);
assertEquals(0, s1.createDrawingPatriarch().getCharts().size());
assertEquals(2, s2.createDrawingPatriarch().getCharts().size());
assertEquals(1, s3.createDrawingPatriarch().getCharts().size());
// Check the titles
XSSFChart chart = s2.createDrawingPatriarch().getCharts().get(0);
assertEquals(null, chart.getTitle());
chart = s2.createDrawingPatriarch().getCharts().get(1);
assertEquals("Pie Chart Title Thingy", chart.getTitle().getString());
chart = s3.createDrawingPatriarch().getCharts().get(0);
assertEquals("Sheet 3 Chart with Title", chart.getTitle().getString());
}
}

View File

@ -55,4 +55,17 @@ public final class TestXSSFChartSheet extends TestCase {
assertEquals(0, sheet.getColumnBreaks().length); assertEquals(0, sheet.getColumnBreaks().length);
assertEquals(true, sheet.getRowSumsBelow()); assertEquals(true, sheet.getRowSumsBelow());
} }
public void testGetCharts() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("chart_sheet.xlsx");
XSSFSheet ns = wb.getSheetAt(0);
XSSFChartSheet cs = (XSSFChartSheet)wb.getSheetAt(2);
assertEquals(0, ns.createDrawingPatriarch().getCharts().size());
assertEquals(1, cs.createDrawingPatriarch().getCharts().size());
XSSFChart chart = cs.createDrawingPatriarch().getCharts().get(0);
assertEquals(null, chart.getTitle());
}
} }