问题
I am using POI 3.12-beta1 and have code that creates a line chart with multiple datasets and named series in the legend. However, the default settings for line charts in poi generate a line that has been smoothed over the data points. Empty values are also being plotted as 0, but we want the lines to stop at the first column where there is an empty cell.
I can go into the chart properties once it is rendered in an xlsx file and change these settings, but we need to have the xlsx rendered with these settings. I can't find anything in the available API to change these settings.
I used this sample class as a starting point for my code below http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 17, 18, 30);
Chart chart = drawing.createChart(anchor);
ChartLegend legend = chart.getOrCreateLegend();
legend.setPosition(LegendPosition.RIGHT);
LineChartData data = chart.getChartDataFactory().createLineChartData();
ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
int row = 2;
int startCol = 3;
int endCol = 17;
boolean abs = false;
ChartDataSource<Number> xs = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(row, row, startCol, endCol));
row = 10;
int seriesCol = 0;
ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(row, row, startCol, endCol));
LineChartSerie ser1 = data.addSerie(xs, ys1);
ser1.setTitle(new CellReference(sheet.getSheetName(), row, seriesCol, abs, abs));
row = 11;
ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(row, row, startCol, endCol));
LineChartSerie ser2 = data.addSerie(xs, ys2);
ser2.setTitle(new CellReference(sheet.getSheetName(), row, seriesCol, abs, abs));
row = 12;
ChartDataSource<Number> ys3 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(row, row, startCol, endCol));
LineChartSerie ser3 = data.addSerie(xs, ys3);
ser3.setTitle(new CellReference(sheet.getSheetName(), row, seriesCol, abs, abs));
chart.plot(data, new ChartAxis[] { bottomAxis, leftAxis });
回答1:
Thanks to Etienne for the code to set blanks as gaps. I got help from a POI developer and here is the solution that solves both issues mentioned in the original question.
XSSFChart chart = (XSSFChart)drawing.createChart(anchor);
// this will set blank values as gaps in the chart so you
// can accurately plot data series of different lengths
CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
disp.setVal(STDispBlanksAs.GAP);
chart.getCTChart().setDispBlanksAs(disp);
// setup chart, axes, data series, etc
chart.plot(data, new ChartAxis[] { bottomAxis, leftAxis });
// this must occur after the call to chart.plot above
CTPlotArea plotArea = chart.getCTChart().getPlotArea();
for (CTLineChart ch : plotArea.getLineChartList()) {
for (CTLineSer ser : ch.getSerList()) {
CTBoolean ctBool = CTBoolean.Factory.newInstance();
ctBool.setVal(false);
ser.setSmooth(ctBool);
}
}
回答2:
I couldn't find any solution to that same problem so I ended up trying to find some "creative workaround". It's not a clean approach at all, but I'll share it just in case.
It turns out that the default Chart POI interface doesn't allow to do a lot of operations (modify Axis and Legend, and that's about it).
I do work with XLSX files however, and the implementing XSSFChart class provides a bit more features, such as a setPlotOnlyVisibleCells method that does work in enabling/disabling that option in the "Hidden & Empty Cells" menu. However, that's not what we want!
If you look at the XLSX file format (which is basically XML), you'll notice there's a "dispBlanksAs" XML element as a child of the Chart element, and we'll want to set it to "gap". (POI won't set it, which is equivalent to set it to "zero").
Unfortunately, there's no such method in the POI API currently, so I had to resort to the following dirty code to get it working:
XSSFChart chart = (XSSFChart)drawing.createChart(anchor);
CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
disp.setVal(STDispBlanksAs.GAP);
chart.getCTChart().setDispBlanksAs(disp);
This code is very likely reprehensible in many ways, but it works for me :)
An important note is that you'll need to have the ooxml-schemas 1.1 jar on the classpath for this to work. It won't work even with poi-ooxml-schemas 3.12, as it doesn't contain the definition for CTDispBlanksAs class.
Hopefully this feature will be supported in a future version of POI.
来源:https://stackoverflow.com/questions/29014848/how-can-i-change-charts-generated-by-apache-poi-to-not-use-smoothed-lines-and-sh