自我救赎之路—(Freemarker.ftl 模板导出word)

Springboot 通过Freemarker 模板引擎导出word

虽然网上很多,到处都是,但是自己做的时候还是会遇到很多问题,特意笔记一下。
现在来说功能和开发步骤;

需求

导出如下图所示的word文档
这里写图片描述

这个word文档也算不上太复杂,主要有几个特点:文本字段(string)、列表字段(list)

开发步骤

先来处理word模板文件

  1. 准备模板Word
    这里写图片描述

  2. 把word模板文件另存为,如下图
    这里写图片描述

  3. 把保存后的模板的后缀名改成.ftl ,如下图
    这里写图片描述

word 模板处理的差不多了,在来处理代码

a. 添加freemarker模板

 <!--添加freemarker模板-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.27-incubating</version>
        </dependency>

b. 把刚才修改成.ftl后缀名的模板文件直接拷贝到项目当中,在点击打开编辑,如下图
这里写图片描述
————————————————————-修改模板字段————————————
这里写图片描述
—————————————–后台模板字段——————————
这里写图片描述
———————————–修改list表格模板————————————
这里写图片描述
这里写图片描述
——————————后台字段模板—————————————–
这里写图片描述

注意:上面的后台字段模板是为了让大家知道页面绑定什么样的字段,后台就绑定什么样的字段或是集合
${wsl.stepNo!''} 还有就是这种写法!”是为了判断是否为空,如果为空不处理就会报错,所以绑定的字段后面加!”
其实在一开始创建word模板的时候就可以添加${String}绑定的字段,但是修改后缀名ftl后里面的内容回乱, 还要在页面中在修改,所以建议最后在修改ftl模板。

c. 开始写代码了,放在你想要调用的控制器下面就行:

    //word生成和下载  工作票生成  cwm add  2018-5-2

    @RequestMapping("downLoad")
    public ResponseEntity<InputStreamResource> dowmload(Integer id) throws Exception {
        ////获取跟目录
        File path = new File(ResourceUtils.getURL("classpath:").getPath());
        //如果上传目录为/downfile,则可以如下获取:
        File downfile = new File(path.getAbsolutePath(),"downfile/");
        if(!downfile.exists()) downfile.mkdirs();
        //文件保存路径
        String  filePath =  URLDecoder.decode( downfile.getPath(), "UTF-8");//"D:\\baidupan";

        //文件唯一名称
        String ticketName="工作票"+ new SimpleDateFormat("yyyyMMddhhmmss").format(new Date())+ ".doc";
        String fileOnlyName =URLDecoder.decode( ticketName,"UTF-8");

        String modelName="freemarker.ftl";
        File staticPath = new File(path.getAbsolutePath(),"templates/workticket/");
        String sourePath=URLDecoder.decode(staticPath.getPath(),"UTF-8");
        //准备数据 这里的数据是为生成word模板准备的数据,调用下面的方法生成的数据
        Map<String,Object> dataMap= getTicketAllData(id);

        /** 生成word */
        if(WordHelper.wordutil(dataMap, modelName, filePath,sourePath,fileOnlyName))
        {
            FileSystemResource file = new FileSystemResource(filePath + File.separator + fileOnlyName);
            HttpHeaders headers = new HttpHeaders();

            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            String downfilename=new String(file.getFilename().getBytes("GB2312"), "ISO_8859_1");
            headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"",downfilename ));
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");
            return ResponseEntity
                    .ok()
                    .headers(headers)
                    .contentLength(file.contentLength())
                    .contentType(MediaType.parseMediaType("application/octet-stream"))

                    .body(new InputStreamResource(file.getInputStream()));
        }else
        {
            throw new Exception(URLDecoder.decode("生成word文档失败!","UTF-8"));
        }
    }

d. 这里是准备的数据

