Apache POI 4 - Create LINE chart with multi empty cells - java

I do like to create a line chart base on my data-source but unfortunately, when the line chart y-series across multiple cells it hit NullPointException while plot chat.
I found the error occurred while the column were blank and force to set "0" to make it work.
Anyway, I could plot chart on the empty cells without hard-coded "0"?
Below is the way how i hard-coded the default value,
for (int i = 0; headers.size() > i; i++) {
row.createCell(i, CellType.NUMERIC);
}
Below is LineChart code:
int rows = numberOfRows - 1;
int cols = headers.size();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
chart.displayBlanksAs(DisplayBlanks.GAP);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setOrientation(AxisOrientation.MAX_MIN);
bottomAxis.setTitle("Date");
XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setTitle("Rates");
rightAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFChartLegend chartLegend = chart.getOrAddLegend();
chartLegend.setPosition(LegendPosition.TOP_RIGHT);
chartLegend.setOverlay(false);
XDDFLineChartData lineChartData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
lineChartData.setVaryColors(false);
XDDFDataSource<String> xs = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, rows, 1, 1));
for (int col = 2; cols > col; col++) {
XDDFNumericalDataSource<Double> ys = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, rows, col, col));
XDDFLineChartData.Series series = (XDDFLineChartData.Series) lineChartData.addSeries(xs, ys);
series.setTitle(headers.get(col), null);
series.setSmooth(false);
series.setMarkerStyle(MarkerStyle.NONE);
}
chart.plot(lineChartData);

Related

Manipulate bars from a chart

I need to change the first and the last bars. As you can see, both bars are halfed due the limits of the chart.
Which class from Apache POI librar should I use to change that?
This is the code which is drawing the chart
private ByteArrayInputStream generateFileDetails(List<ClientDataRequest> clientDataRequest, String metricName){
ByteArrayOutputStream file = new ByteArrayOutputStream();
try{
try(XSSFWorkbook workbook = new XSSFWorkbook()){
XSSFSheet sheet = workbook.createSheet(metricName);
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setUnderline(Font.U_SINGLE);
CellStyle headerCellStyle = workbook.createCellStyle();
headerCellStyle.setFillBackgroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
headerCellStyle.setFont(headerFont);
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 5, 1, 14, 10+ clientDataRequest.size());
Row headerRow = sheet.createRow(anchor.getRow2()+1);
headerRow.createCell(0).setCellValue("Client Name");
headerRow.createCell(1).setCellValue("Value");
for (int i = 0; i < headerRow.getLastCellNum(); i++) {
headerRow.getCell(i).setCellStyle(headerCellStyle);
}
for (int i = 0; i < clientDataRequest.size(); i++) {
Row row = sheet.createRow(anchor.getRow2()+2+i);
row.createCell(0).setCellValue(clientDataRequest.get(i).getClientName());
sheet.autoSizeColumn(0);
row.createCell(1).setCellValue(clientDataRequest.get(i).getValue());
sheet.autoSizeColumn(1);
}
XSSFChart chart = drawing.createChart(anchor);
chart.setTitleText(metricName);
chart.setTitleOverlay(false);
//XDDFChartLegend legend = chart.getOrAddLegend();
//legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("Client Name");
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("Value");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<String> clientNames = XDDFDataSourcesFactory.fromStringCellRange(sheet,
new CellRangeAddress(anchor.getRow2()+2, anchor.getRow2()+1+clientDataRequest.size(), 0, 0));
XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
new CellRangeAddress(anchor.getRow2()+2, anchor.getRow2()+1+clientDataRequest.size(), 1, 1));
XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
XDDFChartData.Series series = data.addSeries(clientNames, values);
XDDFLineProperties line = new XDDFLineProperties();
series.setTitle(null, null);
data.setVaryColors(false);
chart.plot(data);
XDDFBarChartData bar = (XDDFBarChartData) data;
bar.setBarDirection(BarDirection.BAR);
workbook.write(file);
}
} catch (Exception e){
}
return new ByteArrayInputStream(file.toByteArray());
}
It does not have many documentation and samples about the Apache POI.
For a bar chart you additional need set AxisCrossBetween for the value axis, so the value axis crosses the category axis between the categories. Else first and last category is exactly on cross points and the bars are only half visible.
In your case:
...
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("Value");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(org.apache.poi.xddf.usermodel.chart.AxisCrossBetween.BETWEEN);
...

Apache POI Charting with Dates

