Apache POI 柱状图(Bar Chart)Java 实现
概述
本文介绍如何使用 Apache POI 在 word 文档中生成柱状图(Bar Chart),文档格式要求为 docx,对应于 Apache POI 中的 XWPFDocument。文中最后会附上完整的代码实现。
Bar Chart 成品图
在开始之前,同样先放上成果展示,我们的目标就是实现该成品图
为了大家更好的理解这张图和以及后面的代码,我们对图中的元素做一下分解
从上图我们可以看出以下一些元素,这些元素在后面的代码中都会体现:
- 第一个元素是分类:英语、数学、计算机和财经
- 第二元素是系列:共有两个系列,第一个系列是选修人数,第二个系列是课程的课时数
- 第三个元素是图例,通过图例我们能很轻松的区分出两个系列,其中第一个系列是红色柱状图,第二个系列是绿色柱状图
Java 实现柱状图
1、准备数据容器
在开始之前我们提供几个工具类,ChartData/SerieData 用来存储柱状图用到的数据,BarChartRenderer 用来绘制柱状图。可以结合后面的代码在回过头来查看,由于篇幅关系,省略 getter 和 setter:
public class ChartData {
// 图表的标题
private String title;
// 分类
private List<String> categories;
// 每个系列的数据
private List<SerieData> series;
}
public class SerieData {
// 系列名称
private String name;
// 系列数据
private List<Number> data;
// 系列的颜色
private PresetColor color = PresetColor.ALICE_BLUE;
}
/**
* 柱状图绘制
*/
public class BarChartRenderer {
public void render(XWPFDocument document, ChartData chartData) throws IOException, InvalidFormatException {
// 这里的实现拆分到下面的代码片段中,从第 2 - 5 小节,第 6 小节为 main 方法,展示该方法的用法
}
}
代码拆的很零碎,主要是方便讲述,完整代码 Github 传送点
2、在文档中创建图并构造 xy 轴
XWPFChart chart = document.createChart(14 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
yAxis.setCrosses(AxisCrosses.AUTO_ZERO);
yAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
3、构造数据源
// 构造分类数据源
String[] categories = chartData.getCategories().toArray(new String[0]);
XDDFDataSource<String> categoryDS = XDDFDataSourcesFactory.fromArray(categories);
// 构造系列数据源
List<XDDFNumericalDataSource<Number>> valueDS = new ArrayList<>();
List<SerieData> seriesData = chartData.getSeries();
for (SerieData seriesDatum : seriesData) {
XDDFNumericalDataSource<Number> s = XDDFDataSourcesFactory.fromArray(seriesDatum.getData().toArray(new Number[0]));
valueDS.add(s);
}
这里构造系列数据源的时候使用了 for 循环,因为系列是可以有任意多个的,虽然我们这里只有两个系列:一个是选课人数,另一个是课时数。
4、将数据源绑定到图表
XDDFChartData data = chart.createData(ChartTypes.BAR, xAxis, yAxis);
// 控制柱子方向,柱子可以竖直方向也可以水平方向,这里为竖直方向
((XDDFBarChartData) data).setBarDirection(BarDirection.COL);
// 这可以控制柱子的宽度,值越大柱子越细
((XDDFBarChartData) data).setGapWidth(500);
// 如果只有一个系列,那么 setVaryColors(false),否则每个柱子的颜色都不一样
data.setVaryColors(seriesData.size() > 1);
// 将数据源绑定到图表
int i = 0;
for (XDDFNumericalDataSource<Number> value : valueDS) {
XDDFChartData.Series series = data.addSeries(categoryDS, value);
// 设置系列的名称,系列的名称会显示在图例中
series.setTitle(seriesData.get(i).getName(), null);
// 针对 LibreOffice 的设置,否则无法在 LibreOffice 中正常显示
solidFillSeries(series, seriesData.get(i).getColor());
i++;
}
private static void solidFillSeries(XDDFChartData.Series series, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setFillProperties(fill);
series.setShapeProperties(properties);
}
5、设置图例并绘制图表
// 图例
XDDFChartLegend legend = chart.getOrAddLegend();
// 图例显示在图表正下方
legend.setPosition(LegendPosition.BOTTOM);
legend.setOverlay(false);
// 绘制图表
chart.plot(data);
6、将图表保存到 Word 中
在 BarChartRenderer 中添加一个 main 方法,准备图表数据,并调用 render 方法绘制图表,最后将图表保存到 XWPF 文档中。
ChartData chartData = new ChartData();
chartData.setTitle("专业课选修人数/课时数");
chartData.setCategories(Arrays.asList("英语", "数学", "计算机", "财经"));
// 构造系列数据
List<SerieData> seriesData = new ArrayList<>();
// 选修人数:英语 100 人,数学 200 人,计算机 800 人,财经 50 人
seriesData.add(createSerieData("选修人数", Arrays.asList(100, 200, 800, 50), PresetColor.RED));
// 课时:英语 50 课时 ...
seriesData.add(createSerieData("课时数", Arrays.asList(50, 60, 40, 75), PresetColor.DARK_GREEN));
chartData.setSeries(seriesData);
XWPFDocument document = new XWPFDocument();
new BarChartRenderer().render(document, chartData);
try (FileOutputStream fo = new FileOutputStream("D:\\bar.docx")) {
document.write(fo);
}
Apache POI 绘制柱状图 Maven 依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
<version>5.2.3</version>
</dependency>
注意不同的 POI 版本所需的依赖可能不同,这点在 Apache POI 饼图(Pie Chart)Java 实现 有说明,这里不再赘述。
有问题吗?点此反馈!
温馨提示:反馈需要登录