使用poi-tl导出动态word模板,包含折线图、柱状图、饼状图

1 依赖引入

      <dependency>
          <groupId>com.deepoove</groupId>
          <artifactId>poi-tl</artifactId>
          <version>1.8.2</version>
    </dependency>

2 新建word模板

Word模板中所有变量以{{开头,以}}结尾,不同内容变量声明如下

1){{template}}    普通文本,渲染数据为:String或者TextRenderData

2){{#template}}   表格,渲染数据为:TableRenderData

3)当生成图表时,新建图表—>右键编辑替换文字—>{{barLineCharts}} 图表变量,如下图(可能不同版本编辑替换文字位置不同。)

3 java获取数据,生成word

1)声明模板的位置:

XWPFTemplate template = XWPFTemplate.compile("./src/main/resources/templates/template.docx");

2)导出word路径,名称

FileOutputStream out = new FileOutputStream("./src/main/resources/templates/output_"+String.valueOf(Math.random())+".docx");

 3)填充数据

//声明map存放模板中的内容
HashMap<String, Object> data = new HashMap<String, Object>();
data.put("title","hello world");
//Logger.info("hello");
/*测试文本插入------------------------------*/
//先定义文本对象
TextRenderData textRenderData = new TextRenderData();
//设置文本内容
textRenderData.setText("张三");
//设置文本格式
Style style = new Style();
style.setBold(true);
style.setColor("000F00");
style.setFontSize(20);
textRenderData.setStyle(style);
//将文本数据和模板中变量对应
data.put("name", textRenderData);
/* 测试表格插入---------------------------------------*/
		//定义表格的头
		//方式一
		//RowRenderData headerData = RowRenderData.build("电灯名称","使用率");
		//设置样式
		TableStyle tStyle = new TableStyle();
		tStyle.setBackgroundColor("87CEEB");
		//表头方式二
		/*RowRenderData headerData = RowRenderData.build(
				new TextRenderData("FFFFFF","仪器名称"),new TextRenderData("FFFFFF","使用率"));*/
		//表头方式三
		
		List<CellRenderData> listCellRenderDatas =new ArrayList<CellRenderData>();
		CellRenderData cellRenderData1 = new CellRenderData();
		cellRenderData1.setCellText(new TextRenderData("000000","电灯名称"));
		listCellRenderDatas.add(cellRenderData1);
		CellRenderData cellRenderData2 = new CellRenderData();
		cellRenderData2.setCellText(new TextRenderData("000000","使用率"));
		listCellRenderDatas.add(cellRenderData2);
		CellRenderData cellRenderData3 = new CellRenderData();
		cellRenderData3.setCellText(new TextRenderData("000000","使用年限"));
		listCellRenderDatas.add(cellRenderData3);
		RowRenderData headerData = new RowRenderData(listCellRenderDatas);
		headerData.setRowStyle(tStyle);		
		headerData.setCells(listCellRenderDatas);
		
		List<RowRenderData> listRowList = new ArrayList<RowRenderData>();
		
		//将数据存储为了后边生成图样式
		List<String> devname = new ArrayList<String>();
		List<Double> useRate = new ArrayList<Double>();
		List<Integer> useYear = new ArrayList<Integer>();
		
		for(int i = 0; i < 5; i++){
			
			//生成一行数据
			listRowList.add(RowRenderData.build("电灯_"+i,String.valueOf(Math.random()*100)+"%",String.valueOf(i+1)));
			
			//存入list,为了生成图表
			devname.add("电灯_"+i);
			useRate.add(Math.random()*100);
			useYear.add(i+1);
		}
		data.put("table",new MiniTableRenderData(headerData,listRowList));
		
		/* 测试图表的插入-------------------------------------*/
		//柱状图生成
		ChartMultiSeriesRenderData bar = new ChartMultiSeriesRenderData();
		bar.setChartTitle("barCharts");
		//参数为数组
		bar.setCategories(devname.toArray(new String[devname.size()]));
		List<SeriesRenderData> seriesRenderDatas = new ArrayList<SeriesRenderData>();
		seriesRenderDatas.add(new SeriesRenderData("使用率",useRate.toArray(new Double[useRate.size()])));
		seriesRenderDatas.add(new SeriesRenderData("使用年限",useYear.toArray(new Integer[useYear.size()])));
		bar.setSeriesDatas(seriesRenderDatas);
		data.put("barCharts",bar);
		
		//折线图生成
		ChartMultiSeriesRenderData line = new ChartMultiSeriesRenderData();
		line.setChartTitle("lineCharts");
		//参数为数组
		line.setCategories(devname.toArray(new String[devname.size()]));
		List<SeriesRenderData> seriesRenderDatas1 = new ArrayList<SeriesRenderData>();
		seriesRenderDatas1.add(new SeriesRenderData("使用率",useRate.toArray(new Double[useRate.size()])));
		seriesRenderDatas1.add(new SeriesRenderData("使用年限",useYear.toArray(new Integer[useYear.size()])));
		line.setSeriesDatas(seriesRenderDatas1);
		data.put("lineCharts",line);
		
		//柱状图、折线图共存
		ChartMultiSeriesRenderData barLine = new ChartMultiSeriesRenderData();
		barLine.setChartTitle("barLineCharts");
		barLine.setCategories(devname.toArray(new String[devname.size()]));
		
		List<SeriesRenderData> seriesRenderDatas2 = new ArrayList<SeriesRenderData>();
		SeriesRenderData seriesRenderData1 = new SeriesRenderData();
		seriesRenderData1.setName("使用率bar");
		seriesRenderData1.setValues(useRate.toArray(new Double[useRate.size()]));
		seriesRenderData1.setComboType(SeriesRenderData.ComboType.BAR);
		seriesRenderDatas2.add(seriesRenderData1);
		
		SeriesRenderData seriesRenderData2 = new SeriesRenderData();
		seriesRenderData2.setName("使用年限line");
		seriesRenderData2.setValues(useYear.toArray(new Integer[useYear.size()]));
		seriesRenderData2.setComboType(SeriesRenderData.ComboType.LINE);
		seriesRenderDatas2.add(seriesRenderData2);
		
		SeriesRenderData seriesRenderData3 = new SeriesRenderData();
		seriesRenderData3.setName("使用率line");
		seriesRenderData3.setValues(useRate.toArray(new Double[useRate.size()]));
		seriesRenderData3.setComboType(SeriesRenderData.ComboType.LINE);
		seriesRenderDatas2.add(seriesRenderData3);
		
		SeriesRenderData seriesRenderData4 = new SeriesRenderData();
		seriesRenderData4.setName("使用年限bar");
		seriesRenderData4.setValues(useYear.toArray(new Integer[useYear.size()]));
		seriesRenderData4.setComboType(SeriesRenderData.ComboType.BAR);
		seriesRenderDatas2.add(seriesRenderData4);
		
		barLine.setSeriesDatas(seriesRenderDatas2);
		data.put("barLineCharts",barLine);
		
		//饼状图
		ChartSingleSeriesRenderData pie = new ChartSingleSeriesRenderData();
		pie.setChartTitle("饼状图");
		pie.setCategories(devname.toArray(new String[devname.size()]));
		pie.setSeriesData(new SeriesRenderData("电灯数量",new Integer[]{120,25,89,65,49}));
		data.put("pie", pie);