I have started working with Apache POI to create an Excel sheet that contains a chart. The chart is using data that is pretty simple, a date column and a numerical value column. I want to display the data in date reverse order so the newest data is at the top row in the spreadsheet, but I would like the chart to show the data in date normal order, because I'm also including a trend line, and the direction of the trend line is completely dependent on the ordering of the data. The date is being displayed on the x-axis, with the y-axis containing the numerical values. What I want to do is basically reverse all of the data on the chart. Is there some way to do this? In Google Sheets, it happens automatically, but that is not an option.
Here's the code I'm currently experimenting with:
public void addChart() {
final int NUM_OF_ROWS = ytd.size();
final int NUM_OF_COLUMNS = 2;
// Create a row and put some cells in it. Rows are 0 based.
XSSFRow row;
XSSFCell cell;
List<String> dates = new ArrayList<>();
List<Double> values = new ArrayList<>();
for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
row = (XSSFRow)sheet.createRow((short) rowIndex);
row.createCell(0).setCellValue(ytd.get(rowIndex).getShipDate());
dates.add(ytd.get(rowIndex).getShipDate());
for (int colIndex = 1; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(new BigDecimal(ytd.get(rowIndex).getSquareFeet().replaceAll("[,]", "")).doubleValue());
values.add(new BigDecimal(ytd.get(rowIndex).getSquareFeet().replaceAll("[,]", "")).doubleValue());
}
}
Collections.reverse(dates);
Collections.reverse(values);
for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
row = sheet.getRow((short) rowIndex);
row.createCell(2).setCellValue(dates.get(rowIndex));
for (int colIndex = 3; colIndex < 4; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(values.get(rowIndex));
}
}
XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(5, 5, 20, 20, 4, 4, 20, 25);
XSSFChart chart = drawing.createChart(anchor);
CTChart ctChart = ((XSSFChart) chart).getCTChart();
// XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFDateAxis bottomAxis = chart.createDateAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("Ship Date"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("Square Feet");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, NUM_OF_ROWS - 1, 2, 2));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, NUM_OF_ROWS-1, 3, 3));
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
series1.setTitle("SqFt", null); // https://stackoverflow.com/questions/21855842
series1.setSmooth(false); // https://stackoverflow.com/questions/29014848
series1.setMarkerStyle(MarkerStyle.DOT); // https://stackoverflow.com/questions/39636138
chart.plot(data);
// sheet.setColumnHidden(2, true);
// sheet.setColumnHidden(3, true);
// 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);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0)
.addNewTrendline()
.addNewTrendlineType()
.setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STTrendlineType.LINEAR);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
workbook.write(fileOut);
} catch (FileNotFoundException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
I've tried putting the data in columns that are hidden, which works fine in LibreOffice, but doesn't work in excel until I un-hide the columns. So does anyone know if there is a way to control the ordering of the graph data, separate from the data in the table?
I found the solution: you can change the direction of the data by modifying the category axis on the chart, using the enum AxisOrientation. A side effect of getting the data to chart in the order I want, is that the labels for the y-axis now appear on the right instead of the left, but I think I can live with that.

For Apache poi line chart, how to make first column doesn't display on y-axis

I use poi version is 4.1.1.
Now I want to make first column doesn't display on y-axis, means I want to add some space between y-axis and the first column.
I notice there is an option "Axis position" on x-axis, when it set to "Between tick marks", it will work as I want.
But I don't know how to make it using apache-poi. Is it possible to make it?
here is the "Asis position in excel"
now the line chart looks like
what I want
Thanks everyone!!!
Here is the code example from Apache website:
public class LineChart {
public static void main(String[] args) throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("linechart");
final int NUM_OF_ROWS = 3;
final int NUM_OF_COLUMNS = 10;
// Create a row and put some cells in it. Rows are 0 based.
Row row;
Cell cell;
for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1.0));
}
}
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.BOTTOM);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
//bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
//leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
series1.setTitle("a", null); // https://stackoverflow.com/questions/21855842
//series1.setSmooth(false); // https://stackoverflow.com/questions/29014848
series1.setMarkerStyle(MarkerStyle.NONE); // https://stackoverflow.com/questions/39636138
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2);
series2.setTitle("b", null);
//series2.setSmooth(true);
//series2.setMarkerSize((short) 6);
series2.setMarkerStyle(MarkerStyle.NONE); // https://stackoverflow.com/questions/39636138
CTBoolean ctBoolean = CTBoolean.Factory.newInstance();
ctBoolean.setVal(false);
CTPlotArea plotArea = chart.getCTChart().getPlotArea();
chart.getCTChartSpace().setRoundedCorners(ctBoolean);
for (CTLineSer ser : plotArea.getLineChartArray()[0].getSerArray()) {
CTDLbls ctdLbls = ser.addNewDLbls();
ctdLbls.setShowSerName(ctBoolean);
ctdLbls.setShowLegendKey(ctBoolean);
ctdLbls.setShowLeaderLines(ctBoolean);
ctdLbls.setShowCatName(ctBoolean);
CTDLblPos ctdLblPos = CTDLblPos.Factory.newInstance();
ctdLblPos.setVal(STDLblPos.CTR);
CTDLblPos.Factory.newInstance();
ctdLbls.setDLblPos(ctdLblPos);
}
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.LIGHT_GREEN);
solidLineSeries(data, 1, PresetColor.DARK_RED);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
wb.write(fileOut);
}
}
}
//CTPresetLineDashProperties
private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
if (index == 0) {
line.setPresetDash(new XDDFPresetLineDash(PresetLineDash.DOT));
}
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);
}
}
Per default the value axis and the category axis crosses exactly on category point. So if value axis crosses category axis at point 0, then it looks like your result now.
But if x axis is a category axis, then there is a setting XDDFValueAxis.setCrossBetween. If that is set to AxisCrossBetween.BETWEEN then the value axis crosses the category axis between the category points. This looks as you want.
So in your case:
...
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
//bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
//leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
...
Btw.: You should get rid of deprecated methods.
For example the get...Array() methods of ooxml-schemas are deprecated. Either you get a concrete item from the array using get...Array(item) or you get a List using get...List().
In your case:
...
//for (CTLineSer ser : plotArea.getLineChartArray()[0].getSerArray()) {
for (CTLineSer ser : plotArea.getLineChartArray(0).getSerList()) {
...
And also XDDFChartData.getSeries() is deprecated. If you need one series do using XDDFChartData.getSeries(index)
In your case:
...
//XDDFChartData.Series series = data.getSeries().get(index);
XDDFChartData.Series series = data.getSeries(index);
...

POI 4.1.0 Line-Chart y-series showed wrong legend

how can i create a line chart with single legend on y-series instead of showing multiple legend bease on x-series
int rows = numberOfRows - 1;
int cols = headers.size();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
chart.displayBlanksAs(DisplayBlanks.GAP);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setOrientation(AxisOrientation.MAX_MIN);
bottomAxis.setTitle("Date");
XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setTitle("Rates");
rightAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFChartLegend chartLegend = chart.getOrAddLegend();
chartLegend.setPosition(LegendPosition.TOP_RIGHT);
chartLegend.setOverlay(false);
XDDFLineChartData lineChartData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
XDDFDataSource<String> xs = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, rows, 0, 0));
for (int col = 1; col < cols; col++) {
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, rows, col, col));
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) lineChartData.addSeries(xs, ys1);
series1.setTitle(headers.get(col), null);
series1.setSmooth(false);
series1.setMarkerStyle(MarkerStyle.NONE);
}
chart.plot(lineChartData);
Above image is showing my current plot Line-Chart, the y-series is expect only 1 legend but it was showed multiple
Above image Line-Chart is plot using excel, the y-series is only show 1 legend
There is a setting for varying the colors of same-series data markers in a chart. See: Vary the colors of same-series data markers in a chart. That was false per default up to Excel 2007. Now Microsoftdecided to make that setting true per default. So you need explictly set that false if you do not want it.
In your case:
...
XDDFLineChartData lineChartData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
lineChartData.setVaryColors(false);
...

