利用freemarker 在模板里面写入动态数据,动态表格,图片插入并生成word文档

本文介绍如何使用Freemarker在模板中动态插入数据、创建表格,并结合图片,最终生成Word文档。测试代码和模板示例分别展示了数据的插入方式以及模板的结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用freemarker 在模板里面写入动态数据,动态表格,图片插入。
以下测试代码图片(image.jpg)和模板(template.xml)是直接放到src目录下面的,可以根据自己需求调整
废话不多说,直接上代码:

代码块


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import sun.misc.BASE64Encoder;
import freemarker.template.Configuration;
import freemarker.template.Template;


public class CreateWordTest {
   
   

    public static void main(String args[]){
        CreateWordTest t=new CreateWordTest();
        t.write();
    }

    public void write() {
        try {
            //创建配置实例            
            Configuration configuration = new Configuration();        
            //设置编码
            configuration.setDefaultEncoding("UTF-8");        
            //ftl模板文件统一放至/包下面
            configuration.setClassForTemplateLoading(CreateWordTest.class,"/");
            // 获取模板
            Template template=configuration.getTemplate("template.xml");
            String path0 = "D:/test/";
            File f = new File(path0);
            // 创建文件夹
            if (!f.exists()) {
                f.mkdirs();
            }
            //输出文件
            File outFile = new File(path0+"test4.doc");                            
            //将模板和数据模型合并生成文件 
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
            template.process(getRootWord("1"), out);
            out.flush();
            System.out.println("写入成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据
     * @param flag
     * @return
     * @throws Exception
     */
    public Map<String ,Object> getRootWord(String flag) throws Exception{
        Map<String, Object> root= new HashMap<String, Object>();
        List<Map<String,Object>> proList= getProList();
        root.clear();
        root.put("customer", "张三");// key值与模板的${customer}对应
        root.put("papers_num", "452621552");
        root.put("yesterday", "20180319");
        root.put("create_date","20180320");
        root.put("jingzhi_unit","(元)");
        root.put("zichan_unit","(元)");
        root.put("proList",proList);//与模板${proList}对应,由于是列表,模板需要循环生成行,故用标签<#list proList as infolist>,在用infolist.各自的表头,如:${infolist.fund_num}。
        String sumShizhi = sumShizhi(proList);
        root.put("sum",sumShizhi);
        //防止图片出现小红叉(生成时为空,复核加盖印章)
        if("0".equals(flag)){ 
            root.put("aa",0);
            root.put("image","");
        }
        //dataMap.put("image","");
        if ("1".equals(flag)) {
            root.put("aa",1);
            root.put("image", intelligenceWord());//插入图片
        }
        return root;
    }
    /**
     * 求和
     * @param proList
     * @return
     */
    private String sumShizhi(List<Map<String, Object>> proList) {
        double sumShizhi = 0;
        for (int i = 0; i < proList.size(); i++) {
             double shizhi_df = Double.parseDouble(isNotNullString((String)proList.get(i).get("shizhi")));
             sumShizhi += shizhi_df;
        }
        return String.valueOf(sumShizhi);
    }

    /**
     * 模拟列表数据
     * @return
     * @throws Exception
     */
    private List<Map<String, Object>> getProList() throws Exception {
        List<Map<String, Object>> proList = new ArrayList<Map<String, Object>>();
        if (true) {
            List<String> fund_num = new ArrayList<String>();
            fund_num.add("1");
            fund_num.add("2");
            fund_num.add("3");
            List<String> pro_code = new ArrayList<String>();
            pro_code.add("1");
            pro_code.add("2");
            pro_code.add("3");
            List<String> pro_name = new ArrayList<String>();
            pro_name.add("pro_name");
            pro_name.add("2");
            pro_name.add("3");
            List<String> share = new ArrayList<String>();
            share.add("1");
            share.add("2");
            share.add("3");
            List<String> jingzhi = new ArrayList<String>();
            jingzhi.add("1");
            jingzhi.add("2");
            jingzhi.add("3");
            List<String> shizhi = new ArrayList<String>();
            shizhi.add("1");
            shizhi.add("2");
            shizhi.add("3");

            DecimalFormat df = new DecimalFormat("###,##0.00");
            DecimalFormat df_jz = new DecimalFormat("###,##0.0000");
            for (int i = 0; i < fund_num.size(); i++) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("fund_num", fund_num.get(i) == null ? "" : fund_num.get(i));
                map.put("pro_code", pro_code.get(i) == null ? "" : pro_code.get(i));
                map.put("pro_name", pro_name.get(i) == null ? "" : pro_name.get(i));
                double share_df = Double.parseDouble(isNotNullString(share.get(i)));
                map.put("share", share.get(i) == null ? "" : df.format(share_df));
                double jingzhi_df = Double.parseDouble(isNotNullString(jingzhi.get(i)));
                map.put("jingzhi", jingzhi.get(i) == null ? "" : df_jz.format(jingzhi_df));
                double shizhi_df = Double.parseDouble(isNotNullString(shizhi.get(i)));
                map.put("shizhi", shizhi.get(i) == null ? "" : df.format(shizhi_df));
                proList.add(map);
            }
        }
        return proList;
    }

    /**
     * 获取印章并解析word可以识别的编码
     * @return
     * @throws FileNotFoundException 
     */
    public String intelligenceWord() throws FileNotFoundException {
        BASE64Encoder encoder = new BASE64Encoder();
        String path = this.getClass().getResource("/").getPath();
        //InputStream input = this.getClass().getResourceAsStream("/image.jpg");
        System.out.println(path);
        File file = new File(path+"image.jpg");
        InputStream input = new FileInputStream(file);
        byte[] fileBytes = new byte[(int) file.length()];
        try {
            input.read(fileBytes);//读进fileBytes数组里面
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (input != null)
                    input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return encoder.encodeBuffer(fileBytes).trim();
    }

    private String isNotNullString (String agus) {
        String result="0";
        if (null!=agus&&!"".equals(agus)) {
            result=agus;
        }
        return result;

    }
}

template.xml 模板

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Word.Document"?>
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:wsp="http://schemas.microsoft.com/office/word/2003/wordml/sp2" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve">
<w:ignoreElements w:val="http://schemas.microsoft.com/office/word/2003/wordml/sp2"/>
<o:DocumentProperties>
<o:Title>测试构建word动态table</o:Title>
<o:Author>xxs</o:Author>
<o:LastAuthor>gf</o:LastAuthor>
<o:Revision>2</o:Revision>
<o:TotalTime>1</o:TotalTime>
<o:LastPrinted>2015-01-07T05:22:00Z</o:LastPrinted>
<o:Created>2017-01-20T00:44:00Z</o:Created>
<o:LastSaved>2017-01-20T00:44:00Z</o:LastSaved>
<o:Pages>1</o:Pages>
<o:Words>36</o:Words>
<o:Characters>211</o:Characters>
<o:Company>Microsoft</o:Company>
<o:Lines>1</o:Lines>
<o:Paragraphs>1</o:Paragraphs>
<o:CharactersWithSpaces>246</o:CharactersWithSpaces>
<o:Version>11.0000</o:Version>
</o:DocumentProperties>
<w:fonts>
<w:defaultFonts w:ascii="Times New Roman" w:fareast="宋体" w:h-ansi="Times New Roman" w:cs="Times New Roman"/>
<w:font w:name="宋体">
<w:altName w:val="SimSun"/>
<w:panose-1 w:val="02010600030101010101"/>
<w:charset w:val="86"/>
<w:family w:val="Auto"/>
<w:pitch w:val="variable"/>
<w:sig w:usb-0="00000003" w:usb-1="288F0000" w:usb-2="00000016" w:usb-3="00000000" w:csb-0="00040001" w:csb-1="00000000"/>
</w:font>
<w:font w:name="Calibri">
<w:panose-1 w:val="020F0502020204030204"/>
<w:charset w:val="00"/>
<w:family w:val="Swiss"/>
<w:pitch w:val="variable"/>
<w:sig w:usb-0="E10002FF" w:usb-1="4000ACFF" w:usb-2="00000009" w:usb-3="00000000" w:csb-0="0000019F" w:csb-1="00000000"/>
</w:font>
<w:font w:name="@宋体">
<w:panose-1 w:val="02010600030101010101"/>
<w:charset w:val="86"/>
<w:family w:val="Auto"/>
<w:pitch w:val="variable"/>
<w:sig w:usb-0="00000003" w:usb-1="288F0000" w:usb-2="00000016" w:usb-3="00000000" w:csb-0="00040001" w:csb-1="00000000"/>
</w:font>
</w:fonts>
<w:lists>
<w:listDef w:listDefId="0">
<w:lsid w:val="414E191B"/>
<w:plt w:val="HybridMultilevel"/>
<w:tmpl w:val="817AC34A"/>
<w:lvl w:ilvl="0" w:tplc="1592F012">
<w:start w:val="1"/>
<w:lvlText w:val="%1、"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="360" w:hanging="360"/>
</w:pPr>
<w:rPr>
<w:rFonts w:hint="default"/>
</w:rPr>
</w:lvl>
<w:lvl w:ilvl="1" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%2)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="840" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="2" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%3."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:ind w:left="1260" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="3" w:tplc="0409000F" w:tentative="on">
<w:start w:val="1"/>
<w:lvlText w:val="%4."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="1680" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="4" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%5)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="2100" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="5" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%6."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:ind w:left="2520" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="6" w:tplc="0409000F" w:tentative="on">
<w:start w:val="1"/>
<w:lvlText w:val="%7."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="2940" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="7" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%8)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="3360" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="8" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%9."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:ind w:left="3780" w:hanging="420"/>
</w:pPr>
</w:lvl>
</w:listDef>
<w:listDef w:listDefId="1">
<w:lsid w:val="438B7A60"/>
<w:plt w:val="HybridMultilevel"/>
<w:tmpl w:val="88BC2166"/>
<w:lvl w:ilvl="0" w:tplc="C7E656A4">
<w:start w:val="1"/>
<w:lvlText w:val="%1."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="-6" w:hanging="420"/>
</w:pPr>
<w:rPr>
<w:rFonts w:ascii="Times New Roman" w:fareast="宋体" w:h-ansi="Times New Roman" w:cs="Times New Roman"/>
</w:rPr>
</w:lvl>
<w:lvl w:ilvl="1" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%2)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="414" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="2" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%3."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:ind w:left="834" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="3" w:tplc="0409000F" w:tentative="on">
<w:start w:val="1"/>
<w:lvlText w:val="%4."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="1254" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="4" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%5)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="1674" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="5" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%6."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:ind w:left="2094" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="6" w:tplc="0409000F" w:tentative="on">
<w:start w:val="1"/>
<w:lvlText w:val="%7."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="2514" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="7" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%8)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="2934" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="8" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%9."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:ind w:left="3354" w:hanging="420"/>
</w:pPr>
</w:lvl>
</w:listDef>
<w:listDef w:listDefId="2">
<w:lsid w:val="4EE27D85"/>
<w:plt w:val="HybridMultilevel"/>
<w:tmpl w:val="76143BFC"/>
<w:lvl w:ilvl="0" w:tplc="FE0CCD4C">
<w:start w:val="1"/>
<w:lvlText w:val="%1."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:tabs>
<w:tab w:val="list" w:pos="360"/>
</w:tabs>
<w:ind w:left="360" w:hanging="360"/>
</w:pPr>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
</w:lvl>
<w:lvl w:ilvl="1" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%2)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:tabs>
<w:tab w:val="list" w:pos="840"/>
</w:tabs>
<w:ind w:left="840" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="2" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%3."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:tabs>
<w:tab w:val="list" w:pos="1260"/>
</w:tabs>
<w:ind w:left="1260" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="3" w:tplc="0409000F" w:tentative="on">
<w:start w:val="1"/>
<w:lvlText w:val="%4."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:tabs>
<w:tab w:val="list" w:pos="1680"/>
</w:tabs>
<w:ind w:left="1680" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="4" w:tplc="04090019" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="4"/>
<w:lvlText w:val="%5)"/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:tabs>
<w:tab w:val="list" w:pos="2100"/>
</w:tabs>
<w:ind w:left="2100" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="5" w:tplc="0409001B" w:tentative="on">
<w:start w:val="1"/>
<w:nfc w:val="2"/>
<w:lvlText w:val="%6."/>
<w:lvlJc w:val="right"/>
<w:pPr>
<w:tabs>
<w:tab w:val="list" w:pos="2520"/>
</w:tabs>
<w:ind w:left="2520" w:hanging="420"/>
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="6" w:tplc="0409000F" w:tentative="on">
<w:start w:val="1"/>
<w:lvlText w:val="%7."/>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:tabs>
<w:ta
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值