使用freemarker模板导出excel

话不多说直接进入正题,记录一次使用freemarker模板导出excel的过程:

1.先写个导出文件的工具类。代码如下:

package com.xxxx.web.action.xxx;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;


public class FtlHandler {

    /**
     * 生成文件
     * @param fileName 模板文件全名(含后缀)
     * @param outName  导出后文件的全名(含后缀)
     * @param response
     * @param map 模板中需要的数据
     * @throws IOException
     * @throws Exception
     * @throws TemplateException
     */
    public static void directResponseFile(String fileName, String outName,HttpServletResponse response, Map map) throws IOException, Exception, TemplateException {
        //配置响应文件类型
        if(outName.contains(".xls") || outName.contains(".xlsx")) {
    		response.setContentType("application/x-xls");//excel
    	}else {
    		response.setContentType("application/msword");//word
    	}
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(outName, "UTF-8"));
        createFile(fileName, response.getWriter(), map);
        response.reset(); // 清除非常重要
    }


    /**
     * freemaker通过模板生成文件
     * @param fileName 文件全名(含后缀)
     * @param writer
     * @param writeData 模板需要的数据
     * @throws TemplateException
     * @throws Exception
     * @throws IOException
     */
    private static void createFile(String fileName,Writer writer,Map writeData) throws TemplateException, Exception, IOException {
        if(fileName == null || !fileName.contains("."))
            throw new Exception("请输入正确的文件名");

        Configuration cfg=new Configuration();
        String path =FtlHandler.class.getResource("/").getPath()+"ftl";

        TemplateLoader templateLoader = new FileTemplateLoader(new File(path));
        cfg.setTemplateLoader(templateLoader);
        cfg.setDefaultEncoding("UTF-8");//设置模板读取的编码方式,用于处理乱码

        Template template = cfg.getTemplate(fileName,"UTF-8");//模板文件,支持xml,ftl 也支持html

        template.process(writeData, writer);//将模板写到文件中
        writer.flush();
        cfg.clearTemplateCache();
        writer.close();
    }
}

2.在action或者controller里面把需要传入到excel中的数据获取到,然后调用工具类;

         注意事项:a.在调试的过程中发现如果传入的参数为null的时候会报错,所以需要处理一下,要么在后台判断一下 xxx== null ? "" : xxx;要么就在模板中${code!' '}处理一下。

3.客户提供excel模板后把需要填充的地方都写上内容,然后用office把excel另存为《XML电子表格2003》;

          注意事项:a.xml中只能存储文本,所以excel模板中不能有图片;

                            b.说一下踩得一个坑以及解决方案:另存为以后发现xml中在标签之前有很多的乱码,还有后面的标签里也有很多,对比了一下其他的xml发现时没有的,所以就把带有乱码的全都删除了,需要特别注意的是里的保留了最后一行,最后一行是没有乱码的,后续印证还是可行的。

4.把处理之后xml放到系统中,然后根据在excel中填入的数据对照着action里自己传的参数把数据替换成参数;例如:${mcdSum}等等,需要遍历输出行的话就用list

<#if mcdList?exists >
   <#list mcdList as mcd>
   
    ${mcd.partName}
    ${mcd.pointQty}
    ${mcd.qty}
    ${mcd.price}
    ${mcd.cost}
   
   

5.之后就是逐步调试,直到最后没有问能够满足需求进行导出。

         注意事项:最后发现一个问题,导出之后的excel在wps中可以打开,在office中打不开就像下图一样,点击是就会报错

使用freemarker模板导出excel_第1张图片

使用freemarker模板导出excel_第2张图片

怎么处理呢?我是这么干的,既然报错了也给了日志就去看日志呗。找日志的时候发现是找不到的,文件夹被隐藏了,所以我直接在盘符里面搜索的日志,找到以后打开是这样的

使用freemarker模板导出excel_第3张图片

拿到错误信息直接去找错误点就好了,第一个StyleID s418值无效,如果传过来的参数不是null就把s418改成其他的同类型的s420啥的;第二个跟第三个一样都是ss:ExpandedRowCount值是多少的时候报错,查了一圈资料,推测了一下这东西的意思大概就是最大行数之类的,可能是超过了限制吧,所以就把报错的都改成999就搞定了。最后还有一个问题就是office在打开的时候会给提示,如下图,不过点击是的时候是可以打开的,且内容无误,希望有懂的大佬解释一下。

使用freemarker模板导出excel_第4张图片

 

你可能感兴趣的:(个人成长,java,excel,freemarker,模板导出excel)