# poi 生成word统计图表
基于word 模板生成柱状图、条形图、饼图等
# 效果图
模板的原始效果:
生成之后的效果:
# 生成统计图
word 生成统计图表有多种方式,比如通过渲染直接生成,还可以借助图表工具生成图片,然后引入到 word 中。本文介绍的是基于模板生成统计图表。
我们打开一个正常的统计图表,然后右击选择 “编辑数据”,发现其实它的数据源对应的就是一个 excel ,我们把对应的 excel 数据编辑也就完成了图表的生成。
# 具体实现代码
poi 版本为:4.1.2
package org.demo;
import cn.hutool.core.util.RandomUtil;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFChart;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.List;
//需要注意的是excel 第一行对应的索引为0!!!
class ExcelChangeChartData {
public static void main(String[] args) throws Exception {
//数据范围的开始行
int firstDataRow = 1;
//数据范围的结束行
int lastDataRow = 0;
//类目所对应的列
int categoryColumn = 0;
//数据对应的列,示例中展示的是一个双维度的柱状图,索引这里是2个元素,分别对应了数据列的位置
int[] seriesColumns = new int[]{1, 2};
//读取模板
FileInputStream fis = new FileInputStream("D:\\test-file\\example.docx");
XWPFDocument doc = new XWPFDocument(fis);
//获取图表对象
List<XWPFChart> charts = doc.getCharts();
//拿到第一个图表
XWPFChart chart = charts.get(0);
//对应的类目
String[] months = new String[]{"11.1", "11.2", "11.3"};
for (int m = 0; m < months.length; m++) {
String monthResult = months[m ];
XSSFWorkbook workbook = chart.getWorkbook();
//可以理解为 获取excel实例
XSSFSheet sheet = workbook.getSheetAt(0);
//创建一行数据,其实这里是第2行数据,第2行数据模板里边已经有了就是对应的 日志系统告警 订单系统告警
XSSFRow row = sheet.createRow(lastDataRow + 1);
//根据下标创建单元格 这里创建的是类目所对应的单元格
XSSFCell cell = row.createCell(categoryColumn);
//设置类目的值
cell.setCellValue(monthResult);
//遍历添加测试数据
for (int i = 0; i < seriesColumns.length; i++) {
cell = row.createCell(seriesColumns[i]);
cell.setCellValue(RandomUtil.randomInt(10, 100));
}
lastDataRow++;
//获取图表对应数据集
XDDFChartData chartData0 = chart.getChartSeries().get(0);
updateChartData(Arrays.asList(chartData0), sheet, firstDataRow, lastDataRow, categoryColumn, seriesColumns);
}
FileOutputStream fos = new FileOutputStream("D:\\test-file\\example-1.docx");
doc.write(fos);
//这里的关闭不是很合适,请注意处理关闭的异常情况
fos.close();
doc.close();
fis.close();
}
//刷新图表数据到word
static void updateChartData(List<XDDFChartData> chart, XSSFSheet dataSheet,
int firstDataRow, int lastDataRow, int categoryColumn, int[] seriesColumns) {
for (XDDFChartData chartData : chart) {s
for (int s = 0; s < chartData.getSeriesCount(); s++) {
XDDFChartData.Series series = chartData.getSeries(s);
if (seriesColumns.length > s) {
//生成类目数据 firstDataRow 开始行 lastDataRow 结束行 categoryColumn 对应列索引
XDDFCategoryDataSource category = XDDFDataSourcesFactory.fromStringCellRange(
dataSheet, new CellRangeAddress(firstDataRow, lastDataRow, categoryColumn, categoryColumn));
//获取维度引用列
int seriesColumn = seriesColumns[s];
XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(
dataSheet, new CellRangeAddress(firstDataRow, lastDataRow, seriesColumn, seriesColumn));
series.replaceData(category, values);
series.plot();
}
}
}
}
}