4)写入数据导出

		/*将输入写入模板中------------------------------------------*/
		try {
			//将map数据放入模板
			template.render(data);
			//模板数据写入
			template.write(out);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		out.flush();
		out.close();
		template.close();

 

只写了用到的变量,还可以导入图片,可以参考官方文档。参考链接:http://deepoove.com/poi-tl/

### 如何使用 poi-tlWord 文档中生成带有百分比标签的饼状图 要通过 `poi-tl` 实现向 Word 文档中插入带百分比标签的饼状图,可以利用其内置的功能支持以及自定义工具类完成。以下是具体方法: #### 1. 引入必要的依赖 为了使用 `poi-tl` 的图表功能,需确保项目中已正确引入相关依赖项。通常情况下,Maven 构建文件中的配置如下所示[^1]: ```xml <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>4.4.0</version> </dependency> ``` #### 2. 准备数据对象 创建一个用于存储饼状图所需的数据模型。该模型应至少包含两个字段:类别名称和对应的数值。 ```java public class ChartData { private String category; private double value; public ChartData(String category, double value) { this.category = category; this.value = value; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public double getValue() { return value; } public void setValue(double value) { this.value = value; } } ``` #### 3. 使用 CustomCharts 工具类生成饼状图 `CustomCharts` 是 `poi-tl` 提供的一个插件类,允许开发者灵活定制各种类型的图表。对于饼状图而言,可以通过扩展 `CustomChartSingleSeriesRenderData` 来实现显示百分比的效果。 以下是一个完整的代码示例,展示如何生成并插入带有百分比标签的饼状图Word 文件中: ```java import cn.afterturn.easypoi.chart.entity.ChartEntity; import cn.afterturn.easypoi.chart.render.CustomChartSingleSeriesRenderData; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.word.WordExportUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; public class PieChartExample { public static void main(String[] args) throws Exception { List<ChartData> chartDataList = new ArrayList<>(); chartDataList.add(new ChartData("A", 30)); chartDataList.add(new ChartData("B", 70)); XWPFDocument document = ExcelExportUtil.exportWord(WordExportUtils.createDefaultTemplate()); // 创建饼状图实体 ChartEntity pieChart = new ChartEntity(); pieChart.setChartType("pie"); pieChart.setTitle("Sample Pie Chart with Percentage"); // 设置渲染器以显示百分比 CustomChartSingleSeriesRenderData renderData = new CustomChartSingleSeriesRenderData() { @Override protected Object getLabelValue(int index) { double percentage = (chartDataList.get(index).getValue() / getTotalValue()) * 100; return String.format("%.1f%%", percentage); } private double getTotalValue() { return chartDataList.stream().mapToDouble(ChartData::getValue).sum(); } }; // 将数据传递给渲染器 renderData.setData(chartDataList); // 添加图表到文档 WordExportUtils.insertChart(document, pieChart, renderData); try (FileOutputStream fos = new FileOutputStream("output_with_percentage_pie_chart.docx")) { document.write(fos); } } } ``` 上述代码实现了以下几个关键点: - 定义了一个简单的数据结构 `ChartData` 存储分类及其对应值。 - 利用了 `CustomChartSingleSeriesRenderData` 类来自定义每个扇区上的标签内容,并计算出相应的百分比。 - 调用 `WordExportUtils.insertChart()` 方法将生成好的图表嵌入到目标 Word 文档中。 #### 注意事项 如果在 Linux 环境下运行程序时遇到图形绘制失败的问题,则可能是因为缺少某些字体库或者 Java AWT 头部环境未被正确定位所致[^2]。此时可尝试调整 JVM 参数 `-Djava.awt.headless=true` 并确认服务器安装有完整支持绘图操作的基础包。 ---
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值