Setting the color of an Excel sheet scatter chart marker icon with Apache POI

The scatter chart example included with Apache POI shows how to set the color of a line (that connects markers in a series), but I cannot figure out how to set the color of a marker for a series. I see that I can change the marker icon (with setMarkerStyle (javadoc), but that does not appear to have editable color properties).
From a previous SO question I suspect that it will be necessary to disable the vary colors configuration, but I still do not know how to set the colors after that step (if the following line is even necessary).
((XSSFChart)chart).getCTChart().getPlotArea().getScatterChartArray(0)
.addNewVaryColors().setVal(false);
How can I specify the marker icon colors in the example below?
public class ScatterChart {
public static void main(String[] args) throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("Sheet 1");
final int NUM_OF_ROWS = 3;
final int NUM_OF_COLUMNS = 10;
// Create a row and put some cells in it. Rows are 0 based.
Row row;
Cell cell;
for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1.0));
}
}
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
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);
}
}
The previous question you linked is from May 2018 and is about the pure XSSFChart stuff from apache poi upto version 3.17. This is outdated since apache poi 4.0.0 introduced the new XDDF stuff.
Nevertheless setting the marker color is not supported until now using only the high level XDDF classes. The marker has shape properties having fill properties of the same kind as the series itself. So we can use XDDFSolidFillProperties and XDDFShapeProperties as for the line settings. But to get the marker, we need using the low level underlying ooxml-schemas-1.4 beans.
Example:
...
series2.setMarkerStyle(MarkerStyle.DIAMOND);
series2.setMarkerSize((short)15);
XDDFSolidFillProperties fillMarker = new XDDFSolidFillProperties(XDDFColor.from(new byte[]{(byte)0xFF, (byte)0xFF, 0x00}));
XDDFShapeProperties propertiesMarker = new XDDFShapeProperties();
propertiesMarker.setFillProperties(fillMarker);
chart.getCTChart().getPlotArea().getScatterChartArray(0).getSerArray(1).getMarker()
.addNewSpPr().set(propertiesMarker.getXmlObject());
...

Categories

Resources