自我救贖之路—(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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章