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;
    }
}
相关推荐
DianSan_ERP8 分钟前
多平台订单自动下载与回传的技术实现:从消息推送到状态闭环引言
java·linux·服务器·前端·网络·架构·自动化
Joe_Wang59 分钟前
【从0到1学习JVM · 13】点进JDK源码只有一个分号?搞懂本地方法栈与JNI机制
java·jvm·学习·本地方法栈
编码者卢布16 分钟前
【App Service 】WebJobs 多实例实验:谁在运行,什么时候运行?
开发语言·python
kaixin_learn_qt_ing19 分钟前
Qt抽屉窗体实现demo
开发语言·qt
quantdash_cc24 分钟前
Python 获取实时行情后如何进行批量筛选?从全市场快照到策略候选池
开发语言·python·数据分析·量化交易·股票数据·quantdash
AI 算法大模型备案~当当29 分钟前
各地备案数量怎么看:一份属地公告的认读与台账方法
java·数据库·人工智能
论文复现现场34 分钟前
论文复现看到“RTX 3090 or higher”:显存、CUDA、batch size 与 OOM 怎么判断?
开发语言·pytorch·batch·cuda·rtx3090
智鸟科技GemeOpen开发者智能设备36 分钟前
GemeOpen 智能音箱 GSSM0B - 播放控制(Java示例)
java·开发语言·智能音箱
今天的砖头有点烫手啊1 小时前
Java IO/NIO/AIO 演进:从 BIO 到 Netty 的底层逻辑
java·jvm·nio
m0_380743871 小时前
PHP 8.3 接口返回数据为空怎么排查
开发语言·php