如何使用ApachePOI4.0.1和java生成可编辑的堆叠条形图?
我想使用ApachePOI4.0.1和Java语言for Excel创建堆叠条形图 输出excel文件的扩展名应为.xlsx 生成的图表应具有图表标题和数据标签 生成的图表还应该能够在每列顶部显示所有数据的总和,您可以看到每列的总和显示在黄色框中 你可以参考下面的图片,以更清楚地了解我在寻找什么。 堆叠条形图的数据如何使用ApachePOI4.0.1和java生成可编辑的堆叠条形图?,java,excel,apache-poi,stacked-chart,apache-poi-4,Java,Excel,Apache Poi,Stacked Chart,Apache Poi 4,我想使用ApachePOI4.0.1和Java语言for Excel创建堆叠条形图 输出excel文件的扩展名应为.xlsx 生成的图表应具有图表标题和数据标签 生成的图表还应该能够在每列顶部显示所有数据的总和,您可以看到每列的总和显示在黄色框中 你可以参考下面的图片,以更清楚地了解我在寻找什么。 堆叠条形图的数据 根据中的条形图和折线图示例,我们还可以根据此处的要求获得组合图。但到目前为止,并非所有请求都只能使用高级XDDF类。我们需要使用底层的低级ooxml-schemas-1.4bean进
根据中的条形图和折线图示例,我们还可以根据此处的要求获得组合图。但到目前为止,并非所有请求都只能使用高级XDDF类。我们需要使用底层的低级ooxml-schemas-1.4bean进行一些必要的修改。因此,ooxml-schemas-1.4.jar需要位于类路径中 在以下代码中,对官方示例进行了以下更改: leftAxis.setcrossbetween轴crossbetween.BETWEEN;一切就绪。因此,类别轴与笔划之间的值轴相交,而不是笔划的中点。否则,第一个和最后一个类别的条形图只有半宽可见 chart.getCTChart.getPlotArea.getBarChartArray0.addNewOverlap.setValbyte100;将重叠设置为100%。否则,单个系列的钢筋不会真正堆叠,而是并排放置 只有使用底层的低级ooxml-schemas-1.4bean才能添加数据标签 附加折线图必须有自己的轴,这些轴彼此正确交叉。但这些斧子必须是隐形的 因为在添加到图表时,折线图不知道已经存在的条形图的某些信息,它的ID再次以0开头。但这对于组合图表来说是错误的。所以我们需要更正id和顺序。它不能再次以0开头,因为已经有三个条形系列 下面的代码需要一个StackedBarAndLineChart.xlsx,它具有A1:E11范围内第一页问题中提供的数据 代码: 结果: 编辑2019-03-01:
我对代码做了一些改进。在本例中,它现在根据A2中的第一个类别值确定类别轴的类型。对于数据标签,明确设置位置,明确设置仅显示值,而不显示图例键、类别名称或系列名称 根据中的条形图和折线图示例,我们还可以根据此处的要求获得组合图。但到目前为止,并非所有请求都只能使用高级XDDF类。我们需要使用底层的低级ooxml-schemas-1.4bean进行一些必要的修改。因此,ooxml-schemas-1.4.jar需要位于类路径中 在以下代码中,对官方示例进行了以下更改: leftAxis.setcrossbetween轴crossbetween.BETWEEN;一切就绪。因此,类别轴与笔划之间的值轴相交,而不是笔划的中点。否则,第一个和最后一个类别的条形图只有半宽可见 chart.getCTChart.getPlotArea.getBarChartArray0.addNewOverlap.setValbyte100;将重叠设置为100%。否则,单个系列的钢筋不会真正堆叠,而是并排放置 只有使用底层的低级ooxml-schemas-1.4bean才能添加数据标签 附加折线图必须有自己的轴,这些轴彼此正确交叉。但这些斧子必须是隐形的 因为在添加到图表时,折线图不知道已经存在的条形图的某些信息,它的ID再次以0开头。但这对于组合图表来说是错误的。所以我们需要更正id和顺序。它不能再次以0开头,因为已经有三个条形系列 下面的代码需要一个StackedBarAndLineChart.xlsx,它具有A1:E11范围内第一页问题中提供的数据 代码: 结果: 编辑2019-03-01:
我对代码做了一些改进。在本例中,它现在根据A2中的第一个类别值确定类别轴的类型。对于数据标签,明确设置位置,明确设置仅显示值,而不显示图例键、类别名称或系列名称 看。已经链接了一个条形图示例。请尝试一下,并告诉我们为什么这不能满足您的要求。对于你的屏幕截图:如果没有至少提供图表的基础数据,这是没有用的。请提供这些数据。@AxelRichter我已经在问题的主体部分添加了数据。您已经添加了数据的图片。因此,可能的助手需要手动重新键入该图片中的数据。数据没有那么多。那么,为什么不在问题中提供它们作为文本呢?我的其他建议呢?您是否尝试过BarChat.java示例?请参阅。已经链接了一个条形图示例。请尝试一下,并告诉我们为什么这不能满足您的要求
恩茨。对于你的屏幕截图:如果没有至少提供图表的基础数据,这是没有用的。请提供这些数据。@AxelRichter我已经在问题的主体部分添加了数据。您已经添加了数据的图片。因此,可能的助手需要手动重新键入该图片中的数据。数据没有那么多。那么,为什么不在问题中提供它们作为文本呢?我的其他建议呢?您是否尝试过BarChat.java示例?我已经创建了名为StackedBarAndLineChart.xlsx的excel文件。我还在类路径中添加了ooxml-schemas-1.4.jar。但我得到了以下例外。--------线程主线程java.lang.NullPointerException中的异常位于org.apache.poi.xddf.usermodel.chart.XDDFChartData$Series.fillStringCacheXDDFChartData.java:264位于org.apache.poi.xddf.usermodel.chart.XDDFChartData$Series.plotXDDFChartData.java:157位于org.apache.poi.xddf.XDDFChart.plotXDDFChart.java:344位于xls.StackedBarAndLineChart.mainStackedBarAndLineChart.java:50@shubham帕瓦尔:我的A栏是一个文本栏。A2=10/01和A3=10/02以及A4:A11中的值是我的Excel中的文本。它必须是Excel中的日期值。但在我所在的地区,10/01不是一个有意义的日期。但是XDDFDataSource date=XDDFDataSourcesFactory.fromStringCellRange。。。这是错误的。请将A2:A11更改为文本。今天下午我们将尝试在A2:A11为日期值时如何工作。非常感谢Axel。我已将A列更改为文本,现在正在创建excel文件,但数据标签有问题。数据标签在图表上显示三个值示例-总计、10/06、11,而不是仅显示一个值示例-11。我如何对这个问题进行排序?@shubham pawar:什么Excel版本?也许我们必须设置.getDLbls.addNewShowCatName.setValfalse;显式地也是.getDLbls.addNewShowSerName.setValfalse@我正在使用Excel 2013。现在,它正在创建一个带有值的图表,但值位于条形图的右侧,而不是正好位于条形图的中间。我还在类路径中添加了ooxml-schemas-1.4.jar。但我得到了以下例外。--------线程主线程java.lang.NullPointerException中的异常位于org.apache.poi.xddf.usermodel.chart.XDDFChartData$Series.fillStringCacheXDDFChartData.java:264位于org.apache.poi.xddf.usermodel.chart.XDDFChartData$Series.plotXDDFChartData.java:157位于org.apache.poi.xddf.XDDFChart.plotXDDFChart.java:344位于xls.StackedBarAndLineChart.mainStackedBarAndLineChart.java:50@shubham帕瓦尔:我的A栏是一个文本栏。A2=10/01和A3=10/02以及A4:A11中的值是我的Excel中的文本。它必须是Excel中的日期值。但在我所在的地区,10/01不是一个有意义的日期。但是XDDFDataSource date=XDDFDataSourcesFactory.fromStringCellRange。。。这是错误的。请将A2:A11更改为文本。今天下午我们将尝试在A2:A11为日期值时如何工作。非常感谢Axel。我已将A列更改为文本,现在正在创建excel文件,但数据标签有问题。数据标签在图表上显示三个值示例-总计、10/06、11,而不是仅显示一个值示例-11。我如何对这个问题进行排序?@shubham pawar:什么Excel版本?也许我们必须设置.getDLbls.addNewShowCatName.setValfalse;显式地也是.getDLbls.addNewShowSerName.setValfalse@我正在使用Excel 2013。现在,它正在创建一个带有值的图表,但值位于条的右侧,而不是条的正中间。
Date Category High Medium Low
10/01 3 0 3 0
10/02 3 0 2 1
10/03 3 0 2 1
10/04 4 1 2 1
10/05 11 1 7 3
10/08 14 1 10 3
10/09 15 1 11 3
10/10 15 1 11 3
10/11 15 0 11 4
10/12 8 0 6 2
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
public class StackedBarAndLineChart {
public static void main(String[] args) throws IOException {
try (FileInputStream in = new FileInputStream("StackedBarAndLineChart.xlsx");
XSSFWorkbook wb = (XSSFWorkbook)WorkbookFactory.create(in)) {
XSSFSheet sheet = wb.getSheetAt(0);
// determine the type of the category axis from it's first category value (value in A2 in this case)
XDDFDataSource date = null;
CellType type = CellType.ERROR;
Row row = sheet.getRow(1);
if (row != null) {
Cell cell = row.getCell(0);
if (cell != null) {
type = cell.getCellType();
if (type == CellType.STRING) {
date = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, 10, 0, 0));
} else if (type == CellType.NUMERIC) {
date = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 10, 0, 0));
} else if (type == CellType.FORMULA) {
type = cell.getCachedFormulaResultType();
if (type == CellType.STRING) {
date = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, 10, 0, 0));
} else if (type == CellType.NUMERIC) {
date = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 10, 0, 0));
}
}
}
}
if (date != null) { // if no type of category axis found, don't create a chart at all
XDDFNumericalDataSource<Double> high = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 10, 2, 2));
XDDFNumericalDataSource<Double> medium = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 10, 3, 3));
XDDFNumericalDataSource<Double> low = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 10, 4, 4));
XDDFNumericalDataSource<Double> category = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 10, 1, 1));
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 6, 0, 16, 20);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.RIGHT);
// bar chart
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("Number of defects");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
// category axis crosses the value axis between the strokes and not midpoint the strokes
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
XDDFChartData.Series series1 = data.addSeries(date, high);
series1.setTitle("high", new CellReference(sheet.getSheetName(), 0, 2, true, true));
XDDFChartData.Series series2 = data.addSeries(date, medium);
series2.setTitle("medium", new CellReference(sheet.getSheetName(), 0, 3, true, true));
XDDFChartData.Series series3 = data.addSeries(date, low);
series3.setTitle("low", new CellReference(sheet.getSheetName(), 0, 4, true, true));
chart.plot(data);
XDDFBarChartData bar = (XDDFBarChartData) data;
bar.setBarDirection(BarDirection.COL);
// looking for "Stacked Bar Chart"? uncomment the following line
bar.setBarGrouping(BarGrouping.STACKED);
// correcting the overlap so bars really are stacked and not side by side
chart.getCTChart().getPlotArea().getBarChartArray(0).addNewOverlap().setVal((byte)100);
solidFillSeries(data, 0, PresetColor.CORNFLOWER_BLUE);
solidFillSeries(data, 1, PresetColor.LIGHT_SALMON);
solidFillSeries(data, 2, PresetColor.LIGHT_GRAY);
// add data labels
for (int s = 0 ; s < 3; s++) {
chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).addNewDLbls();
chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls()
.addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.CTR);
chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowVal().setVal(true);
chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowLegendKey().setVal(false);
chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowCatName().setVal(false);
chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowSerName().setVal(false);
}
// line chart
// axis must be there but must not be visible
bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setVisible(false);
leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setVisible(false);
// set correct cross axis
bottomAxis.crossAxis(leftAxis);
leftAxis.crossAxis(bottomAxis);
data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series4 = (XDDFLineChartData.Series)data.addSeries(date, category);
series4.setTitle("total", null);
series4.setSmooth(false);
series4.setMarkerStyle(MarkerStyle.STAR);
chart.plot(data);
// correct the id and order, must not start 0 again because there are three bar series already
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getIdx().setVal(3);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getOrder().setVal(3);
solidLineSeries(data, 0, PresetColor.YELLOW);
// add data labels
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).addNewDLbls();
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls()
.addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte)255,(byte)255,0});
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls()
.addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.CTR);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(true);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(false);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(false);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(false);
}
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("StackedBarAndLineChartResult.xlsx")) {
wb.write(fileOut);
}
}
}
private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setFillProperties(fill);
series.setShapeProperties(properties);
}
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);
}
}