java-根据word模板灵活生成word文档-demo

文章目录

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。

  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


java-根据word模板灵活生成word文档-demo

1. 背景

编写验收材料,其中有些内容有固定规则,但是量大,如果一一手动太浪费时间了,比如。

数据库表结构,这个材料大概需要5个库,300多张表,如果手动写,工作量太大,因此通过代码编写的方式节省工作量是非常值得推荐的,效果如下:


2. 设计原理

3. demo

这里只提供如何使用word模板进行生成word文档的demo的源码。

3.1. word模板
3.2. 生成后的效果

执行:

内容:

3.3. pom
bash 复制代码
<!-- poi-tl 核心 start -->
<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>1.12.1</version>
</dependency>




<!-- Apache POI(必要,否则会报 package 不存在) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>5.1.1</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>

源码:

1、工具类

java 复制代码
package com.yzy.tool.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


public class DateFileUtil {
    private DateFileUtil() {}

    /**
     * 默认格式:yyyyMMdd_HHmmss
     */
    public static String addTimestamp(String fileName) {
        return addTimestamp(fileName, "yyyyMMdd_HHmmss");
    }
    /**
     * 添加时间戳到文件名
     * @param fileName 原始文件名
     * @param pattern 时间格式(遵循DateTimeFormatter规范)
     * @return 带时间戳的新文件名
     */
    public static String addTimestamp(String fileName, String pattern) {
        if (fileName == null || fileName.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
        // 分离文件名和扩展名
        int lastDotIndex = fileName.lastIndexOf('.');
        int lastSeparatorIndex = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));

        // 确保点号在路径分隔符之后(才是真正的扩展名)
        if (lastDotIndex > lastSeparatorIndex) {
            String name = fileName.substring(0, lastDotIndex);
            String ext = fileName.substring(lastDotIndex);
            return name + "_" + timestamp + ext;
        } else {
            return fileName + "_" + timestamp;
        }
    }
    /**
     * 生成带时间戳的日志文件名
     */
    public static String generateLogFileName(String baseName,String type) {
        return addTimestamp(baseName + ".log", "yyyyMMdd");
    }

}

vo:

java 复制代码
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class User {

    public String name;
    public String job;
    public String salary;
}
java 复制代码
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class UserNum {
    public String persion;
    public String num;
}

主体类:

java 复制代码
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.yzy.tool.util.DateFileUtil;
import com.yzy.tool.vo.User;
import com.yzy.tool.vo.UserNum;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.*;

public class WordUtils {

    public static void main(String[] args) throws Exception {

        // 数据
        Map<String, Object> data = new HashMap<>();
        List<User> userList = Lists.newArrayList();
        userList.add(map( "张三",  "开发",  "20k"));
        userList.add(map( "李四",  "测试",  "15k"));
        userList.add(map( "王五",  "运维",  "18k"));
        Map<String, Object> user = new HashMap<>();
        user.put("department","技术部");
        user.put("year", "2025");
        user.put("userList", userList);

        List<UserNum> userList1 = Lists.newArrayList();
        userList1.add(numMap( "张三",  "10"));
        userList1.add(numMap( "李四",  "23"));
        user.put("userList1", userList1);

        Map<String, Object> user1 = new HashMap<>();
        user1.put("department","运维部");
        user1.put("year", "2024");
        user1.put("userList", userList);
        List<UserNum> userList2 = Lists.newArrayList();
        userList2.add(numMap( "张三",  "3"));
        userList2.add(numMap( "李四",  "55"));
        user1.put("userList1", userList2);

        List< Map<String, Object>> list = Lists.newArrayList();
        list.add(user);
        list.add(user1);
        data.put("list", list);

        // 加载模板
        InputStream templateStream = WordUtils.class.getClassLoader()
                .getResourceAsStream("templates/example.docx");
        // 表格数据
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        // 设置字段属性()
        Configure builder = Configure.builder()
                .bind("userList", policy) // 表格集合数组
                .bind("userList1", policy) // 表格集合数组
                .bind("list", policy) // 表格集合数组
                .useSpringEL(true)
                .build();

        String detailedName = DateFileUtil.addTimestamp("output.docx", "yyyyMMdd_HHmmss_SSS");
        String join = StringUtils.join("F:\\test\\", detailedName);
        //生成文件
        XWPFTemplate.compile(templateStream, builder)
                .render(data)
                .writeToFile(join);
        System.out.println("生成成功:output.docx");
    }

    private static User map(String ... kv) {
        User build = User.builder().name(kv[0]).job(kv[1]).salary(kv[2]).build();
        return build;
    }

    private static UserNum numMap(String ... kv) {
        UserNum build = UserNum.builder().persion(kv[0]).num(kv[1]).build();
        return build;
    }
}
相关推荐
ZC跨境爬虫10 分钟前
LeetCode 88. 合并两个有序数组(双指针详解 + Java Python 实现)
java·python·算法·leetcode
caimouse14 分钟前
ReactOS 图形系统分析(17):区域填充 — EngPaint / IntEngPaint(paint.c)
c语言·开发语言·算法
北风toto21 分钟前
研发效能与后端核心技术全景指南:从CI/CD到共性组件实战
java·开发语言·ci/cd
Billy1213823 分钟前
Day12-C++20 Coroutines(上):协程原理与Promise/Awaitable机制
开发语言·c++进阶学习
01二进制代码漫游日记25 分钟前
C++基础入门速通
java·开发语言·c++
Herbert_hwt26 分钟前
第六章 Java深入理解接口、函数式接口与lambda表达式
java·开发语言·算法
API快乐传递者42 分钟前
电商竞品分析接口实战指南:从数据采集到决策洞察的全链路方案
java·python
橙橙笔记1 小时前
C++的学习第三部分
开发语言·c++·学习
程序员黑豆8 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
风流 少年9 小时前
Spring AI 2.0:Memory
java·后端·spring