springboot整合freemaker实现复杂动态word生成

springboot整合freemaker实现复杂动态word生成
1.引入maven依赖
 		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
2.application.yml添加配置
spring:
  freemarker:
    allow-request-override: false
    cache: false
    check-template-location: false
    charset: UTF-8
    content-type: text/html; charset=utf-8
    expose-spring-macro-helpers: false
    suffix: .ftl
3.初始doc模板另存为xml文件,注意变量分离问题

示例doc模板:

姓名编码密码电话
${user}${code}${password}${phone}

调整前:

 							<w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="4B82BCE8" w14:textId="7FB604DC" w:rsidR="00352125"
                                     w:rsidRDefault="005125BF">
                                    <w:pPr>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                    </w:pPr>
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>$</w:t>
                                    </w:r>
                                    <w:r>
                                        <w:t>{user}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>

调整后:

 							<w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="4B82BCE8" w14:textId="7FB604DC" w:rsidR="00352125"
                                     w:rsidRDefault="005125BF">
                                    <w:pPr>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                    </w:pPr>
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>${user}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
4.xml文件重命名为ftl文件,resource下创建template文件夹,ftl文件放入文件夹下

完整ftl:

                <w:body>
                    <w:p w14:paraId="5E326395" w14:textId="3914992A" w:rsidR="00411E60" w:rsidRDefault="00535F4C">
                        <w:pPr>
                            <w:pStyle w:val="4"/>
                        </w:pPr>

                            <w:r w:rsidRPr="008D36EA">
                                <w:rPr>
                                    <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋"/>
                                    <w:sz w:val="28"/>
                                    <w:szCs w:val="28"/>
                                </w:rPr>
                                <w:t>其中</w:t>
                            </w:r>
                            <#list areaList as area>
                            <w:r>
                                <w:rPr>
                                    <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" w:hint="eastAsia"/>
                                    <w:sz w:val="28"/>
                                    <w:szCs w:val="28"/>
                                </w:rPr>
                                <w:t></w:t>
                                <w:t>${area.district}</w:t>
                                <w:t>${area.num}</w:t>
                                <w:t>家占比达到</w:t>
                                <w:t>${area.percent}</w:t>
                            </w:r>
                        </#list>
                        <w:r w:rsidRPr="008D36EA">
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋"/>
                                <w:sz w:val="28"/>
                                <w:szCs w:val="28"/>
                            </w:rPr>
                            <w:t></w:t>
                        </w:r>
                    </w:p>

                    <#list userListAll as userMap>
                        <w:p w14:paraId="5E326395" w14:textId="3914992A" w:rsidR="00411E60" w:rsidRDefault="00535F4C">
                            <w:pPr>
                                <w:pStyle w:val="4"/>
                            </w:pPr>
                            <w:r>
                                <w:t>2.1.1.1.</w:t>
                                <w:t>${userMap_index+1}</w:t>
                                <w:t>${userMap.name}</w:t>
                            </w:r>
                        </w:p>
                    <w:tbl>
                        <w:tblPr>
                            <w:tblStyle w:val="a3"/>
                            <w:tblW w:w="0" w:type="auto"/>
                            <w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0"
                                       w:noHBand="0" w:noVBand="1"/>
                        </w:tblPr>
                        <w:tblGrid>
                            <w:gridCol w:w="2074"/>
                            <w:gridCol w:w="2074"/>
                            <w:gridCol w:w="2074"/>
                            <w:gridCol w:w="2074"/>
                        </w:tblGrid>
                        <w:tr w:rsidR="00352125" w14:paraId="3EAB44FF" w14:textId="77777777" w:rsidTr="00352125">
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="7055CD47" w14:textId="076D8891" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>姓名</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="26B106D2" w14:textId="101CCF30" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>编码</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="705F7197" w14:textId="3C4513DE" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>密码</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="18959CC1" w14:textId="411804AA" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>电话</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                        </w:tr>
                        <#list userMap.value as user>
                        <w:tr w:rsidR="00352125" w14:paraId="01EED409" w14:textId="77777777" w:rsidTr="00352125">
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="4B82BCE8" w14:textId="1C7883DA" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>${user.name}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="7195FB0D" w14:textId="1C3BF44D" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>${user.code}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="21CD1BB5" w14:textId="36069722" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>${user.pwd}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="54ACBD81" w14:textId="3B4D6346" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>${user.phone}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                        </w:tr>
                        </#list>
                    </w:tbl>
                    </#list>
                    <w:p w14:paraId="6C395266" w14:textId="77777777" w:rsidR="001B2CFA" w:rsidRDefault="001B2CFA"/>
                    <w:sectPr w:rsidR="001B2CFA">
                        <w:pgSz w:w="11906" w:h="16838"/>
                        <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992"
                                 w:gutter="0"/>
                        <w:cols w:space="425"/>
                        <w:docGrid w:type="lines" w:linePitch="312"/>
                    </w:sectPr>
                </w:body>

