basic bubble chart support

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1903272 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
PJ Fanning 2022-08-07 22:19:10 +00:00
parent f6a320770b
commit 72983be276
16 changed files with 579 additions and 82 deletions

View File

@ -150,6 +150,13 @@ public class XDDFArea3DChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTAreaSer getCTAreaSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -23,12 +23,7 @@ import java.util.Map;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAreaChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAreaSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFAreaChartData extends XDDFChartData {
@ -131,6 +126,13 @@ public class XDDFAreaChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTAreaSer getCTAreaSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -24,12 +24,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBar3DChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFBar3DChartData extends XDDFChartData {
@ -202,6 +197,13 @@ public class XDDFBar3DChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTBarSer getCTBarSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -24,12 +24,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFBarChartData extends XDDFChartData {
@ -192,6 +187,13 @@ public class XDDFBarChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTBarSer getCTBarSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -0,0 +1,224 @@
/* ====================================================================
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.List;
import java.util.Map;
import java.util.Collections;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBubbleChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBubbleSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumData;
/**
* @since POI 5.2.3
*/
@Beta
public class XDDFBubbleChartData extends XDDFChartData {
private CTBubbleChart chart;
public XDDFBubbleChartData(
XDDFChart parent,
CTBubbleChart chart,
XDDFChartAxis category,
XDDFValueAxis values) {
super(parent);
this.chart = chart;
Map<Long, XDDFChartAxis> categories = null;
Map<Long, XDDFValueAxis> mapValues = null;
categories = Collections.singletonMap(category.getId(), category);
mapValues = Collections.singletonMap(values.getId(), values);
for (CTBubbleSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getXVal(), series.getYVal()));
}
defineAxes(categories, mapValues);
}
@Internal
protected XDDFBubbleChartData(
XDDFChart parent,
CTBubbleChart chart,
Map<Long, XDDFChartAxis> categories,
Map<Long, XDDFValueAxis> values) {
super(parent);
this.chart = chart;
for (CTBubbleSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getXVal(), series.getYVal()));
}
defineAxes(categories, values);
}
private void defineAxes(Map<Long, XDDFChartAxis> categories, Map<Long, XDDFValueAxis> values) {
if (chart.sizeOfAxIdArray() == 0) {
for (Long id : categories.keySet()) {
chart.addNewAxId().setVal(id);
}
for (Long id : values.keySet()) {
chart.addNewAxId().setVal(id);
}
}
defineAxes(chart.getAxIdArray(), categories, values);
}
@Internal
@Override
protected void removeCTSeries(int n) {
chart.removeSer(n);
}
@Override
public void setVaryColors(Boolean varyColors) {
if (varyColors == null) {
if (chart.isSetVaryColors()) {
chart.unsetVaryColors();
}
} else {
if (chart.isSetVaryColors()) {
chart.getVaryColors().setVal(varyColors);
} else {
chart.addNewVaryColors().setVal(varyColors);
}
}
}
@Override
public XDDFChartData.Series addSeries(XDDFDataSource<?> category,
XDDFNumericalDataSource<? extends Number> values) {
final long index = this.parent.incrementSeriesCount();
try {
final CTBubbleSer ctSer = this.chart.addNewSer();
ctSer.addNewXVal();
ctSer.addNewYVal();
ctSer.addNewIdx().setVal(index);
ctSer.addNewOrder().setVal(index);
final Series added = new Series(ctSer, category, values);
this.series.add(added);
return added;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public class Series extends XDDFChartData.Series {
private CTBubbleSer series;
protected Series(CTBubbleSer series, XDDFDataSource<?> category, XDDFNumericalDataSource<?> values) {
super(category, values);
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTBubbleSer getCTBubbleSer() {
return series;
}
protected Series(CTBubbleSer series, CTAxDataSource category, CTNumDataSource values) {
super(XDDFDataSourcesFactory.fromDataSource(category), XDDFDataSourcesFactory.fromDataSource(values));
this.series = series;
}
public void setBubbleSizes(XDDFNumericalDataSource<?> values) {
try {
if (series.isSetBubbleSize()) series.unsetBubbleSize();
CTNumDataSource bubbleSizes = series.addNewBubbleSize();
CTNumData cache = retrieveNumCache(bubbleSizes, values);
values.fillNumericalCache(cache);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx();
} else {
return series.addNewTx();
}
}
@Override
public void setShowLeaderLines(boolean showLeaderLines) {
if (!series.isSetDLbls()) {
series.addNewDLbls();
}
if (series.getDLbls().isSetShowLeaderLines()) {
series.getDLbls().getShowLeaderLines().setVal(showLeaderLines);
} else {
series.getDLbls().addNewShowLeaderLines().setVal(showLeaderLines);
}
}
@Override
public XDDFShapeProperties getShapeProperties() {
if (series.isSetSpPr()) {
return new XDDFShapeProperties(series.getSpPr());
} else {
return null;
}
}
@Override
public void setShapeProperties(XDDFShapeProperties properties) {
if (properties == null) {
if (series.isSetSpPr()) {
series.unsetSpPr();
}
} else {
if (series.isSetSpPr()) {
series.setSpPr(properties.getXmlObject());
} else {
series.addNewSpPr().set(properties.getXmlObject());
}
}
}
@Override
protected CTAxDataSource getAxDS() {
return series.getXVal();
}
@Override
protected CTNumDataSource getNumDS() {
return series.getYVal();
}
@Override
protected void setIndex(long val) {
series.getIdx().setVal(val);
}
@Override
protected void setOrder(long val) {
series.getOrder().setVal(val);
}
@Override
protected List<CTDPt> getDPtList() {
return series.getDPtList();
}
}
}

View File

@ -380,7 +380,7 @@ public abstract class XDDFChartData {
return strCache;
}
private CTNumData retrieveNumCache(final CTNumDataSource numDataSource, XDDFDataSource<?> data) {
protected CTNumData retrieveNumCache(final CTNumDataSource numDataSource, XDDFDataSource<?> data) {
CTNumData numCache;
if (data.isReference()) {
CTNumRef numRef;

View File

@ -23,12 +23,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDoughnutChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFDoughnutChartData extends XDDFChartData {
@ -142,6 +137,13 @@ public class XDDFDoughnutChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTPieSer getCTPieSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -87,31 +87,31 @@ public class XDDFLine3DChartData extends XDDFChartData {
return Grouping.valueOf(chart.getGrouping().getVal());
}
public void setGrouping(Grouping grouping) {
if (chart.getGrouping() != null) {
chart.getGrouping().setVal(grouping.underlying);
} else {
chart.addNewGrouping().setVal(grouping.underlying);
}
}
public void setGrouping(Grouping grouping) {
if (chart.getGrouping() != null) {
chart.getGrouping().setVal(grouping.underlying);
} else {
chart.addNewGrouping().setVal(grouping.underlying);
}
}
public Integer getGapDepth() {
return (chart.isSetGapDepth()) ? POIXMLUnits.parsePercent(chart.getGapDepth().xgetVal()) / 1000 : null;
}
public Integer getGapDepth() {
return (chart.isSetGapDepth()) ? POIXMLUnits.parsePercent(chart.getGapDepth().xgetVal()) / 1000 : null;
}
public void setGapDepth(Integer depth) {
if (depth == null) {
if (chart.isSetGapDepth()) {
chart.unsetGapDepth();
}
} else {
if (chart.isSetGapDepth()) {
chart.getGapDepth().setVal(depth);
} else {
chart.addNewGapDepth().setVal(depth);
}
}
}
public void setGapDepth(Integer depth) {
if (depth == null) {
if (chart.isSetGapDepth()) {
chart.unsetGapDepth();
}
} else {
if (chart.isSetGapDepth()) {
chart.getGapDepth().setVal(depth);
} else {
chart.addNewGapDepth().setVal(depth);
}
}
}
@Override
public XDDFChartData.Series addSeries(XDDFDataSource<?> category,
@ -141,6 +141,13 @@ public class XDDFLine3DChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTLineSer getCTLineSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -23,13 +23,7 @@ import java.util.Map;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTMarker;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFLineChartData extends XDDFChartData {
@ -122,6 +116,13 @@ public class XDDFLineChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTLineSer getCTLineSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -22,12 +22,7 @@ import java.util.List;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPie3DChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFPie3DChartData extends XDDFChartData {
@ -91,6 +86,13 @@ public class XDDFPie3DChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTPieSer getCTPieSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -116,6 +116,13 @@ public class XDDFPieChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTPieSer getCTPieSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -23,13 +23,7 @@ import java.util.Map;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarStyle;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFRadarChartData extends XDDFChartData {
@ -122,6 +116,13 @@ public class XDDFRadarChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTRadarSer getCTRadarSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -23,14 +23,7 @@ import java.util.Map;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
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;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterStyle;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFScatterChartData extends XDDFChartData {
@ -128,6 +121,13 @@ public class XDDFScatterChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTScatterSer getCTScatterSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -23,12 +23,7 @@ import java.util.Map;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurface3DChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurfaceSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
@Beta
public class XDDFSurface3DChartData extends XDDFChartData {
@ -128,6 +123,13 @@ public class XDDFSurface3DChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTSurfaceSer getCTSurfaceSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -128,6 +128,13 @@ public class XDDFSurfaceChartData extends XDDFChartData {
this.series = series;
}
/**
* @since POI 5.2.3
*/
public CTSurfaceSer getCTSurfaceSer() {
return series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {

View File

@ -0,0 +1,231 @@
/* ====================================================================
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.charts;
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xddf.usermodel.PresetColor;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.junit.jupiter.api.Test;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import java.io.IOException;
import java.util.GregorianCalendar;
/**
* Tests for XSSFBubbleChartData.
*/
public final class TestXSSFBubbleChartData {
@Test
void testExample() throws IOException {
Object[][] chartData = new Object[][]{
new Object[]{"", "Category 1"},
new Object[]{"Bubble Size", "Bubble Date"},
new Object[]{1000, new GregorianCalendar(2020, 0, 1)},
new Object[]{10, new GregorianCalendar(2020, 0, 1)},
new Object[]{300, new GregorianCalendar(2021, 0, 1)},
new Object[]{"", ""},
new Object[]{"", "Category 2"},
new Object[]{"Bubble Size", "Bubble Date"},
new Object[]{100, new GregorianCalendar(2018, 0, 1)},
new Object[]{100, new GregorianCalendar(2020, 0, 1)}
};
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("bubblechart");
DataFormat format = wb.createDataFormat();
XSSFCellStyle dateStyle = wb.createCellStyle();
dateStyle.setDataFormat(14);
// put sheet data
Row row;
Cell cell;
int rowIndex = 0;
int colIndex = 0;
for (Object[] dataRow : chartData) {
row = sheet.createRow((short) rowIndex);
colIndex = 0;
for (Object value : dataRow) {
cell = row.createCell((short) colIndex);
if (value instanceof String) cell.setCellValue((String)value);
if (value instanceof Number) cell.setCellValue(((Number)value).doubleValue());
if (value instanceof GregorianCalendar) {
cell.setCellValue((GregorianCalendar)value);
cell.setCellStyle(dateStyle);
}
colIndex++;
}
rowIndex++;
}
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
// create the chart
// chart data sources
XDDFDataSource<Double> xs1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 4, 1, 1));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 4, 0, 0));
XDDFNumericalDataSource<Double> bSz1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 4, 0, 0));
XDDFDataSource<Double> xs2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(8, 9, 1, 1));
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(8, 9, 0, 0));
XDDFNumericalDataSource<Double> bSz2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(8, 9, 0, 0));
// chart in drawing
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 3, 0, 15, 20);
XSSFChart chart = drawing.createChart(anchor);
chart.setTitleText("Chart Title");
chart.setTitleOverlay(false);
chart.getFormattedTitle().getParagraph(0).addDefaultRunProperties().setFontSize(20d);
// value axis x
XDDFValueAxis valAxisX = chart.createValueAxis(AxisPosition.BOTTOM);
valAxisX.setTitle("Axis Title");
// value axis y
XDDFValueAxis valAxisY = chart.createValueAxis(AxisPosition.LEFT);
valAxisY.setTitle("Axis Title");
// cross axes
valAxisY.setCrosses(AxisCrosses.AUTO_ZERO);
// chart data
//XDDFChartData data = chart.createData(ChartTypes.???, valAxisX, valAxisY);
XDDFBubbleChartData data = new XDDFBubbleChartData(chart, chart.getCTChart().getPlotArea().addNewBubbleChart(), valAxisX, valAxisY);
// series
XDDFBubbleChartData.Series series1 = (XDDFBubbleChartData.Series)data.addSeries(xs1, ys1);
series1.setTitle("Category 1", new CellReference(sheet.getSheetName(), 0, 1, true, true));
// set bubble sizes
series1.setBubbleSizes(bSz1);
// add data labels
// pos 8 = INT_R , showVal = true, showLegendKey= false, showCatName = true
CTDLbls ctDLbls = setDataLabels(series1, 8, true, false, true);
XDDFBubbleChartData.Series series2 = (XDDFBubbleChartData.Series)data.addSeries(xs2, ys2);
series2.setTitle("Category 2", new CellReference(sheet.getSheetName(), 6, 1, true, true));
// set bubble sizes
series2.setBubbleSizes(bSz2);
// add data labels
// pos 8 = INT_R , showVal = true, showLegendKey= false, showCatName = true
ctDLbls = setDataLabels(series2, 8, true, false, true);
// plot chart
chart.plot(data);
// legend
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.RIGHT);
// set series fill color
solidFillSeries(data, 0, PresetColor.BLUE);
solidFillSeries(data, 1, PresetColor.RED);
// set rounded corners false
setRoundedCorners(chart, false);
// Write the output to a file
try (UnsynchronizedByteArrayOutputStream outStream = new UnsynchronizedByteArrayOutputStream()) {
wb.write(outStream);
try (XSSFWorkbook wb2 = new XSSFWorkbook(outStream.toInputStream())) {
// see if this fails
}
}
}
}
private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFChartData.Series series = data.getSeries(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setFillProperties(fill);
series.setShapeProperties(properties);
}
private static CTDLbls setDataLabels(XDDFChartData.Series series, int pos, boolean... show) {
/*
INT_BEST_FIT 1
INT_B 2
INT_CTR 3
INT_IN_BASE 4
INT_IN_END 5
INT_L 6
INT_OUT_END 7
INT_R 8
INT_T 9
*/
CTDLbls ctDLbls = null;
if (series instanceof XDDFBarChartData.Series) {
CTBarSer ctBarSer = ((XDDFBarChartData.Series)series).getCTBarSer();
if (ctBarSer.isSetDLbls()) ctBarSer.unsetDLbls();
ctDLbls = ctBarSer.addNewDLbls();
if (!(pos == 3 || pos == 4 || pos == 5 || pos == 7)) pos = 3; // bar chart does not provide other pos
ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
} else if (series instanceof XDDFLineChartData.Series) {
CTLineSer ctLineSer = ((XDDFLineChartData.Series)series).getCTLineSer();
if (ctLineSer.isSetDLbls()) ctLineSer.unsetDLbls();
ctDLbls = ctLineSer.addNewDLbls();
if (!(pos == 3 || pos == 6 || pos == 8 || pos == 9 || pos == 2)) pos = 3; // line chart does not provide other pos
ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
} else if (series instanceof XDDFPieChartData.Series) {
CTPieSer ctPieSer = ((XDDFPieChartData.Series)series).getCTPieSer();
if (ctPieSer.isSetDLbls()) ctPieSer.unsetDLbls();
ctDLbls = ctPieSer.addNewDLbls();
if (!(pos == 3 || pos == 1 || pos == 4 || pos == 5)) pos = 3; // pie chart does not provide other pos
ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
} else if (series instanceof XDDFBubbleChartData.Series) {
CTBubbleSer ctBubbleSer = ((XDDFBubbleChartData.Series)series).getCTBubbleSer();
if (ctBubbleSer.isSetDLbls()) ctBubbleSer.unsetDLbls();
ctDLbls = ctBubbleSer.addNewDLbls();
if (!(pos == 3 || pos == 2 || pos == 6 || pos == 8 || pos == 9)) pos = 3; // bubble chart does not provide other pos
ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
}// else if ...
if (ctDLbls != null) {
ctDLbls.addNewShowVal().setVal((show.length>0)?show[0]:false);
ctDLbls.addNewShowLegendKey().setVal((show.length>1)?show[1]:false);
ctDLbls.addNewShowCatName().setVal((show.length>2)?show[2]:false);
ctDLbls.addNewShowSerName().setVal((show.length>3)?show[3]:false);
ctDLbls.addNewShowPercent().setVal((show.length>4)?show[4]:false);
ctDLbls.addNewShowBubbleSize().setVal((show.length>5)?show[5]:false);
ctDLbls.addNewShowLeaderLines().setVal((show.length>6)?show[8]:false);
return ctDLbls;
}
return null;
}
private static void setRoundedCorners(XDDFChart chart, boolean setVal) {
if (chart.getCTChartSpace().getRoundedCorners() == null) chart.getCTChartSpace().addNewRoundedCorners();
chart.getCTChartSpace().getRoundedCorners().setVal(setVal);
}
}