From ef75a6d2d2dda6ab20366954bd19e3e492bc5dc2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alain=20B=C3=A9arez?= Date: Sat, 8 Dec 2018 02:44:22 +0000 Subject: [PATCH] create chart from scratch by sandeeptiwari32 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1848432 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xslf/usermodel/ChartFromScratch.java | 145 ++++++++++++++++++ .../usermodel/examples/ChartFromScratch.java | 140 +++++++++++++++++ .../poi/xddf/usermodel/chart/XDDFChart.java | 46 +++++- .../poi/xslf/usermodel/XMLSlideShow.java | 15 +- .../apache/poi/xslf/usermodel/XSLFChart.java | 57 +++++++ .../poi/xslf/usermodel/XSLFDrawing.java | 13 ++ .../apache/poi/xslf/usermodel/XSLFSheet.java | 31 +++- .../apache/poi/xwpf/usermodel/XWPFChart.java | 4 +- .../poi/xwpf/usermodel/XWPFDocument.java | 3 +- .../poi/xslf/usermodel/TestXSLFSlide.java | 31 +++- 10 files changed, 467 insertions(+), 18 deletions(-) create mode 100644 src/examples/src/org/apache/poi/xslf/usermodel/ChartFromScratch.java create mode 100644 src/examples/src/org/apache/poi/xwpf/usermodel/examples/ChartFromScratch.java diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/ChartFromScratch.java b/src/examples/src/org/apache/poi/xslf/usermodel/ChartFromScratch.java new file mode 100644 index 0000000000..12f96fa6fd --- /dev/null +++ b/src/examples/src/org/apache/poi/xslf/usermodel/ChartFromScratch.java @@ -0,0 +1,145 @@ +/* + * ==================================================================== + * 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.xslf.usermodel; + +import java.awt.geom.Rectangle2D; +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xddf.usermodel.chart.AxisCrosses; +import org.apache.poi.xddf.usermodel.chart.AxisPosition; +import org.apache.poi.xddf.usermodel.chart.BarDirection; +import org.apache.poi.xddf.usermodel.chart.ChartTypes; +import org.apache.poi.xddf.usermodel.chart.LegendPosition; +import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData; +import org.apache.poi.xddf.usermodel.chart.XDDFChart; +import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis; +import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend; +import org.apache.poi.xddf.usermodel.chart.XDDFDataSource; +import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory; +import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource; +import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis; + +/** + * Build a chart without reading template file + */ +public class ChartFromScratch { + private static void usage(){ + System.out.println("Usage: BarChartExample "); + System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " + + "then go pairs {axis-label value}"); + } + + public static void main(String[] args) throws Exception { + if(args.length < 1) { + usage(); + return; + } + + try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) { + + String chartTitle = modelReader.readLine(); // first line is chart title + String[] series = modelReader.readLine().split(","); + + // Category Axis Data + List listLanguages = new ArrayList<>(10); + + // Values + List listCountries = new ArrayList<>(10); + List listSpeakers = new ArrayList<>(10); + + // set model + String ln; + while((ln = modelReader.readLine()) != null) { + String[] vals = ln.split(","); + listCountries.add(Double.valueOf(vals[0])); + listSpeakers.add(Double.valueOf(vals[1])); + listLanguages.add(vals[2]); + } + + String[] categories = listLanguages.toArray(new String[listLanguages.size()]); + Double[] values1 = listCountries.toArray(new Double[listCountries.size()]); + Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]); + + try { + + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFChart chart = ppt.createChart(); + Rectangle2D rect2D = new java.awt.Rectangle(XDDFChart.DEFAULT_X, XDDFChart.DEFAULT_Y, + XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT); + slide.addChart(chart, rect2D); + setBarData(chart, chartTitle, series, categories, values1, values2); + // save the result + try (OutputStream out = new FileOutputStream("bar-chart-demo-output.pptx")) { + ppt.write(out); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + System.out.println("Done"); + } + + private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) { + // Use a category axis for the bottom axis. + XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); + bottomAxis.setTitle(series[2]); + XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); + leftAxis.setTitle(series[0]+","+series[1]); + leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); + + final int numOfPoints = categories.length; + final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0)); + final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1)); + final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2)); + final XDDFDataSource categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); + final XDDFNumericalDataSource valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1); + values1[6] = 16.0; // if you ever want to change the underlying data + final XDDFNumericalDataSource valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2); + + + XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); + XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData); + series1.setTitle(series[0], chart.setSheetTitle(series[0], 1)); + + XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2); + series2.setTitle(series[1], chart.setSheetTitle(series[1], 2)); + + bar.setVaryColors(true); + bar.setBarDirection(BarDirection.COL); + chart.plot(bar); + + XDDFChartLegend legend = chart.getOrAddLegend(); + legend.setPosition(LegendPosition.LEFT); + legend.setOverlay(false); + + chart.setTitleText(chartTitle); + chart.setTitleOverlay(false); + } +} + diff --git a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/ChartFromScratch.java b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/ChartFromScratch.java new file mode 100644 index 0000000000..4a1a78150f --- /dev/null +++ b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/ChartFromScratch.java @@ -0,0 +1,140 @@ +/* + * ==================================================================== + * 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.xwpf.usermodel.examples; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xddf.usermodel.chart.AxisCrosses; +import org.apache.poi.xddf.usermodel.chart.AxisPosition; +import org.apache.poi.xddf.usermodel.chart.BarDirection; +import org.apache.poi.xddf.usermodel.chart.ChartTypes; +import org.apache.poi.xddf.usermodel.chart.LegendPosition; +import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData; +import org.apache.poi.xddf.usermodel.chart.XDDFChart; +import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis; +import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend; +import org.apache.poi.xddf.usermodel.chart.XDDFDataSource; +import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory; +import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource; +import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis; +import org.apache.poi.xwpf.usermodel.XWPFChart; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +/** + * Build a chart without reading template file + */ +public class ChartFromScratch { + private static void usage(){ + System.out.println("Usage: BarChartExample "); + System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " + + "then go pairs {axis-label value}"); + } + + public static void main(String[] args) throws Exception { + if(args.length < 1) { + usage(); + return; + } + + try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) { + + String chartTitle = modelReader.readLine(); // first line is chart title + String[] series = modelReader.readLine().split(","); + + // Category Axis Data + List listLanguages = new ArrayList<>(10); + + // Values + List listCountries = new ArrayList<>(10); + List listSpeakers = new ArrayList<>(10); + + // set model + String ln; + while((ln = modelReader.readLine()) != null) { + String[] vals = ln.split(","); + listCountries.add(Double.valueOf(vals[0])); + listSpeakers.add(Double.valueOf(vals[1])); + listLanguages.add(vals[2]); + } + + String[] categories = listLanguages.toArray(new String[listLanguages.size()]); + Double[] values1 = listCountries.toArray(new Double[listCountries.size()]); + Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]); + + try (XWPFDocument doc = new XWPFDocument()) { + XWPFChart chart = doc.createChart(XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT); + setBarData(chart, chartTitle, series, categories, values1, values2); + // save the result + try (OutputStream out = new FileOutputStream("bar-chart-demo-output.docx")) { + doc.write(out); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + System.out.println("Done"); + } + + private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) { + // Use a category axis for the bottom axis. + XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); + bottomAxis.setTitle(series[2]); + XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); + leftAxis.setTitle(series[0]+","+series[1]); + leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); + + final int numOfPoints = categories.length; + final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0)); + final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1)); + final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2)); + final XDDFDataSource categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); + final XDDFNumericalDataSource valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1); + values1[6] = 16.0; // if you ever want to change the underlying data + final XDDFNumericalDataSource valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2); + + + XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); + XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData); + series1.setTitle(series[0], chart.setSheetTitle(series[0], 1)); + + XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2); + series2.setTitle(series[1], chart.setSheetTitle(series[1], 2)); + + bar.setVaryColors(true); + bar.setBarDirection(BarDirection.COL); + chart.plot(bar); + + XDDFChartLegend legend = chart.getOrAddLegend(); + legend.setPosition(LegendPosition.LEFT); + legend.setOverlay(false); + + chart.setTitleText(chartTitle); + chart.setTitleOverlay(false); + } +} + diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java index 321626d71f..4267898309 100644 --- a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java @@ -53,6 +53,7 @@ import org.apache.poi.xddf.usermodel.text.XDDFTextBody; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFTable; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; @@ -81,6 +82,27 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns; @Beta public abstract class XDDFChart extends POIXMLDocumentPart implements TextContainer { + + /** + * default width of chart in emu + */ + public static final int DEFAULT_WIDTH = 500000; + + /** + * default height of chart in emu + */ + public static final int DEFAULT_HEIGHT = 500000; + + /** + * default x-coordinate of chart in emu + */ + public static final int DEFAULT_X = 10; + + /** + * default y-coordinate value of chart in emu + */ + public static final int DEFAULT_Y = 10; + /** * Underlying workbook */ @@ -712,10 +734,29 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai XSSFRow row = this.getRow(sheet, 0); XSSFCell cell = this.getCell(row, column); cell.setCellValue(title); - this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, column); + + CTTable ctTable = this.getSheetTable(sheet); + + this.updateSheetTable(ctTable, title, column); return new CellReference(sheet.getSheetName(), 0, column, true, true); } + /** + * this method will check whether sheet have table + * in case table size zero then create new table and add table columns element + * @param sheet + * @return table object + */ + private CTTable getSheetTable(XSSFSheet sheet) { + if(sheet.getTables().size() == 0) + { + XSSFTable newTable = sheet.createTable(null); + newTable.getCTTable().addNewTableColumns(); + sheet.getTables().add(newTable); + } + return sheet.getTables().get(0).getCTTable(); + } + /** * this method update column header of sheet into table * @@ -729,7 +770,8 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai private void updateSheetTable(CTTable ctTable, String title, int index) { CTTableColumns tableColumnList = ctTable.getTableColumns(); CTTableColumn column = null; - for( int i = 0; tableColumnList.getCount() < index; i++) { + int columnCount = tableColumnList.getTableColumnList().size()-1; + for( int i = columnCount; i < index; i++) { column = tableColumnList.addNewTableColumn(); column.setId(i); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index 687ddc5f5b..b0cbc59dd1 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -302,14 +302,23 @@ public class XMLSlideShow extends POIXMLDocument * Create a blank chart on the given slide. */ public XSLFChart createChart(XSLFSlide slide) { + XSLFChart chart = createChart(); + slide.addRelation(null, XSLFRelation.CHART, chart); + return chart; + } + + /** + * This method is used to create template for chart XML. + * @return Xslf chart object + * @since POI 4.0.2 + */ + public XSLFChart createChart() { int chartIdx = findNextAvailableFileNameIndex(XSLFRelation.CHART, _charts.size() + 1); XSLFChart chart = (XSLFChart) createRelationship(XSLFRelation.CHART, XSLFFactory.getInstance(), chartIdx, true).getDocumentPart(); - slide.addRelation(null, XSLFRelation.CHART, chart); chart.setChartIndex(chartIdx); _charts.add(chart); return chart; } - /** * Return notes slide for the specified slide or create new if it does not exist yet. */ @@ -416,7 +425,7 @@ public class XMLSlideShow extends POIXMLDocument * Return all the charts in the slideshow */ public List getCharts() { - return _charts; + return Collections.unmodifiableList(_charts); } /** diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFChart.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFChart.java index 8e6612f875..5e8d73cd06 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFChart.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFChart.java @@ -19,16 +19,28 @@ package org.apache.poi.xslf.usermodel; +import java.awt.geom.Rectangle2D; import java.io.IOException; +import javax.xml.namespace.QName; + import org.apache.poi.ooxml.POIXMLFactory; import org.apache.poi.ooxml.POIXMLRelation; import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.util.Beta; import org.apache.poi.xddf.usermodel.chart.XDDFChart; +import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual; /** * Represents a Chart in a .pptx presentation @@ -36,6 +48,8 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; @Beta public final class XSLFChart extends XDDFChart { + private static String CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart"; + /** * Construct a PresentationML chart. */ @@ -90,4 +104,47 @@ public final class XSLFChart extends XDDFChart { }; } } + + /** + * method to add graphic frame for XSLF chart + * + * @param shapeId shape id + * @param rID relation id + * @param anchor size and location of chart + * @return graphic frame object + * @since POI 4.0.2 + */ + static CTGraphicalObjectFrame prototype(int shapeId, String rID, Rectangle2D anchor) { + CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance(); + CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr(); + + CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr(); + cnv.setName("Chart " + shapeId); + cnv.setId(shapeId); + nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true); + nvGr.addNewNvPr(); + + CTTransform2D xfrm = frame.addNewXfrm(); + + CTPoint2D off = xfrm.addNewOff(); + off.setX((int)anchor.getX()); + off.setY((int)anchor.getY()); + + CTPositiveSize2D ext = xfrm.addNewExt(); + ext.setCx((int)anchor.getWidth()); + ext.setCy((int)anchor.getHeight()); + + xfrm.setExt(ext); + xfrm.setOff(off); + + CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData(); + XmlCursor grCur = gr.newCursor(); + grCur.toNextToken(); + grCur.beginElement(new QName(CHART_URI, "chart")); + grCur.insertAttributeWithValue("id", PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS, rID); + grCur.dispose(); + + gr.setUri(CHART_URI); + return frame; + } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java index f4cd0d8e1c..ba93988d0b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java @@ -107,6 +107,19 @@ public class XSLFDrawing { return shape; } + /** + * This method will add chart into slide's graphic frame + * + * @param rID relation id of chart + * @param rect2D Chart Bounding values + * @since POI 4.0.2 + */ + public void addChart(String rID, Rectangle2D rect2D) { + CTGraphicalObjectFrame sp = _spTree.addNewGraphicFrame(); + sp.set(XSLFChart.prototype(_sheet.allocateShapeId(), rID, rect2D)); + } + + public XSLFObjectShape createOleShape(String pictureRel) { CTGraphicalObjectFrame sp = _spTree.addNewGraphicFrame(); sp.set(XSLFObjectShape.prototype(_sheet.allocateShapeId(), pictureRel)); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index b67264ba0f..2bcf063990 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -20,6 +20,7 @@ import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; import java.awt.Dimension; import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -52,6 +53,7 @@ import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.Units; +import org.apache.poi.xddf.usermodel.chart.XDDFChart; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; @@ -306,14 +308,13 @@ implements XSLFShapeContainer, Sheet { throw new IllegalArgumentException("pictureData needs to be of type XSLFPictureData"); } RelationPart rp = addRelation(null, XSLFRelation.IMAGES, (XSLFPictureData)pictureData); - + XSLFObjectShape sh = getDrawing().createOleShape(rp.getRelationship().getId()); CTOleObject oleObj = sh.getCTOleObject(); Dimension dim = pictureData.getImageDimension(); oleObj.setImgW(Units.toEMU(dim.getWidth())); oleObj.setImgH(Units.toEMU(dim.getHeight())); - - + getShapes().add(sh); sh.setParent(this); return sh; @@ -719,4 +720,28 @@ implements XSLFShapeContainer, Sheet { return (ph == null) ? null : new XSLFPlaceholderDetails(ph); } + /** + * this method will add chart into slide + * with default height, width, x and y + * @param chart xslf chart object + * @since POI 4.0.2 + */ + public void addChart(XSLFChart chart) { + Rectangle2D rect2D = new java.awt.Rectangle(XDDFChart.DEFAULT_X, XDDFChart.DEFAULT_Y, + XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT); + + this.addChart(chart, rect2D); + } + + /** + * this method will add chart into slide + * with given height, width, x and y + * @param chart xslf chart object + * @since POI 4.0.2 + */ + public void addChart(XSLFChart chart, Rectangle2D rect2D) { + RelationPart rp = addRelation(null, XSLFRelation.CHART, chart); + getDrawing().addChart(rp.getRelationship().getId(), rect2D); + } + } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFChart.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFChart.java index 44820a5871..495cde1bf9 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFChart.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFChart.java @@ -39,12 +39,12 @@ public class XWPFChart extends XDDFChart { /** * default width of chart in emu */ - public static final int DEFAULT_WIDTH = 500000; + public static final int DEFAULT_WIDTH = XDDFChart.DEFAULT_WIDTH; /** * default height of chart in emu */ - public static final int DEFAULT_HEIGHT = 500000; + public static final int DEFAULT_HEIGHT = XDDFChart.DEFAULT_HEIGHT; // lazy initialization private Long checksum; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java index e3cc314a4a..8e7e383d45 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -58,6 +58,7 @@ import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.wp.usermodel.HeaderFooterType; +import org.apache.poi.xddf.usermodel.chart.XDDFChart; import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; @@ -1672,7 +1673,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * @since POI 4.0.0 */ public XWPFChart createChart() throws InvalidFormatException, IOException { - return createChart(XWPFChart.DEFAULT_WIDTH, XWPFChart.DEFAULT_HEIGHT); + return createChart(XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT); } /** diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java index fbf4589765..b9cda3fd21 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java @@ -20,6 +20,7 @@ import static org.apache.poi.sl.TestCommonSL.sameColor; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -34,7 +35,7 @@ import org.junit.Test; * @author Yegor Kozlov */ public class TestXSLFSlide { - + @Test public void testReadShapes() throws IOException { XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); @@ -101,7 +102,7 @@ public class TestXSLFSlide { XSLFTable tbl = (XSLFTable)shapes4.get(0); assertEquals(3, tbl.getNumberOfColumns()); assertEquals(6, tbl.getNumberOfRows()); - + ppt.close(); } @@ -116,7 +117,7 @@ public class TestXSLFSlide { assertFalse(slide.getFollowMasterGraphics()); slide.setFollowMasterGraphics(true); assertTrue(slide.getFollowMasterGraphics()); - + ppt.close(); } @@ -174,7 +175,7 @@ public class TestXSLFSlide { XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1); XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1); assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData()); - + ppt.close(); } @@ -191,7 +192,23 @@ public class TestXSLFSlide { } } assertEquals(30, ppt.getSlides().size()); - + ppt.close(); - } -} \ No newline at end of file + } + + @Test + public void testCreateChart() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFChart chart = ppt.createChart(); + assertNotNull(chart); + + slide.addChart(chart); + assertEquals(XSLFRelation.CHART.getContentType(), chart.getPackagePart().getContentType()); + + String partName = slide.getRelationPartById("rId2").getDocumentPart().getPackagePart().getPartName().getName(); + assertEquals(partName, chart.getPackagePart().getPartName().getName()); + + ppt.close(); + } +} -- 2.39.5