段落循环:

 						<#list areaList as area>
                            <w:r>
                               	...
                                <w:t></w:t>
                                <w:t>${area.district}</w:t>
                                <w:t>${area.num}</w:t>
                                <w:t>家占比达到</w:t>
                                <w:t>${area.percent}</w:t>
                            </w:r>
                        </#list>

表格循环:

  					<#list userListAll as userMap>
                        <w:p w14:paraId="5E326395" w14:textId="3914992A" w:rsidR="00411E60" w:rsidRDefault="00535F4C">
                            <w:pPr>
                                <w:pStyle w:val="4"/>
                            </w:pPr>
                            <w:r>
                                <w:t>2.1.1.1.</w:t>
                                <w:t>${userMap_index+1}</w:t>
                                <w:t>${userMap.name}</w:t>
                            </w:r>
                        </w:p>
                    <w:tbl>
                      ...
                    </w:tbl>
                    </#list>

行循环:

 						<#list userMap.value as user>
                        <w:tr w:rsidR="00352125" w14:paraId="01EED409" w14:textId="77777777" w:rsidTr="00352125">
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="2074" w:type="dxa"/>
                                </w:tcPr>
                                <w:p w14:paraId="4B82BCE8" w14:textId="1C7883DA" w:rsidR="00352125"
                                     w:rsidRDefault="00352125">
                                    <w:r>
                                        <w:rPr>
                                            <w:rFonts w:hint="eastAsia"/>
                                        </w:rPr>
                                        <w:t>${user.name}</w:t>
                                    </w:r>
                                </w:p>
                            </w:tc>
                          	....
                        </w:tr>
                        </#list>
5.controller测试
   /**
     * doc文档导出测试
     * @return
     * @throws IOException
     */
    @PostMapping("/docTest")
    @ResponseBody
    @ApiOperation(value="导出doc", httpMethod = "POST",produces="application/json",notes = "导出doc测试")
    public boolean exportDocTest() throws IOException {
        List areaList = new ArrayList();
        Map<String, Object> areaMap1 = new HashMap<>();
        areaMap1.put("district","昆山");
        areaMap1.put("num",4578);
        areaMap1.put("percent","24.56%");
        Map<String, Object> areaMap2 = new HashMap<>();
        areaMap2.put("district","吴江");
        areaMap2.put("num",3521);
        areaMap2.put("percent","20.12%");
        areaList.add(areaMap1);
        areaList.add(areaMap2);

        List userList1 = new ArrayList();
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("name","wuzhigang");
        dataMap.put("code","861225");
        dataMap.put("pwd","root");
        dataMap.put("phone","138********");
        userList1.add(dataMap);
        Map<String, Object> dataMap1 = new HashMap<>();
        dataMap1.put("name","wuzhigang");
        dataMap1.put("code","870124");
        dataMap1.put("pwd","root");
        dataMap1.put("phone","180********");
        userList1.add(dataMap1);

        List userList2 = new ArrayList();
        Map<String, Object> dataMap2 = new HashMap<>();
        dataMap2.put("name","Alex");
        dataMap2.put("code","861225");
        dataMap2.put("pwd","root");
        dataMap2.put("phone","138********");
        userList2.add(dataMap2);
        Map<String, Object> dataMap3 = new HashMap<>();
        dataMap3.put("name","Alex");
        dataMap3.put("code","870124");
        dataMap3.put("pwd","root");
        dataMap3.put("phone","180********");
        userList2.add(dataMap3);

        Map<String, Object> userMap1 = new HashMap<>();
        userMap1.put("name","user1");
        userMap1.put("value",userList1);

        Map<String, Object> userMap2 = new HashMap<>();
        userMap2.put("name","user2");
        userMap2.put("value",userList2);

        List userListAll = new ArrayList();
        userListAll.add(userMap1);
        userListAll.add(userMap2);
        Map<String, Object> map = new HashMap<>();
        map.put("areaList",areaList);
        map.put("userListAll",userListAll);
        String templateName = "freemarkerTest2.ftl";
        String targetPath = "/data/freemarkerTest2.doc";
        boolean result = ExportDoc.EconomicReportExport(map,templateName,targetPath);
        return result;
    }

ExportDoc代码:

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.util.Map;

/**
 * @description: word文档导出测试
 * @author: wzg
 * @create: 2021-12-7
 **/
public class ExportDoc {

    /**
     * word导出
     * @param dataMap 数据
     * @param templateName 模板名
     * @param targetPath 导出地址
     * @return
     */
    public static boolean EconomicReportExport(Map dataMap, String templateName, String targetPath) throws IOException {
        Boolean result = true;
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(configuration.getClass(),"/template");
        Writer out = null;
        try {
            Template template = configuration.getTemplate(templateName);
            File outFile = new File(targetPath);
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
            template.process(dataMap,out);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }finally {
            out.close();
        }
        return result;
    }
}
6.doc文件效果

其中,昆山4,578家占比达到24.56%,吴江3,521家占比达到20.12%。

2.1.1.1.1user1

姓名编码密码电话
wuzhigang861225root138********
wuzhigang870124root180********

2.1.1.1.2user2

姓名编码密码电话
Alex861225root138********
Alex870124root180********
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值