每一年都奔走在自己热爱里 没有人是一座孤岛,总有谁爱着你

岁
万
月
12

使用XWPFTemplate生成Word并使用docx4j转Pdf

一、所需依赖

            <!--             引入 poi-tl,推荐 1.12.x 版本 -->
<!--            无法引入时在在终端执行以下命令,强制下载 poi-tl 的元数据到本地仓库:
                mvn dependency:get -Dartifact=com.deepoove:poi-tl:1.12.1-->
            <dependency>
                <groupId>com.deepoove</groupId>
                <artifactId>poi-tl</artifactId>
                <version>1.12.1</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.apache.logging.log4j</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.docx4j</groupId>
                <artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
                <version>8.3.15</version>
            </dependency>
<!--            mvn dependency:get -Dartifact=org.docx4j:docx4j-core:8.3.15-->

            <dependency>
                <groupId>org.docx4j</groupId>
                <artifactId>docx4j-export-fo</artifactId>
                <version>8.3.15</version>
            </dependency>

如果jdk版本过高,大于8以上,可以尝试再添加以下依赖:

                <!-- 1. JAXB API (javax 版本) -->
                <dependency>
                    <groupId>javax.xml.bind</groupId>
                    <artifactId>jaxb-api</artifactId>
                    <version>2.3.1</version>
                </dependency>

                <!-- 2. JAXB Runtime (实现,推荐使用 Glassfish) -->
                <dependency>
                    <groupId>org.glassfish.jaxb</groupId>
                    <artifactId>jaxb-runtime</artifactId>
                    <version>2.3.9</version>
                </dependency>

                <!-- 3. (可选) 激活 API -->
                <dependency>
                    <groupId>javax.activation</groupId>
                    <artifactId>activation</artifactId>
                    <version>1.1</version>
                </dependency>

二、配置模板

需要填充的数据使用{{data}}来标记,动态数量表格行可用内置的循环标签如{{?dataList}}和{{/dataList}},具体模板如下:
image
image

三、实现代码

    @Override
    public void createWord(UserDto userDto) {
        try {
            //读取文件模板
            XWPFTemplate template = XWPFTemplate.compile("E:\\file\\template\\word生成模板.docx");
            //填充数据
            template.render(dataMap());
            String timeStr = LocalDateTimeUtil.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            //输出文件
            template.writeToFile("E:\\file\\generateDocxFile\\word生成文件" + timeStr + ".docx");
            template.close();

            //转pdf,使用docx4j ,只能处理docx文件
            // 1. 加载Word文档
            WordprocessingMLPackage wordMLPackage =
                    WordprocessingMLPackage.load(new File("E:\\file\\generateDocxFile\\word生成文件" + timeStr + ".docx"));
            //配置字体映射
            Mapper mapper = new IdentityPlusMapper();
            PhysicalFonts.discoverPhysicalFonts();
            //没有映射的字体将会变成"##"
            String[][] fontMap = {
                    {"宋体", "SimSun"},
                    {"黑体", "SimHei"},
                    {"微软雅黑", "Microsoft YaHei"},
                    {"楷体", "KaiTi"},
                    {"隶书", "LiSu"},
                    {"幼圆", "YouYuan"},
                    {"华文细黑", "STXihei"},
                    {"华文楷体", "STKaiti"},
                    {"华文宋体", "STSong"},
                    {"华文仿宋", "STFangsong"},
                    {"华文中宋", "STZhongsong"},
                    {"华文彩云", "STCaiyun"},
                    {"华文琥珀", "STHupo"},
                    {"华文新魏", "STXinwei"},
                    {"华文隶书", "STLiti"},
                    {"华文行楷", "STXingkai"},
                    {"方正舒体", "FZShuTi"},
                    {"方正姚体", "FZYaoti"},
                    {"仿宋_GB2312", "FangSong_GB2312"},
                    {"楷体_GB2312", "KaiTi_GB2312"},
                    {"宋体_GB2312", "SimSun_GB2312"},
                    {"新宋体", "NSimSun"},
                    {"仿宋", "FangSong"},
            };
            for (String[] font : fontMap) {
                PhysicalFont physicalFont = PhysicalFonts.get(font[1]);
                if (physicalFont != null) {
                    mapper.put(font[0], physicalFont);
                }
            }
            wordMLPackage.setFontMapper(mapper);
            // 2. 执行转换,将PDF输出到文件流
            try (FileOutputStream fos = new FileOutputStream("E:\\file\\generatePDFFile\\word生成文件" + timeStr + ".pdf")) {
                Docx4J.toPDF(wordMLPackage, fos);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Map dataMap() {
        Map map = new HashMap<>();
        map.put("userName", "张三");
        map.put("age", 20);
        map.put("sex", "男");
        map.put("address", "北京市海淀区");
        map.put("phone", "12345678901");
        map.put("email", "zhangsan@example.com");

        //表格数据
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("workTime", "2024-01-01——2025-01-01");
        map1.put("companyName", "字节跳动");
        map1.put("post", "Java开发工程师");

        Map<String, Object> map2 = new HashMap<>();
        map2.put("workTime", "2025-01-01——2026-01-01");
        map2.put("companyName", "腾讯");
        map2.put("post", "项目经理");

        list.add(map1);
        list.add(map2);

        map.put("workList", list);
        return map;
    }
	
posted @ 2026-04-08 10:15  果咩那塞  阅读(8)  评论(0)    收藏  举报