1. 程式人生 > >Java中使用freemarker匯出word文件(詳細案例,含圖片和表格)

Java中使用freemarker匯出word文件(詳細案例,含圖片和表格)

Java中使用freemarker匯出word文件(自己真實專案案例)

最近做了一個專案,有一個需求是要將職員的一些資料按照指定的樣式匯出成一個word文件出來,由於自己是一個Java小白,不懂,於是便在網上找方法,網上介紹的有很多,因為原來用poi匯出過ppt,於是便想用poi來做,但是由於時間不夠,最終選擇了用freemarker來做,在做的過程中遇到了一些問題,但最終還是完成了。於是把自己完成這個功能所做的一切從頭到尾的記錄一編,希望能對其他人有幫助。

1.專案需要匯出圖片和表格

可以看出在這個樣式中,需要匯出圖片和迴圈表格。

2.開始製作模板

在製作模板時,用office word 2003或以上的版本來製作,不要用wps做。在畫模板遇到一些問題,我的解決如下:
1.關於圖片,我畫了一個文字框來放圖片,然後隨便放了一個圖片進去(一定要插入一張圖片,方便後面找到圖片的位置好 進行替換)。
2.一些需要動態生成的資料寫如個人資訊用personInfo來代替,注意,單詞要先用一個文字框寫好,再複製黏貼過來,不要再word上手動敲,不然再轉成xml時單詞會被拆散。也不要直接黏貼過來一個${personInfo}

,我發現還是會被拆散,最好直接黏貼一個單詞過來,在xml中再找到這個單詞再新增${}。
3.表格只需要畫一行,迴圈在xml中配置。
這裡寫圖片描述

模板畫好之後,直接將word另存為xml格式,儲存完後將word關掉。

用notepad++開啟你儲存的xml格式的文件找到你寫的單詞如stdName

在單詞前後加上${},所有你寫的單詞都加上。

搜尋w:tr找到表格

在表格標籤<w:tr>的首尾分別加上<#list expList as exp></#list> 標籤,並且標籤裡的單詞要改成${exp.time}這種形式。解釋一下:list標籤可以使標籤內的表格自動迴圈生成相應的行數,expList是自己命名的,是表格的資料來源,是一個list集合。exp是別名。

搜尋<pkg:binaryData>,你會發現這個標籤裡的內容特別多,這就是你畫模板時插入的圖片的BASE64字串。

<pkg:binaryData>標籤裡的內容刪完,替換為${images},這樣就可以在程式碼中設定,然後匯出自己獲取的圖片了,當然名字自己取,叫img也可以,只要在程式碼中和這對應就好了。

3.完成模板

將上面修改好的xml文件儲存好,點選重新命名將其型別修改為ftl。我的是將template.xml改為template.ftl。
好了,至此,模板就製作好了,在後面程式碼中你要用的模板就是template.ftl。我是直接將template.ftl文件複製到我的專案中,當然,你放本地也可以,只是引用時方法和路徑不一樣而已。

4.Java程式碼

private void exportWord(String ssdw, String image64Str, String stdName, String personInfo, List<FamilyInfo> familyInfos,
            Map<String, String> maps) {
    Map<String, Object> dataMap = new HashMap<String, Object>();
    //ssdw 是我前面獲取的職員資訊
    dataMap.put("orgName", ssdw);
    //image64Str 是職員的照片轉換後的BASE64字串
    dataMap.put("images", image64Str);
    //stdName 是我前面獲取的職員資訊
    dataMap.put("stdName", stdName);
    //personInfo 是我前面獲取的職員資訊
    dataMap.put("personInfo", personInfo);

    //familyList 是職員的家庭資訊的集合,對應模板中的表格
    List<Map<String, Object>> familyList = new ArrayList<Map<String, Object>>();
    for (int i = 0; i < familyInfos.size(); i++) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("gx", familyInfos.get(i).getYbrgx());
        map.put("xm", familyInfos.get(i).getCyxm());
        map.put("dwjzw", familyInfos.get(i).getDwjzw());
        familyList.add(map);
    }
    dataMap.put("familyList", familyList);

    //expList 是職員的工作經歷資訊的集合,對應模板中的表格
    List<Map<String, Object>> expList = new ArrayList<Map<String, Object>>();
    Iterator<Entry<String, String>> it = maps.entrySet().iterator();
    while (it.hasNext()) {
        Map<String, Object> map = new HashMap<String, Object>();
        Map.Entry<String, String> entity = (Entry<String, String>) it.next();
        map.put("time", entity.getKey());
        map.put("experience", entity.getValue());
        expList.add(map);
    }
    dataMap.put("expList", expList);

    @SuppressWarnings("deprecation")
    Configuration configuration = new Configuration();
    configuration.setDefaultEncoding("utf-8");
    //有兩種方式獲取你的模板,模板在專案中時用第一個,模板在本地時用第二個。
    //注意:兩種方式的路徑都只需要寫到模板的上一級目錄
    configuration.setClassForTemplateLoading(this.getClass(), "/tem");
//  configuration.setDirectoryForTemplateLoading(new File("C:/"));  

    File outFile = new File("D:/outFilessa"+Math.random()*10000+".doc");//輸出路徑
    Template t=null;  
    Writer out = null;
    try {
        t = configuration.getTemplate("template.ftl", "utf-8"); //檔名,獲取模板
        out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));  
        t.process(dataMap, out);
    } catch (Exception e) {
        e.printStackTrace();  
    } finally {
        try {
            out.close();
        } catch (IOException  e1) {
            e.printStackTrace(); 
        }
    }

}

將獲取的圖片轉換為BASE64字串

public String getImageStr() {  
       //data是獲取圖片的二進位制碼;怎麼獲取圖片以及怎麼將圖片轉為二進位制碼的方法就不多說了
       BASE64Encoder encoder = new BASE64Encoder();  
       return encoder.encode(data);  
}  

要使用BASE64Encoder還得有如下操作:
點選你的專案名右鍵,選擇Properties,進去後選擇Java Build Path,然後如圖:



操作完成,應用並OK。

Over 使用freemarker匯出word完成。