/**
     * cwm add 2018-5-5  
     * 根据工作票id来获取工作票导出信息
     * @param id
     * @return
     */
    private  Map<String,Object> getTicketAllData(Integer id)
    {
        Map<String,Object> dataMap=new HashMap<>();

        WorkTicketModel workTicketModel = optWorkTicketService.getWorkTicketModel(id);
        if(workTicketModel!=null)
        {
            //工作票
            WorkTicketVM workTicketVM=workTicketModel.getWorkTicketVM();
            if(workTicketVM!=null)
            {
                dataMap.put("repair_company",workTicketVM.getRepair_company()==null?"":workTicketVM.getRepair_company());
                dataMap.put("wt_no",workTicketVM.getWt_no()==null?"":workTicketVM.getWt_no());
                dataMap.put("team_leader",workTicketVM.getTeam_leader()==null?"":workTicketVM.getTeam_leader());
                dataMap.put("change_no",workTicketVM.getChange_no()==null?"":workTicketVM.getChange_no());
                dataMap.put("team_member",workTicketVM.getTeam_member()==null?"":workTicketVM.getTeam_member());
                dataMap.put("work_content",workTicketVM.getWork_content()==null?"":workTicketVM.getWork_content());
                dataMap.put("start_time",workTicketVM.getStart_time()==null?"":workTicketVM.getStart_time());
                dataMap.put("end_time",workTicketVM.getEnd_time()==null?"":workTicketVM.getEnd_time());
                dataMap.put("hot_tip",workTicketVM.getHot_tip()==null?"":workTicketVM.getHot_tip());
                dataMap.put("licensor_time_end",workTicketVM.getLicensor_time_start()==null?"":workTicketVM.getLicensor_time_start());//没有
                dataMap.put("issuer_id",workTicketVM.getIssuer_name()==null?"":workTicketVM.getIssuer_name());//没有
                dataMap.put("licensor_time_start",workTicketVM.getLicensor_time_start()==null?"":workTicketVM.getLicensor_time_start());//没有
                dataMap.put("team_leader",workTicketVM.getTeam_member()==null?"":workTicketVM.getTeam_member());
                //dataMap.put("team_member",workTicketVM.getTeam_member());
                dataMap.put("delay_leader","");//延期负责人没有
                dataMap.put("delay_licensor_id","");//延期许可人 没有
                dataMap.put("re_delay_leader","");//再次延期负责人 没有
                dataMap.put("re_delay_licensor_id","");//再次延期许可人 没有

                dataMap.put("finish_time","");//全部工作结束时间没有
                dataMap.put("remark","");//备注没有
            }
            //隔离措施
           WorkInsulateVM workInsulateVM=  workTicketModel.getWorkInsulate();
            if(workInsulateVM!=null)
            {
                dataMap.put("isolationNo",workInsulateVM.getIsolationNo()==null?"":workInsulateVM.getIsolationNo());
                dataMap.put("description",workInsulateVM.getDescription()==null?"":workInsulateVM.getDescription());
                dataMap.put("condition",workInsulateVM.getCondition()==null?"":workInsulateVM.getCondition());
                dataMap.put("approverPerson",workInsulateVM.getApproverPerson()==null?"":workInsulateVM.getApproverPerson());
                dataMap.put("markCardNo",workInsulateVM.getMarkCardNo()==null?"":workInsulateVM.getMarkCardNo());
            }
            //安全措施
            List<WorkSecurityVM> workSecurityList= workTicketModel.getWorkSecurityList();
            if(workSecurityList!=null)
            {
                dataMap.put("workSecurityList",workSecurityList);
            }
            //危险点预控措施
            List<WorkPreventVM> workPreventList = workTicketModel.getWorkPreventList();
            if(workPreventList!=null)
            {
                dataMap.put("workPreventList",workPreventList);
            }
        }

        return dataMap;

    }

e. 导出word的帮助类:

public class WordHelper {


    /**
     * 生成word文件
     * @param dataMap word中需要展示的动态数据,用map集合来保存
     * @param templateName word模板名称,例如:test.ftl
     * @param filePath 文件生成的目标路径,例如:D:/wordFile/
     * @param sourePath word模板路径
     * @param fileName 生成的文件名称,例如:test.doc
     */
    @SuppressWarnings("unchecked")
    public static boolean wordutil(Map dataMap, String templateName, String filePath,String sourePath, String fileName)
    {
        try {
            //创建配置实例
            Configuration configuration = new Configuration();

            //设置编码
            configuration.setDefaultEncoding("utf-8");

            //ftl模板文件
            //configuration.setClassForTemplateLoading(WordHelper.class,"/");

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

            //获取模板
            Template template = configuration.getTemplate(templateName);


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


            //输出文件
            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 true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}

欢迎大家批评和指导

每个人的背后都会有心酸,每个人的故事都有泪流。自己的路总归要自己走。困了,让自己睡一觉,累了,给自己一个拥抱;失败了,跌倒了,有人帮扶,一定要感恩,无人支持,也绝不气馁,随时记得给自己一份坚强,继续前行。
美好一天从“坚强”开始!

共同学习,共同进步,技术交流群:210470210

猜你喜欢

转载自blog.csdn.net/ccwm0129/article/details/80242297