From 5430141cfb3a831231b705e5bcd78f05c4db9f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alain=20B=C3=A9arez?= Date: Wed, 3 Oct 2018 14:32:34 +0000 Subject: [PATCH] XDDF improvements based on StackOverflow examples git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1842728 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xslf/usermodel/BarChartDemo.java | 11 ++-- .../poi/xssf/usermodel/examples/BarChart.java | 12 ++-- .../xssf/usermodel/examples/LineChart.java | 40 ++++++++++++- .../xssf/usermodel/examples/ScatterChart.java | 32 ++++++++-- .../usermodel/examples/BarChartExample.java | 11 ++-- .../xddf/usermodel/chart/DisplayBlanks.java | 45 ++++++++++++++ .../usermodel/chart/XDDFBarChartData.java | 6 +- .../poi/xddf/usermodel/chart/XDDFChart.java | 18 ++++++ .../usermodel/chart/XDDFLineChartData.java | 43 ++++++++++++- .../usermodel/chart/XDDFPieChartData.java | 6 +- .../usermodel/chart/XDDFRadarChartData.java | 6 +- .../usermodel/chart/XDDFScatterChartData.java | 60 +++++++++++++++++-- 12 files changed, 261 insertions(+), 29 deletions(-) create mode 100644 src/ooxml/java/org/apache/poi/xddf/usermodel/chart/DisplayBlanks.java diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/BarChartDemo.java b/src/examples/src/org/apache/poi/xslf/usermodel/BarChartDemo.java index 7b052b7da..bd26f8c73 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/BarChartDemo.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/BarChartDemo.java @@ -107,10 +107,13 @@ public class BarChartDemo { 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); - bar.getSeries().get(0).replaceData(categoriesData, valuesData); - bar.addSeries(categoriesData, valuesData2); - bar.getSeries().get(0).setTitle(series[0], chart.setSheetTitle(series[0], 0)); - bar.getSeries().get(1).setTitle(series[1], chart.setSheetTitle(series[1], 1)); + + XDDFChartData.Series series1 = bar.getSeries().get(0); + series1.replaceData(categoriesData, valuesData); + series1.setTitle(series[0], chart.setSheetTitle(series[0], 0)); + XDDFChartData.Series series2 = bar.addSeries(categoriesData, valuesData2); + series2.setTitle(series[1], chart.setSheetTitle(series[1], 1)); + chart.plot(bar); } diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/BarChart.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/BarChart.java index 5e695decf..c9e73efab 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/BarChart.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/BarChart.java @@ -84,8 +84,10 @@ public class BarChart { XDDFNumericalDataSource ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1)); XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); - data.addSeries(xs, ys1); - data.addSeries(xs, ys2); + XDDFChartData.Series series1 = data.addSeries(xs, ys1); + series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842 + XDDFChartData.Series series2 = data.addSeries(xs, ys2); + series2.setTitle("3x", null); chart.plot(data); // in order to transform a bar chart into a column chart, you just need to change the bar direction @@ -106,12 +108,12 @@ public class BarChart { private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) { XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color)); - XDDFChartData.Series firstSeries = data.getSeries().get(index); - XDDFShapeProperties properties = firstSeries.getShapeProperties(); + XDDFChartData.Series series = data.getSeries().get(index); + XDDFShapeProperties properties = series.getShapeProperties(); if (properties == null) { properties = new XDDFShapeProperties(); } properties.setFillProperties(fill); - firstSeries.setShapeProperties(properties); + series.setShapeProperties(properties); } } diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java index 3a1e0e858..9a48f4757 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java @@ -22,15 +22,22 @@ import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xddf.usermodel.PresetColor; +import org.apache.poi.xddf.usermodel.XDDFColor; +import org.apache.poi.xddf.usermodel.XDDFLineProperties; +import org.apache.poi.xddf.usermodel.XDDFShapeProperties; +import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties; import org.apache.poi.xddf.usermodel.chart.AxisCrosses; import org.apache.poi.xddf.usermodel.chart.AxisPosition; import org.apache.poi.xddf.usermodel.chart.ChartTypes; import org.apache.poi.xddf.usermodel.chart.LegendPosition; +import org.apache.poi.xddf.usermodel.chart.MarkerStyle; import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis; import org.apache.poi.xddf.usermodel.chart.XDDFChartData; 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.XDDFLineChartData; import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource; import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis; import org.apache.poi.xssf.usermodel.XSSFChart; @@ -77,15 +84,42 @@ public class LineChart { XDDFNumericalDataSource ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1)); XDDFNumericalDataSource ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1)); - XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); - data.addSeries(xs, ys1); - data.addSeries(xs, ys2); + XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); + XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1); + series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842 + series1.setSmooth(false); // https://stackoverflow.com/questions/29014848 + series1.setMarkerStyle(MarkerStyle.STAR); // https://stackoverflow.com/questions/39636138 + XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2); + series2.setTitle("3x", null); + series2.setSmooth(true); + series2.setMarkerSize((short) 6); + series2.setMarkerStyle(MarkerStyle.TRIANGLE); // https://stackoverflow.com/questions/39636138 chart.plot(data); + // if your series have missing values like https://stackoverflow.com/questions/29014848 + // chart.displayBlanksAs(DisplayBlanks.GAP); + + // https://stackoverflow.com/questions/24676460 + solidLineSeries(data, 0, PresetColor.CHARTREUSE); + solidLineSeries(data, 1, PresetColor.TURQUOISE); + // Write the output to a file try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) { wb.write(fileOut); } } } + + private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) { + XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color)); + XDDFLineProperties line = new XDDFLineProperties(); + line.setFillProperties(fill); + XDDFChartData.Series series = data.getSeries().get(index); + XDDFShapeProperties properties = series.getShapeProperties(); + if (properties == null) { + properties = new XDDFShapeProperties(); + } + properties.setLineProperties(line); + series.setShapeProperties(properties); + } } diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java index 9b96ee312..8c62436e5 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java @@ -25,6 +25,11 @@ import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xddf.usermodel.PresetColor; +import org.apache.poi.xddf.usermodel.XDDFColor; +import org.apache.poi.xddf.usermodel.XDDFLineProperties; +import org.apache.poi.xddf.usermodel.XDDFShapeProperties; +import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties; import org.apache.poi.xddf.usermodel.chart.AxisCrosses; import org.apache.poi.xddf.usermodel.chart.AxisPosition; import org.apache.poi.xddf.usermodel.chart.ChartTypes; @@ -34,6 +39,7 @@ 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.XDDFScatterChartData; import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis; import org.apache.poi.xssf.usermodel.XSSFChart; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; @@ -79,16 +85,34 @@ public class ScatterChart { XDDFNumericalDataSource ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1)); - XDDFChartData data = chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis); - - data.addSeries(xs, ys1); - data.addSeries(xs, ys2); + XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis); + XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1); + series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842 + series1.setSmooth(false); // https://stackoverflow.com/questions/39636138 + XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2); + series2.setTitle("3x", null); chart.plot(data); + solidLineSeries(data, 0, PresetColor.CHARTREUSE); + solidLineSeries(data, 1, PresetColor.TURQUOISE); + // Write the output to a file try (FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx")) { wb.write(fileOut); } } } + + private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) { + XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color)); + XDDFLineProperties line = new XDDFLineProperties(); + line.setFillProperties(fill); + XDDFChartData.Series series = data.getSeries().get(index); + XDDFShapeProperties properties = series.getShapeProperties(); + if (properties == null) { + properties = new XDDFShapeProperties(); + } + properties.setLineProperties(line); + series.setShapeProperties(properties); + } } diff --git a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExample.java b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExample.java index d1e7f6b8b..55185cbf8 100644 --- a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExample.java +++ b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExample.java @@ -109,10 +109,13 @@ public class BarChartExample { 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); - bar.getSeries().get(0).replaceData(categoriesData, valuesData); - bar.addSeries(categoriesData, valuesData2); - bar.getSeries().get(0).setTitle(series[0], chart.setSheetTitle(series[0], 0)); - bar.getSeries().get(1).setTitle(series[1], chart.setSheetTitle(series[1], 1)); + + XDDFChartData.Series series1 = bar.getSeries().get(0); + series1.replaceData(categoriesData, valuesData); + series1.setTitle(series[0], chart.setSheetTitle(series[0], 0)); + XDDFChartData.Series series2 = bar.addSeries(categoriesData, valuesData2); + series2.setTitle(series[1], chart.setSheetTitle(series[1], 1)); + chart.plot(bar); } diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/DisplayBlanks.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/DisplayBlanks.java new file mode 100644 index 000000000..0d8bbbfb0 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/DisplayBlanks.java @@ -0,0 +1,45 @@ +/* ==================================================================== + 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.xddf.usermodel.chart; + +import java.util.HashMap; + +import org.openxmlformats.schemas.drawingml.x2006.chart.STDispBlanksAs; + +public enum DisplayBlanks { + GAP(STDispBlanksAs.GAP), + SPAN(STDispBlanksAs.SPAN), + ZERO(STDispBlanksAs.ZERO); + + final STDispBlanksAs.Enum underlying; + + DisplayBlanks(STDispBlanksAs.Enum mode) { + this.underlying = mode; + } + + private final static HashMap reverse = new HashMap<>(); + static { + for (DisplayBlanks value : values()) { + reverse.put(value.underlying, value); + } + } + + static DisplayBlanks valueOf(STDispBlanksAs.Enum mode) { + return reverse.get(mode); + } +} diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFBarChartData.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFBarChartData.java index 9f1004ad2..ce79733aa 100644 --- a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFBarChartData.java +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFBarChartData.java @@ -135,7 +135,11 @@ public class XDDFBarChartData extends XDDFChartData { @Override protected CTSerTx getSeriesText() { - return series.getTx(); + if (series.isSetTx()) { + return series.getTx(); + } else { + return series.addNewTx(); + } } @Override 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 d146e59d0..7357381e7 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 @@ -214,6 +214,24 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai chart.getAutoTitleDeleted().setVal(deleted); } + /** + * @since 4.0.1 + * + */ + public void displayBlanksAs(DisplayBlanks as) { + if (as == null){ + if (chart.isSetDispBlanksAs()) { + chart.unsetDispBlanksAs(); + } + } else { + if (chart.isSetDispBlanksAs()) { + chart.getDispBlanksAs().setVal(as.underlying); + } else { + chart.addNewDispBlanksAs().setVal(as.underlying); + } + } + } + /** * @since 4.0.1 */ diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFLineChartData.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFLineChartData.java index 687bc44ab..4d4f00ce9 100644 --- a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFLineChartData.java +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFLineChartData.java @@ -100,7 +100,11 @@ public class XDDFLineChartData extends XDDFChartData { @Override protected CTSerTx getSeriesText() { - return series.getTx(); + if (series.isSetTx()) { + return series.getTx(); + } else { + return series.addNewTx(); + } } @Override @@ -139,7 +143,44 @@ public class XDDFLineChartData extends XDDFChartData { } } + /** + * @since 4.0.1 + */ + public Boolean getSmooth() { + if (series.isSetSmooth()) { + return series.getSmooth().getVal(); + } else { + return null; + } + } + + /** + * @param smooth + * whether or not to smooth lines, if null then reverts to default. + * @since 4.0.1 + */ + public void setSmooth(Boolean smooth) { + if (smooth == null) { + if (series.isSetSmooth()) { + series.unsetSmooth(); + } + } else { + if (series.isSetSmooth()) { + series.getSmooth().setVal(smooth); + } else { + series.addNewSmooth().setVal(smooth); + } + } + } + + /** + * @param size + *
Minimum inclusive:
2
Maximum inclusive:
72
+ */ public void setMarkerSize(short size) { + if (size < 2 || 72 < size) { + throw new IllegalArgumentException("Minimum inclusive: 2; Maximum inclusive: 72"); + } CTMarker marker = getMarker(); if (marker.isSetSize()) { marker.getSize().setVal(size); diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFPieChartData.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFPieChartData.java index 3d7cac674..988b48e84 100644 --- a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFPieChartData.java +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFPieChartData.java @@ -75,7 +75,11 @@ public class XDDFPieChartData extends XDDFChartData { @Override protected CTSerTx getSeriesText() { - return series.getTx(); + if (series.isSetTx()) { + return series.getTx(); + } else { + return series.addNewTx(); + } } @Override diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFRadarChartData.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFRadarChartData.java index ce1cd5965..a7917c30f 100644 --- a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFRadarChartData.java +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFRadarChartData.java @@ -104,7 +104,11 @@ public class XDDFRadarChartData extends XDDFChartData { @Override protected CTSerTx getSeriesText() { - return series.getTx(); + if (series.isSetTx()) { + return series.getTx(); + } else { + return series.addNewTx(); + } } @Override diff --git a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFScatterChartData.java b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFScatterChartData.java index 22f7eea39..eec3a3730 100644 --- a/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFScatterChartData.java +++ b/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFScatterChartData.java @@ -22,6 +22,7 @@ import java.util.Map; import org.apache.poi.util.Beta; import org.apache.poi.xddf.usermodel.XDDFShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTMarker; import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart; import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer; @@ -108,7 +109,11 @@ public class XDDFScatterChartData extends XDDFChartData { @Override protected CTSerTx getSeriesText() { - return series.getTx(); + if (series.isSetTx()) { + return series.getTx(); + } else { + return series.addNewTx(); + } } /** @@ -123,13 +128,58 @@ public class XDDFScatterChartData extends XDDFChartData { } /** + * @param smooth + * whether or not to smooth lines, if null then reverts to default. * @since 4.0.1 */ - public void setSmooth(boolean smooth) { - if (series.isSetSmooth()) { - series.getSmooth().setVal(smooth); + public void setSmooth(Boolean smooth) { + if (smooth == null) { + if (series.isSetSmooth()) { + series.unsetSmooth(); + } } else { - series.addNewSmooth().setVal(smooth); + if (series.isSetSmooth()) { + series.getSmooth().setVal(smooth); + } else { + series.addNewSmooth().setVal(smooth); + } + } + } + + /** + * @param size + *
Minimum inclusive:
2
Maximum inclusive:
72
+ * @since 4.0.1 + */ + public void setMarkerSize(short size) { + if (size < 2 || 72 < size) { + throw new IllegalArgumentException("Minimum inclusive: 2; Maximum inclusive: 72"); + } + CTMarker marker = getMarker(); + if (marker.isSetSize()) { + marker.getSize().setVal(size); + } else { + marker.addNewSize().setVal(size); + } + } + + /** + * @since 4.0.1 + */ + public void setMarkerStyle(MarkerStyle style) { + CTMarker marker = getMarker(); + if (marker.isSetSymbol()) { + marker.getSymbol().setVal(style.underlying); + } else { + marker.addNewSymbol().setVal(style.underlying); + } + } + + private CTMarker getMarker() { + if (series.isSetMarker()) { + return series.getMarker(); + } else { + return series.addNewMarker(); } }