2,制作报表模板

把模板文档需要动态添加内容的地方用${test} 占位,需要注意的是后台通过Template 对象的process 方法在模板中写入数据时是传入一个存放数据的Map来写入数据到模板的, 所以test需要后台dataMap中存入key为test的value,比较不一样的就是单元格中填入数据了,单元格中放入数据就需要在dataMap中放入List。模板中占位写法如下图

freemarker导出复杂excel freemarker导出word 表格_报表

这样dataMap就必须存入key为list value为List类型的数据,当然也可以key不为list 可在后面的模板中修改

3,写好了模板之后需要把模板转换为xml格式的文件,改为xml格式后需要用编辑器打开文件进行一些修改和补充。有时候由于模板的格式或者字体原因,当模板转换成xml文件后${test}会被拆分,如下面这样

<w:t>${</w:t><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:ascii="Consolas" w:hAnsi="Consolas" w:eastAsia="Consolas"/><w:color w:val="2A00FF"/><w:sz w:val="28"/><w:highlight w:val="white"/></w:rPr><w:t>test</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="微软雅黑" w:hAnsi="微软雅黑" w:eastAsia="微软雅黑"/></w:rPr><w:t xml:space="preserve"> } </w:t>

这样test由于模板的字体和格式样式被拆分了,这样会导致报错,必须手动把{test}拼到一起写到${test}中即可。

当然单元格中展示列表也需要一些修改,先找到标题后面第一个,在第一个前面加上一句标签<#list list as list> (这里#list是类型
as 前面的list是后台放到dataMap中对应的List的key,as 后面的是对list的别名,对应模板中的${list.test}标签的list)
然后在对应的标签后面加上

<#list list as list><w:tr><w:tblPrEx><w:tblLayout w:type="fixed"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx><w:trPr><w:trHeight w:val="270" w:hRule="atLeast"/></w:trPr><w:tc><w:tcPr><w:tcW w:w="2502" w:type="dxa"/><w:tcBorders><w:top w:val="nil"/><w:left w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/><w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/></w:tcBorders><w:shd w:val="clear" w:color="000000" w:fill="FFFFFF"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:widowControl/><w:spacing w:line="240" w:lineRule="auto"/><w:jc w:val="both"/><w:rPr><w:rFonts w:hint="eastAsia" w:ascii="微软雅黑" w:hAnsi="微软雅黑" w:eastAsia="微软雅黑" w:cs="宋体"/><w:snapToGrid/><w:color w:val="000000"/><w:szCs w:val="21"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:ascii="Consolas" w:hAnsi="Consolas" w:eastAsia="Consolas"/><w:color w:val="2A00FF"/><w:sz w:val="28"/><w:highlight w:val="white"/></w:rPr><w:t></w:t></w:r><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:ascii="Consolas" w:hAnsi="Consolas"/><w:color w:val="2A00FF"/><w:sz w:val="28"/><w:highlight w:val="white"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t></w:t></w:r><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:ascii="Consolas" w:hAnsi="Consolas" w:eastAsia="Consolas"/><w:color w:val="2A00FF"/><w:sz w:val="28"/><w:highlight w:val="white"/></w:rPr><w:t>${list.cpbCode}</w:t>.....................................</w:tr></#list>

这样模板修改的制作就完成了,最后只要把修改好的xml文件后缀改为
.ftl 就可以拿来用了。我实在根目录下新建了一个ftl的文件夹放进去

4,终于开始了代码环节

// 获取应用的根路径
        String servletContextRealPath = request.getServletContext().getRealPath("/");
        // 获取模板文件
               File templateFile = new    File(servletContextRealPath+"/ftl");
        Template t = null;
        configuration.setDefaultEncoding("UTF-8");
        try {// 模板文件所在路径
            configuration.setDirectoryForTemplateLoading(templateFile);
            // 获取模板文件
            t = configuration.getTemplate("report.ftl"); 

        File outFile = new File(templateFile+"/demo.doc"); // 导出文件到服务器
            Writer out = null;
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"utf-8"));
            t.process(dataMap, out); // 将填充数据填入模板文件并输出到目标文件
            out.close();
            //
            SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy-MM-dd");
            String reportDate = sdFormat.format(new Date());
            String filename="XXXXXX报告"+reportDate;
            downLoad(templateFile+"/demo.doc",response,filename,servletContextRealPath);

downLoad方法主要是从服务器下载到前端页面

public void downLoad(String filePath, HttpServletResponse response,String fileNewName,String servletContextRealPath) throws Exception {
            File f = new File(filePath);
            OutputStream out = response.getOutputStream();
            if (!f.exists()) {
                response.setCharacterEncoding("UTF-8");
                out.flush();
                return;
            }
            BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
            byte[] buf = new byte[1024];
            int len = 0;

            response.reset(); // 非常重要
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/x-msdownload; charset=UTF-8");
            response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileNewName, "UTF-8")+".doc");
            response.setHeader("name",servletContextRealPath+"download\\demo.doc");
            while ((len = br.read(buf)) > 0)
            out.write(buf, 0, len);
            br.close();
            out.close();
        }

基本这样就算完成了,
属于我这种新手写出来的功能,代码很多地方都很low,比如下载的话poi是直接可以导出到response里面下载到前端,jxl我找了很久api也没找到直接导出到前端的方法。。如果你们有大神知道可以给我指导下。不胜感激。。。