JAVA使用Apache POI动态导出Word文档

news2024/12/28 3:15:01

文章目录

  • 一、文章背景
  • 二、实现步骤
    • 2.1 需要的依赖
    • 2.2 创建模板
    • 2.3 书写java类
      • 2.3.1 模板目录
      • 2.3.2 Controller类
      • 2.3.2 工具类
    • 2.4 测试
      • 2.4.1 浏览器请求接口
      • 2.4.2 下载word
  • 三、注意事项
  • 四、其他导出word实现方式

一、文章背景

  1. 基于Freemarker模版动态生成并导出word文档存在弊端,生成的word文档格式是xml类型(通过生成word文档然后点击另存为可以查看是xml类型);但我们当前的需求是对生成的word文档提供预览功能,在公司提供的接口中,如果word格式不是doc格式就不能正确展示数据;同时对于频繁修改模板,Freemarker不好维护等问题;于是就有了此篇文章。
  2. 调研市面上java导出word文档主流的方案以及弊端(借鉴以下文章):https://zhuanlan.zhihu.com/p/672525861
    在这里插入图片描述

二、实现步骤

2.1 需要的依赖

<dependency>
     <groupId>cn.afterturn</groupId>
     <artifactId>easypoi-base</artifactId>
     <version>4.4.0</version>
 </dependency>
 <dependency>
     <groupId>cn.afterturn</groupId>
     <artifactId>easypoi-web</artifactId>
     <version>4.4.0</version>
 </dependency>
 <dependency>
     <groupId>cn.afterturn</groupId>
     <artifactId>easypoi-annotation</artifactId>
     <version>4.4.0</version>
 </dependency>
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi</artifactId>
     <version>4.1.1</version>
 </dependency>
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>4.1.1</version>
 </dependency>

2.2 创建模板

请添加图片描述

2.3 书写java类

2.3.1 模板目录

在这里插入图片描述

2.3.2 Controller类

/**
 * @author henry
 * @version 1.0
 * @describe todo
 * @data 2024/5/10 09:44
 */
@Api("测试poi导出word")
@RestController
@RequestMapping("/poiExport")
@Slf4j
public class Controller {

    @ApiOperation("word模板下载")
    @GetMapping("/poiExport")
    public void exportWordByModel(HttpServletResponse response, String path){
        Map<String,Object> map = new HashMap<>();
        map.put("startTime","2023");
        map.put("endTime","2024");
        map.put("name","tom");
        map.put("age","23");
        map.put("sex","男");

        List<String> list = new ArrayList<>();
        list.add("2019就读A学校");
        list.add("2022就读B学校");
        list.add("2023上岸研究生");
        map.put("list",list);

        ImageEntity imageEntity = new ImageEntity();
        imageEntity.setUrl(FileUtil.filePath("templates/cute.png").getPath());
        imageEntity.setWidth(80);
        imageEntity.setHeight(100);
        map.put("photo",imageEntity);

        FileUtil.exportWordByModel(response,map,"templates/word.docx","员工统计");
    }
}

2.3.2 工具类

/**
 * @author henry
 * @version 1.0
 * @describe todo
 * @data 2024/5/10 09:48
 */
public class FileUtil {
    /**
     * 根据模板导出Word
     * @param response
     * @param map
     * @param modelFileName
     * @param outFileName
     */
    public static void exportWordByModel(HttpServletResponse response, Map<String, Object> map, String modelFileName, String outFileName) {
        try {
            // 1.获取模板文件路径 - 重点
            //XWPFDocument word = WordExportUtil.exportWord07(modelFileName, map);有时候这种方式可以找到有时候找不到(不太清楚)
            String templatePath = filePath(modelFileName).getAbsolutePath();

            // 打印出模板文件的完整路径 - 校验路径是否存在
            File templateFile = new File(templatePath);
            if (templateFile.exists()) {
                System.out.println("模板文件存在: " + templateFile.getAbsolutePath());
            } else {
                System.out.println("模板文件不存在: " + templateFile.getAbsolutePath());
            }
            // 2.映射模板,替换数据
            XWPFDocument word = WordExportUtil.exportWord07(templatePath, map);
            // 3.设置返回参数的字符集
            response.reset();
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setContentType("application/msexcel");
            response.setContentType("text/html; charset=UTF-8");
            // 4.设置响应类型为Word文档
            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            // 5.中文文件名处理,否则报错
            String encodedFileName = URLEncoder.encode(outFileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".docx");
            // 6.将Word文档发送到浏览器
            word.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据文件名获取文件对象
     * @param modelFileName
     * @return
     */
    public static File filePath(String modelFileName) {
        // 获取类加载器
        ClassLoader classLoader = FileUtil.class.getClassLoader();
        // 尝试从类路径中加载资源
        URL resource = classLoader.getResource(modelFileName);
        return new File(resource.getFile());
    }
}

2.4 测试

2.4.1 浏览器请求接口

在这里插入图片描述

2.4.2 下载word

在这里插入图片描述

三、注意事项

1、模板文件读取不到(容易出现错误-需及时更换文件读取方式)
2、list循环借鉴文章
https://blog.csdn.net/andy_67/article/details/124906812

四、其他导出word实现方式

JAVA利用Freemarker模版动态生成并导出word文档

借鉴文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1662042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

西米支付:数字藏品元宇宙的介绍与骗局套路解析

一、什么是元宇宙&#xff1f; 元宇宙是一个集体虚拟共享空间&#xff0c;由虚拟增强的物理现实和物理持久的虚拟空间融合而创造&#xff0c;包括所有虚拟世界、增强现实和互联网的总和。简单地说&#xff0c;元宇宙是Web3.0时期的数字世界。 这类新兴概念被非法分子包装后&am…

JVM基础之垃圾回收

垃圾回收 1. Base 内存泄漏&#xff1a;不再使用的对象在系统中未被回收 内存溢出&#xff1a;内存泄漏的积累 手动触发垃圾回收&#xff1a;System.gc(),该方法不一定会立即回收垃圾&#xff0c;仅仅是向JVM发送一个垃圾回收请求&#xff0c;具体是否需要垃圾回收由JVM自行…

【树莓派4B】如何用树莓派的串口发送数据给单片机

文章目录 查看路由器中的树莓派IProot连接打开vnc远程桌面服务打开win的远程桌面软件输入IP和端口串口发送数据硬件连接树莓派发送 查看路由器中的树莓派IP root连接 打开vnc远程桌面服务 vncserver :1打开win的远程桌面软件 输入IP和端口 192.168.3.33:1输入密码qwer1234后点…

draw.io-24-windows-no-installer.exe是一个自解压文件

draw.io-24-windows-no-installer.exe是一个自解压文件&#xff0c;每次启动都会执行解压操作&#xff0c;在以下两个位置产生程序主体文件draw.io.exe&#xff0c;大约170M&#xff0c;程序关闭后再删除解压后的文件&#xff0c;给硬盘增加不必要的读写操作。 C:\Users\AAA\Ap…

工作中使用Optional过滤出符合条件的数据

工作中使用Optional获取非空对象的属性 实体类Optional对非空对象的处理满足过滤条件返回的值不满足条件返回的值 实体类 package po;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.io.Serializable;Data AllArgsConst…

从零开始写 Docker(十四)---重构:实现容器间 rootfs 隔离

本文为从零开始写 Docker 系列第十四篇&#xff0c;实现容器间的 rootfs 隔离&#xff0c;使得多个容器间互不影响。 完整代码见&#xff1a;https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识&#xff1a; 核心原理&#xff1a;…

数据库基础语法二

一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo mysql -uroot -p #登陆数据库 create database zoo; #创建数据库zoo alter database zoo character set gbk collate gbk_…

ArrayList的深拷贝与浅拷贝

1、深拷贝 通过以下代码进行理解 import java.util.ArrayList; import java.util.List;public class Demo {public static void main(String[] args) {List<Integer> c new ArrayList<>();c.add(1);c.add(2);c.add(3);List<Integer> c1 new ArrayList<…

理解Go语言中的测试种类

测试金字塔将测试分为不同的类别,如下图所示 单元测试在金字塔的底部。大部分测试都是单元测试,它们编写成本代、执行速度快且执行结果高度确定。通常,越往金子塔的上层走,测试变得越复杂,运行速度越慢,并且越难保证执行结果的确定性。 一个常见的技巧是明确说明要运行哪…

xhci 寄存器学习

xhci 寄存器介绍 查看linux 代码&#xff1a; 1733 /* There is one xhci_hcd structure per controller */ 1734 struct xhci_hcd { 1735 struct usb_hcd *main_hcd; 1736 struct usb_hcd *shared_hcd; 1737 /* glue to PCI and HCD framework */ 1738 stru…

爱喵喵宠物网站系统asp.netmvc

c#asp.net mvc爱喵喵宠物网站系统asp.netmvc 说明文档 运行前附加数据库.mdf&#xff08;或sql生成数据库&#xff09; 主要技术&#xff1a; 基于asp.net mvc架构和sql server数据库 功能模块&#xff1a; 首页 预约 猫生活 猫科普 参馆 个人中心 管理员后台可以对猫猫和猫…

闲聊大模型

人工智能&#xff0c;机器学习&#xff0c;神经网络&#xff0c;深度学习&#xff0c;大模型 https://www.ibm.com/cn-zh/topics/machine-learning https://www.ibm.com/cloud/blog/ai-vs-machine-learning-vs-deep-learning-vs-neural-networks ChatGPT https://openai.com/…

使用Pycharm编写Python程序时对基本类结构中方法的重写的两种初步操作方式

使用Pycharm编写Python程序时对基本类结构中方法的重写的两种初步操作方式 Python和其他一些高级面向对象的编程语言中&#xff0c;子类可继承父类中的方法&#xff0c;而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法&#xff0c;而是想作一定的修改&…

02.文件IO

文件描述符 表述打开的文件的 它是open函数的返回值&#xff0c;一个进程启动之后&#xff0c;会默认打开3个文件标识符 0标准输入&#xff0c;1标准输出&#xff0c;2标准错误 新的打开的文件返回文件描述符表中未使用过的最小的文件描述符 open函数 用来打开或者新建一个文件…

Nvidia V100 GPU 运行 InternVL 1.5-8bit

InternVL 运行 InternVL 1.5-8bit教程 InternVL 官网仓库及教程 1. 设置最小环境 conda create --name internvl python3.10 -y conda activate internvl conda install pytorch2.2.2 torchvision pytorch-cuda11.8 -c pytorch -c nvidia -y pip install transf…

2010年认证杯SPSSPRO杯数学建模D题(第一阶段)服务网点的分布全过程文档及程序

2010年认证杯SPSSPRO杯数学建模 D题 服务网点的分布 原题再现&#xff1a; 服务网点、通讯基站的设置&#xff0c;都存在如何设置较少的站点&#xff0c;获得较大效益的问题。通讯基站的覆盖范围一般是圆形的&#xff0c;而消防、快餐、快递服务则受到道路情况和到达时间的限…

ITIL4之打造高效IT运维的“金三角”

在这个数字化时代&#xff0c;每一秒的停顿都可能意味着巨大的经济损失&#xff0c;因此&#xff0c;高效且可靠的IT运维管理成为了企业稳健前行的基石。我们就以小白友好的方式&#xff0c;深入浅出地探讨ITIL4理论框架下的三个关键实践——容量和性能管理、可用性管理、以及度…

Java代理Ⅱ

目录 静态代理的内存结构图 测试demo 内存图 关于为什么不能直接修改原方法&#xff0c;而是要用代理 参考文章 关于代理我之前写过一篇博客&#xff0c;基本已经讲的差不多了&#xff0c;有兴趣的读者可以去看看 Java代理 最近有了新的感悟&#xff0c;所以记录一下 静…

线路和绕组中的波过程(一)

本篇为本科课程《高电压工程基础》的笔记。 本篇为这一单元的第一篇笔记。下一篇传送门。 当电路中的设备&#xff08;元件&#xff09;最大实际尺寸l大于人们所感兴趣的谐波波长 λ \lambda λ时&#xff0c;可以作为集中参数处理&#xff0c;否则就要当做分布参数处理。即&…

一键开启,盲盒小程序里的梦幻奇遇

在这个充满惊喜与未知的数字时代&#xff0c;盲盒小程序以其独特的魅力成为了许多人的新宠。只需一键开启&#xff0c;你就能踏入一个充满梦幻奇遇的世界&#xff0c;探索未知的惊喜与乐趣。 盲盒小程序不仅仅是一个简单的购物平台&#xff0c;它更是一个充满神秘与惊喜的宝藏库…