zoukankan      html  css  js  c++  java
  • freemarker根据模板生成word文件实现导出功能

    一、准备工作

    1.创建一个03的word文档,动态的数据用占位符标志占位(如testname)。然后另存为word2003的xml文件。

    2.格式化xml文件,占位符的位置用${testname}代替,若有多行格式相同数据等,用List循环。

      注意:不要用Eclipse工具去格式化xml文件(会导致导出的word文件不能用office软件打开,但是PDF能打开,估计是pdf的容错率高于office),推荐使用firstObject工具格式化xml文件。

    firstobject下载地址:http://www.firstobject.com/dn_editor.htm

    3.将xml文件(也可以改成ftl格式)存放到项目中指定位置。

    3.下载freemarker的jar包(到中央仓库即可下载)。  

        

    二、前端

    前端页面添加一个导出按钮,然后按钮添加点击事件,事件中跳转到所请求的Controller层即可:

    window.location.href='XXXController/XXXMethod';

    如有参数,直接添加到后边即可。

    三、后台

    1.编写工具类

    复制代码
    package io.renren.common.utils;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Map;
    import java.util.Random;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    
    /**
    * 文件导出工具类
    *
    * @author zblwj
    * @email 351094262@qq.com    
    * @date 2018年11月1日下午2:40:42
    */
    public class WordUtils {
    /**
    *    生成word文档 
    */
    @SuppressWarnings("unchecked")
    public static File createWord(Map dataMap,String templateName,String filePath,String fileName){
    
    try {
    //创建配置实例
    Configuration configuration = new Configuration();
    
    //设置编码
    configuration.setDefaultEncoding("UTF-8");
    
    //ftl模板文件
    configuration.setClassForTemplateLoading(WordUtils.class,"/template");
    
    //获取模板
    Template template = configuration.getTemplate(templateName);
    
    //输出文件
    File outFile = new File(filePath+File.separator+fileName);
    //如果输出目标文件夹不存在,则创建
    if (!outFile.getParentFile().exists()){
    outFile.getParentFile().mkdirs();
    }
    //将模板和数据模型合并生成文件
    Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
    //生成文件
    template.process(dataMap, out);
    //关闭流
    out.flush();
    out.close();
    return outFile;
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    }
    
    /**
    * 生成文件名字
    * @return
    */
    public static String creatFileName() {
    /** 文件名称,唯一字符串 */
    Random r = new Random();
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
    StringBuffer sb = new StringBuffer();
    sb.append(sdf1.format(new Date()));
    sb.append("_");
    sb.append(r.nextInt(100));
    //文件唯一名称
    String fileOnlyName = "机关党支部党员积分申报表" + sb + ".doc";
    return fileOnlyName;
    }
    
    /**
    * 导出文件
    * @throws IOException 
    */
    public static void exportMillCertificateWord( HttpServletResponse response, Map map,String filePath,String templateName) throws IOException {
    File file = null; 
    InputStream fin = null; 
    ServletOutputStream out = null;
    try {
    String fileName = WordUtils.creatFileName();
    file = WordUtils.createWord(map, templateName, filePath,fileName);
    fin = new FileInputStream(file);
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/msword");
    response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
    out = response.getOutputStream();
    byte[] buffer = new byte[512]; // 缓冲区 
    int bytesToRead = -1; 
    // 通过循环将读入的Word文件的内容输出到浏览器中 
    while((bytesToRead = fin.read(buffer)) != -1) { 
    out.write(buffer, 0, bytesToRead); 
    } 
    }finally {
    if(fin != null) fin.close(); 
    if(out != null) out.close(); 
    if(file != null) file.delete(); // 删除临时文件 
    }
    
    }
    }
    复制代码

    2.Controller层

    复制代码
    @RequestMapping("/exportSellPlan")
    @ResponseBody
    public void exportSellPlan(HttpServletResponse response,PageUtils page, NcPartydeclare partydeclare) {
    try {
    Map<String, Object> dataMap = partyDeclareService.exportWordFile(response,page, partydeclare);
    WordUtils.exportMillCertificateWord(response, dataMap, "D:/doc_f/","test.xml");
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    复制代码

    3.Server层(主要是获取数据源)

    复制代码
    /**
    * word文件导出
    */
    @Override
    public Map<String, Object> exportWordFile(HttpServletResponse response, PageUtils page, NcPartydeclare partydeclare) {
    partydeclare.setUserid( getCurrUser().getUserid());
    //数据源
    List<?> list = partydeclareMapper.selectPersonPage(page, page.getOrderByClause(), partydeclare);
    /** 用于组装word页面需要的数据 */
    Map<String, Object> dataMap = new HashMap<String, Object>();
    /** 组装数据 */
    dataMap.put("realname", partydeclare.getRealname());
    dataMap.put("zname", "");
    dataMap.put("sname", "");
    List<Map<String, Object>> listInfo = new ArrayList<Map<String, Object>>();
    BigDecimal num = new BigDecimal ("0");
    for (int i = 0; i < 10; i++) {
    Map<String, Object> map = new HashMap<String, Object>();
    if(list.size() -1 < i) {
    map.put("index","");
    map.put("sbtitle","");
    map.put("add", "");
    map.put("reduce","");
    }else {
    NcPartydeclare entity = (NcPartydeclare)list.get(i);
    map.put("index",i+1);
    map.put("sbtitle",entity.getTitle());
    map.put("add", entity.getBonusvalue());
    map.put("reduce", entity.getSubtractionvalue());
    //计算总共
    num = num.add(entity.getBonusvalue()).subtract(entity.getSubtractionvalue());
    }
    listInfo.add(map);
    }
    //计算总共分数
    dataMap.put("total", num);
    dataMap.put("listInfo", listInfo);
    return dataMap; 
    }
    复制代码

     三、最终结果

     四、个人总结

         此方法还是很简单,但是由于第一次使用,废了不少功夫。导出过程中会生成一个临时的文件,然后利用response的输出流将文件读取到浏览器客户端,读取完成后将会删除生成的临时文件。个人踩坑的地方是用Eclipse格式化了xml文件,导致了导出的word文件不能用office工具打开。

    个人学习随笔,如若转载,请标明出处。如有不懂之处,联系QQ:351094262
  • 相关阅读:
    【转】基于 Apache 在本地配置多个虚拟主机
    ubuntu linux下各种格式软件包的安装卸载
    钩子
    静态方法中不能使用 $this
    Redis Sentinel机制与用法说明【转】
    CI 分页类的使用
    MySQL压力测试
    简单配置.htaccess就可以实现的10个功能
    bzoj 3529 数表
    poj2773 Happy 2006
  • 原文地址:https://www.cnblogs.com/zhouheblog/p/9929861.html
Copyright © 2011-2022 走看看