专题页网站,wordpress展开 折叠功能,wordpress用户头像,公司网站如何做二维码文章目录 前言一、需求背景二、方案分析三、 POI-TL JFreeChart 实现3.1 Maven 依赖3.3 word模板设置3.2 实现代码 踩坑 前言
在开发过程中#xff0c;我们经常需要生成包含动态数据和图表的 Word 报告。本文将介绍如何结合 POI-TL 和 JFreeChart#xff0c;实现动态生成 W… 文章目录 前言一、需求背景二、方案分析三、 POI-TL JFreeChart 实现3.1 Maven 依赖3.3 word模板设置3.2 实现代码 踩坑 前言
在开发过程中我们经常需要生成包含动态数据和图表的 Word 报告。本文将介绍如何结合 POI-TL 和 JFreeChart实现动态生成 Word 报告的功能并分享一些实际开发中的踩坑经验。 word生成方案
freemarkerftlpot-tl模板替换poi硬编码
一、需求背景
在之前的文章中我们已经介绍了如何使用模板替换、复杂表格和图片插入等功能。此次的需求是生成一个包含统计图的 Word 报告统计图需要根据动态数据生成。面临的主要问题包括
选择 Word 生成方案如何在 Word 中动态插入数据和图表图片插入方案如何将生成的统计图插入到 Word 中生成统计图表方案如何根据数据动态生成统计图
二、方案分析 POI 硬编码 直接使用 Apache POI 硬编码生成 Word 文档虽然可行但代码复杂且难以维护因此不推荐。 FreeMarker FTL FreeMarker 可以实现文本替换和图片插入理论上符合需求。但 FTL 模板的维护较为繁琐尤其是在处理复杂表格和图片时。 POI-TL JFreeChart POI-TL 是一个基于 Apache POI 的模板引擎支持文本替换、图片插入等功能。结合 JFreeChart 生成统计图可以很好地满足需求。
三、 POI-TL JFreeChart 实现
关于JFreeChart请移步使用 JFreeChart 创建动态图表从入门到实战
3.1 Maven 依赖
首先需要在项目中引入 POI-TL 和 JFreeChart 的依赖。注意 POI 和 POI-TL 的版本需要对应否则可能会出现 NoSuchMethod 等错误。
dependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml/artifactIdversion4.1.2/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-scratchpad/artifactIdversion4.1.2/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-excelant/artifactIdversion4.1.2/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml-schemas/artifactIdversion4.1.2/version/dependencydependencygroupIdorg.jfree/groupIdartifactIdjfreechart/artifactIdversion1.5.3/version/dependencydependencygroupIdcom.deepoove/groupIdartifactIdpoi-tl/artifactIdversion1.10.0/version/dependency3.3 word模板设置
在 Word 模板中使用占位符标记需要替换的内容。对于图片需要在占位符前加 例如
替换文本时间 - ${date}插入图片${dailyOnlinePic}条件判断${?isTrue} 条件内容 ${/isTrue}
3.2 实现代码
以下是核心实现代码 private static final String TEMPLATE_PATH classpath:template/report.docx;private static final String OUTPUT_DIR D:/data/upload/analysis/;private static final String PIC_DIR OUTPUT_DIR pic/;public void getWord(String curDistCode) {try {// 获取模板文件File file ResourceUtils.getFile(TEMPLATE_PATH);// 构建模板替换的数据MapString, Object dataMap buildTemplateData(curDistCode);// 生成最终文件路径String fileName UUIDUtil.genUUID32() .docx;String filePath OUTPUT_DIR fileName;// 使用 POI-TL 渲染模板并保存try (XWPFTemplate template XWPFTemplate.compile(file, Configure.newBuilder().buildGramer(${, }).build()).render(dataMap)) {template.writeToFile(filePath);}//上传文件返回附件id} catch (Exception e) {e.printStackTrace();}}private MapString, Object buildTemplateData(String curDistCode) throws IOException {MapString, Object dataMap new HashMap();// 设置日期和在线总数dataMap.put(date, LocalDate.now());// 查询设备数据dataMap.put(onlineTotal, 100);// 生成每日在线图表DefaultCategoryDataset dailyData buildDailyDataset(stationByTime);String dailyPicFile generateChart(dailyData, 监测站总在线数, 小时, 数量, dailyOnlineTxtEnum);dataMap.put(dailyOnlinePic, Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());return dataMap;}// 构建每日在线图表的数据集private DefaultCategoryDataset buildDailyDataset(ListFireStationByTimeDTO stationByTime) {DefaultCategoryDataset dataset new DefaultCategoryDataset();stationByTime.forEach(t - dataset.addValue(t.getOnlineNum(), , t.getTime()));return dataset;}// 生成图表并保存为图片private String generateChart(DefaultCategoryDataset dataset, String title, String xAxisLabel, String yAxisLabel, DailyOnlineTxtEnum style) throws IOException {// 设置全局字体支持中文StandardChartTheme chartTheme new StandardChartTheme(CN);chartTheme.setExtraLargeFont(new Font(宋体, Font.PLAIN, 14)); // 标题字体chartTheme.setLargeFont(new Font(宋体, Font.PLAIN, 14)); // 图例字体chartTheme.setRegularFont(new Font(宋体, Font.PLAIN, 12)); // 轴标签字体ChartFactory.setChartTheme(chartTheme);// 创建图表JFreeChart chart ChartFactory.createLineChart(title, xAxisLabel, yAxisLabel, dataset);setChartStyle(chart, style);// 保存图表为图片String picFile PIC_DIR UUIDUtil.genUUID32() .png;//int numberOfCategories dataset.getColumnCount();//int width Math.max(800, numberOfCategories * 50); // 每个类别宽度为50最小宽度为800ChartUtils.saveChartAsPNG(new File(picFile), chart, 1200, 400);return picFile;}// 设置图表样式private void setChartStyle(JFreeChart chart) {CategoryPlot plot chart.getCategoryPlot();chart.setBackgroundPaint(Color.WHITE);plot.setBackgroundPaint(Color.WHITE);plot.setDomainGridlinePaint(Color.LIGHT_GRAY);plot.setRangeGridlinePaint(Color.LIGHT_GRAY);// 设置第一条折线的粗细plot.getRenderer().setSeriesStroke(0, new BasicStroke(5.0f));// 根据样式设置折线颜色plot.getRenderer().setSeriesPaint(0, Color.RED);}效果 踩坑
插入图片如何占位 与常规文本替换不同图片插入需要在占位符前加 例如 ${dailyOnlinePic}或{{pic}}统计图中文乱码 JFreeChart 默认不支持中文需要通过设置全局字体解决 // 设置全局字体支持中文StandardChartTheme chartTheme new StandardChartTheme(CN);chartTheme.setExtraLargeFont(new Font(宋体, Font.PLAIN, 14)); // 标题字体chartTheme.setLargeFont(new Font(宋体, Font.PLAIN, 14)); // 图例字体chartTheme.setRegularFont(new Font(宋体, Font.PLAIN, 12)); // 轴标签字体ChartFactory.setChartTheme(chartTheme);3.统计图横坐标… 如果生成的图片宽度不够横坐标可能会显示不全。可以通过增加图片宽度解决插入时等比例缩放
ChartUtils.saveChartAsPNG(new File(picFile), chart, 1200, 400);dataMap.put(dailyOnlinePic,
Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());或动态计算需要生成的图片宽度
int numberOfCategories dataset.getColumnCount();
int width Math.max(800, numberOfCategories * 50); // 每个类别宽度为50最小宽度为800模板条件判断 POI-TL支持复杂的条件判断例如结合逻辑运算符、||和比较运算符、!、、 等。 例如
{{?isStudent}}{{?age 18}}您是一名成年学生。{{/age 18}}
{{/isStudent}}此次实验boolean好用字符串匹配失败。