poi-tl word模版生成、动态表格、坑点合集

一、配置

1、导入依赖

java 复制代码
  <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.10.0</version>
   </dependency>

apache poi版本要对应

java 复制代码
 <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
</dependency>
<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
</dependency>

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
</dependency>

2、模版存放问题

(1)如果你的模版存放在你c盘之类的,是不用再去配置maven文件

(2)如果你的是要发布到inux的spring项目,或者为了可用性,将模版存放在resource文件夹下面,这个时候就要配置maven文件,因为打jar包的时候,会将你的word文件默认压缩,通过maven构建文件不对后缀docx的文件压缩过滤,这样文件打包之后就不会损坏

java 复制代码
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <version>2.6</version>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>docx</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>

        </plugins> 
    </build> 

二、案例

1、普通模版

新建一个word文档,{{}}这种格式,里面放替换的字母,将map集合替换内容设置好,交给poi-tl渲染。

word模版

以下就是普通模版生成的三个方法,其中一个为主方法,调用生成。如果需要字节流转成mutipartfile需要导入mock依赖

java 复制代码
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-mock</artifactId>
            <version>2.0.8</version>
        </dependency>
java 复制代码
public class WordTemplateUtils {  


    public static void main(String[] args) {
        Map<String, Object> templateMap = new HashMap<>();
        templateMap.put("Year", "2023年");
        templateMap.put("HqCompany","测试名单");
        exportWord(templateMap);
    }


/**
     * 生成word模版
     *
     * @param data
     * @return
     */
    public static MultipartFile exportWord(Map<String, Object> data) {
        MultipartFile multipartFile = null;
        ByteArrayOutputStream ostream = null;
        XWPFTemplate template = null;
        try {
            //获取模板
            template = getWordTemplate(data);
            ostream = new ByteArrayOutputStream();
            // 将模板输出到字节流
            template.write(ostream);//这里还有一个方法是template.writeToFile("");可以直接填写本地文件路径
            byte[] fileBytes = ostream.toByteArray();
            String newFileName = "测试" + data.get("Year") + "年生成文件.docx";
            //转成可上传的文件(作者这里是为了上传到服务器转换成mutipartFile)
            multipartFile = new MockMultipartFile(newFileName, newFileName,
                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileBytes);
        } catch (IOException e) {
            log.error("模版1导出异常");
        } finally {
            //关闭流
            IOUtils.close(ostream);
            IOUtils.close(template);
        }
        return multipartFile;
    }

    /**
     * 获取普通word模版渲染
     *
     * @param data
     * @return
     * @throws IOException
     */
    private static XWPFTemplate getWordTemplate(Map<String, Object> data) {
        //获取模板的输入流,读取resource里面的template文件夹里的word1.docx
        ClassPathResource tempFileResource = new ClassPathResource("template/" + "word1.docx");
        InputStream stream = null;
        try {
            stream = tempFileResource.getInputStream();
        } catch (IOException e) {
            log.error("获取模版失败!");
        }
        ConfigureBuilder builder = Configure.builder();
        builder.useSpringEL();
        XWPFTemplate template = XWPFTemplate.compile(stream, builder.build()).render(data);
        return template;
    }

}

2、带有表格的模版

word模版

代码:

java 复制代码
  public class WordTemplateUtils {
  /**
     * 生成word表格模版
     *
     * @param data
     * @return
     */
    public static MultipartFile exportWordTable(Map<String, Object> data) {
        //模板地址
        ClassPathResource tempFileResource = new ClassPathResource("template/" + "word2.docx");
        // 行循环实例
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        //这里可以指定一个config类,用来指定一些规则,也可以改变模板中{{}}的这种格式
        MultipartFile multipartFile = null;
        XWPFTemplate compile = null;
        File file = null;
        ByteArrayOutputStream ostream = null;
        try {
            //lists绑定对象
            Configure config = Configure.builder()
                    .bind("lists", policy).build();
            compile = XWPFTemplate.compile(tempFileResource.getInputStream(), config);
            compile.render(data);
            ostream = new ByteArrayOutputStream();
            compile.write(ostream);
            byte[] fileBytes = ostream.toByteArray();
            String newFileName = "测试" + data.get("Year") + "年企业名单.docx";
            multipartFile = new MockMultipartFile(newFileName, newFileName,
                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileBytes);
        } catch (IOException e) {
            log.error("模版导出失败");
        } finally {
            IOUtils.close(ostream);
            IOUtils.close(compile);
        }
        return multipartFile;
    }


    public static void main(String[] args) {
        Map<String, Object> templateMap = new HashMap<>();
        //建立公司对象集合
        List<Company> companyList=new ArrayList();
        Company company1=new Company();
        company1.setIndex(1);
        company1.setEnterpriseName("测试1");
        Company company2=new Company();
        company1.setIndex(2);
        company1.setEnterpriseName("测试2");
        companyList.add(company1);
        //放进模版集合
        templateMap.put("Year", "2023年");
        templateMap.put("lists","测试名单");
        exportWordTable(templateMap);
    }

}
相关推荐
FQNmxDG4S8 小时前
Java多线程编程:Thread与Runnable的并发控制
java·开发语言
虹科网络安全9 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje9 小时前
Java语法进阶
java·开发语言·jvm
rKWP8gKv79 小时前
Java微服务性能监控:Prometheus与Grafana集成方案
java·微服务·prometheus
老前端的功夫9 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287929 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
小江的记录本9 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
yaoxin52112310 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python
极客先躯12 小时前
高级java每日一道面试题-2025年11月24日-容器与虚拟化题[Dockerj]-runc 的作用是什么?
java·oci 的命令行工具·最小可用·无守护进程·完全标准·创建容器的核心流程·runc 核心职责思维导图
用户606487671889612 小时前
AI 抢不走的技能:用 Claude API 构建自动化工作流实战
java