Java使用POI-TL和JFreeChart动态生成Word报告

2025-02-10 04:50

本文主要是介绍Java使用POI-TL和JFreeChart动态生成Word报告,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码...

前言

在开发过程中,我们经常需要生成包含动态数据和图表的 Word 报告。本文将介绍如何结合 POI-TL 和 JFreeChart,实现动态生成 Word 报告的功能,并分享一些实际开发中的踩坑经验
word生成方案:

  • freemarker+ftl
  • pot-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请移步Java使用JFreeChart创建动态图表的代码示例_java_China编程(www.chinasem.cn)

3.1 Maven 依赖

首先,需要在项目中引入 POI-TL 和 JFreeChart 的依赖。注意 POI 和 POI-TL 的版本需要对应,否则可能会出现 NoSuchMethod 等错误。

<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooXML</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-scratchpad</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    &ljst;artifactId>poi-excelant</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooxml-schemas</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.jfree</groupId>
			<artifactId>jfreechart</artifactId>
			<version>1.5.3</version>
		</dependency>
		<dependency>
			<groupId>com.deepoove</groupId>
			<artifactId>poi-tl</artifactId>
			<version>1.10.0</version>
		</dependency>

3.2 word模板设置

在 Word 模板中,使用占位符标记需要替换的内容。对于图片,需要在占位符前加 @,例如:

  • 替换文本:时间 -> ${date}
  • 插入图片:${@dailyOnlinePic}

3.3 实现代码

以下是核心实现代码:

    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);

            // 构建模板替换的数据
            Map<String, Object> dataMap = buildTemplateData(curDistCode);

            // 生成最终文件路径
            String fileName = UUIDUtil.genUUID32() + ".docx";
            String filePath = OUTPUT_DIR + fileName;

            // 使用 POI-TL 渲染模板并保存
            try (XwpFTemplate template = XWPFTemplate.compile(file, Conwww.chinasem.cnfigure.newBuilder().buildGramer("${", "}").build())
                    .render(dataMap)) {
                template.writeToFile(filePath);
            }
            //上传文件返回附件id
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Map<String, Object> buildTemplateData(String curDistCode) throws IOException {
        Map<String, 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(List<FireStationByTimeDTO> 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,最小宽度为800
        ChartUtils.saveChartASPNG(new File(picFile), cpythonhart, 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);
    }

效果

Java使用POI-TL和JFreeChart动态生成Word报告

踩坑

  • 插入图片如何占位
    与常规文本替换不同,图片插入需要在占位符前加 @,例如 ${@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);
  • 统计图横坐标…
    如果生成的图片宽度不够,横坐标可能会显示不全。可以通过增加图片宽度解决,插入时等比例缩放:
ChartUtils.saveChartAsPNG(new File(picFile), chart, 1200, 400);
dataMap.put("dailyOnlinePic", 
Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JjavascriptPEG).size(600, 200).create());

或动态计算需要生成的图片宽度:

int numberOfCategories = dataset.getColumnCount();
int width = Math.max(800, numberOfCategories * 50); // 每个类别宽编程度为50,最小宽度为800

到此这篇关于Java使用POI-TL和JFreeChart动态生成Word报告的文章就介绍到这了,更多相关Java POI-TL JFreeChart生成Word报告t内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于Java使用POI-TL和JFreeChart动态生成Word报告的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153371

相关文章

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

使用Python和Pyecharts创建交互式地图

《使用Python和Pyecharts创建交互式地图》在数据可视化领域,创建交互式地图是一种强大的方式,可以使受众能够以引人入胜且信息丰富的方式探索地理数据,下面我们看看如何使用Python和Pyec... 目录简介Pyecharts 简介创建上海地图代码说明运行结果总结简介在数据可视化领域,创建交互式地

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD