JAVA 使用freemarker导出Word、循环生成多页文档 - 学习记录二

xu.wang

发布于 2019.12.19 23:24 阅读 4322 评论 0

在生成word的时候,只替换文档中的字符会有很多的限制,例如想生成多页相同格式的文档时就不好实现。

本次记录接 《JAVA 使用freemarker导出Word - 学习记录一》,在上一篇的基础上增加循环生成相同格式的word。

第一步:与上一篇相同,先生成word模板,然后将word另存为xml后修改后缀名为ftl。

我的模板如下

注意生成xml后需要修改占位符被xml标签隔开的情况,类似下图:

 

第二步:打开xml在模板内容增加  <#list columns as obj> </#list>

      注意 “ columns”为代码中list的参数名称,“obj”为list的每一项的名字。

      2.1 若生成的模板为表格则在<w:tbl> 标签前、</w:tbl>后增加循环标签

       2.2 若生成的模板中不带有表格,直接在文档中增加了占位符,则在<w:body></w:body>标签之前增加<#list columns as obj> </#list>

第三步: 在展位符名称前增加 “obj.” 如下图

第四步:撸代码

还是使用Junit进行测试:

注意:

分页符为:<w:p><w:r><w:br w:type="page"/></w:r></w:p>

换行符为:</w:t></w:r></w:p><w:p><w:pPr></w:pPr>  ,文字换行后第二行的文本格式会被清除,所以需要手动添加格式。

            str.append(" </w:t></w:r></w:p><w:p><w:pPr></w:pPr>");
            //换行、增加下面的代码防止换行后出现格式被清楚的情况
            str.append("<w:r><w:rPr>");
            //设置样式  字体 大小 颜色
            str.append("<w:rFonts w:ascii=\"宋体\" w:fareast=\"宋体\" w:h-ansi=\"宋体\"/>");
            str.append("<w:color w:val=\"000000\"/><w:sz w:val=\"28\"/>");
            //换行3
            str.append(" </w:rPr><w:t>  ");

 

 @Test
    public void excelTest(){
        Map<String,Object> dataMap = new HashMap<String, Object>();
        try {

            //测试数据
            List<Map> mapList = new ArrayList<>();
            Map contentMap1 = new HashMap();
            contentMap1.put("roleName1","角色-1 ");
            contentMap1.put("roleName2","角色-2 ");
            contentMap1.put("roleName3","角色-3 ");
            contentMap1.put("roleName4","角色-4 ");
            contentMap1.put("roleName5","角色-5 ");
            contentMap1.put("roleName6","角色-6 ");
            contentMap1.put("roleName7","");
            contentMap1.put("roleName8","");
            contentMap1.put("roleName9","");
            contentMap1.put("roleName10","");

            contentMap1.put("userName1","王**-1 ");
            contentMap1.put("userName2","赵**-2 ");
            contentMap1.put("userName3","钱**-3 ");
            contentMap1.put("userName4","孙**-4 ");
            contentMap1.put("userName5","李**-5 ");
            contentMap1.put("userName6","周**-6 ");
            contentMap1.put("userName7","");
            contentMap1.put("userName8","");
            contentMap1.put("userName9","");
            contentMap1.put("userName10","");

            contentMap1.put("title", "标题");
            contentMap1.put("groupName", "小组名");
            contentMap1.put("number", "人数");
            //换行符
            contentMap1.put("line", "<w:p><w:r><w:br w:type=\"page\"/></w:r></w:p>");

            mapList.add(contentMap1);

            Map contentMap2 = new HashMap();
            contentMap2.put("roleName1","角色-1 ");
            contentMap2.put("roleName2","角色-2 ");
            contentMap2.put("roleName3","角色-3 ");
            contentMap2.put("roleName4","角色-4 ");
            contentMap2.put("roleName5","角色-5 ");
            contentMap2.put("roleName6","角色-6 ");
            contentMap2.put("roleName7","");
            contentMap2.put("roleName8","");
            contentMap2.put("roleName9","");
            contentMap2.put("roleName10","");

            contentMap2.put("userName1","王**-1 ");
            contentMap2.put("userName2","赵**-2 ");
            contentMap2.put("userName3","钱**-3 ");
            contentMap2.put("userName4","孙**-4 ");
            contentMap2.put("userName5","李**-5 ");

            StringBuffer str = new StringBuffer();
            str.append(" </w:t></w:r></w:p><w:p><w:pPr></w:pPr>");
            //换行、增加下面的代码防止换行后出现格式被清楚的情况
            str.append("<w:r><w:rPr>");
            //设置样式  字体 大小 颜色
            str.append("<w:rFonts w:ascii=\"宋体\" w:fareast=\"宋体\" w:h-ansi=\"宋体\"/>");
            str.append("<w:color w:val=\"000000\"/><w:sz w:val=\"28\"/>");
            //换行3
            str.append(" </w:rPr><w:t>  ");

            contentMap2.put("userName6","周** 周**  周** 周**  周**  周** "+str+"                 周**  周**  周**  周**");
            contentMap2.put("userName7","");
            contentMap2.put("userName8","");
            contentMap2.put("userName9","");
            contentMap2.put("userName10","");

            contentMap2.put("title", "标题");
            contentMap2.put("groupName", "标题");
            contentMap2.put("number", "标题");
            contentMap2.put("line", "<w:p><w:r><w:br w:type=\"page\"/></w:r></w:p>");

            mapList.add(contentMap2);


            dataMap.put("columns",mapList);

            //Configuration 用于读取ftl文件
            Configuration configuration = new Configuration(new Version("2.3.0"));
            configuration.setDefaultEncoding("utf-8");

            /**
             * 以下是两种指定ftl文件所在目录路径的方式,注意这两种方式都是
             * 指定ftl文件所在目录的路径,而不是ftl文件的路径
             */
            //指定路径的第一种方式(根据某个类的相对路径指定)
//                configuration.setClassForTemplateLoading(this.getClass(), "");

            //指定路径的第二种方式,我的路径是C:/a.ftl
            configuration.setDirectoryForTemplateLoading(new File("/Users/xuwang/Desktop/"));

            //输出文档路径及名称
            File outFile = new File("/Users/xuwang/Desktop/导出-excelWord.doc");

            //以utf-8的编码读取ftl文件
            Template template = configuration.getTemplate("patrolTemplate.ftl", "utf-8");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
            template.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }