【FreeMarker】利用freemarker生成word版報表

前言:

在很多業務系統中,都需要生成月報,週報的報表。freemarker就很適合生成word版報表,freemarker就是利用word本身自帶的xml格式進行文本替換,圖片替換等操作的,當然除了簡單的替換文本之外,他還有其他的高級用法,詳情請見freemarker的官網,官網地址在文末給出。
利用freemarker生成報表只需要幾個簡單的步驟。

下面利用示例展示整個流程

1,製作word模板

按照自己的業務需求,首先整理出一個word模板,這個模板除了沒有數據之外,其他的部分都是已經固定的。只是在需要數據填充的部分暫時空着,之後調用相關的freemarker的API往裏面填充數據。
下面簡單的製作一個模板(格式排版並沒有嚴格製作,開發者在開發過程中需要自己調整好模板裏面的排版,格式。)

1.1 按照業務需求製作自己的模板

下面是一個示例:
生成的word模板如下:
freemarker操作說明書.doc
這裏寫圖片描述

1.2 另存爲xml格式

freemarker操作說明書.xml
這裏寫圖片描述

1.3 用文本編輯器修改《freemarker操作說明書》(.xml)

注:xml格式化後xml結構更清晰,方便查看
得到文本數據,如下圖
這裏寫圖片描述
從圖片中可以看出來,上面的${name}等變量被拆分成了多個部分,那麼現在需要將這樣的被拆分的變量名整合成整體。
整合後如下:
這裏寫圖片描述

注:

文檔中只要是需要填充變量的地方,如果像上面一樣被拆分成多個,都需要手動拼接成塊。 另外對於表格,稍有不同。
如果你的表格的行數不是固定的,那麼可能需要迭代。 freemarker中提供了一種標籤,<#list val_name as
alias>

1.4 保存後,修改文件擴展名爲ftl

ftl爲freemarker的模板格式,之後就可以依據此模板生成word

2 利用freemaker的jar包編程

下面根據上面的模板,創建對應的java工程
這裏寫圖片描述

上面的package(xunhuan)這個包沒有什麼用,讀者自行忽略

工程中的兩個主要的類是WordAction.java和WordUtil.java,代碼如下:

WordAction.java

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import sun.misc.BASE64Encoder;

public class WordAction {

    private String filePath; // 文件路徑
    private String fileOnlyName; // 文件唯一名稱


    public static void main(String []args){
        new WordAction().createWord();
    }

    public String createWord() {
        /** 用於組裝word頁面需要的數據 */
        Map<String, Object> dataMap = new HashMap<String, Object>();

        /** 組裝數據 */
        dataMap.put("name", "張三");

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        dataMap.put("date", sdf.format(new Date()));


        List<Map<String, Object>> newsList = new ArrayList<Map<String, Object>>();
        for (int i = 1; i <= 10; i++) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("title", "標題" + i);
            map.put("address", "博客地址" + (i * 2));
            newsList.add(map);
        }
        dataMap.put("table", newsList);
        dataMap.put("pic", getImageStr());

        /** 文件名稱,唯一字符串 */
        Random r = new Random();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS");
        StringBuffer sb = new StringBuffer();
        sb.append(sdf1.format(new Date()));
        sb.append("_");
        sb.append(r.nextInt(100));

        // 文件唯一名稱
        fileOnlyName = "用freemarker導出的Word文檔_" + sb + ".doc";

        // 文件名稱
        String classpath=Class.class.getClass().getResource("/").getPath();
        System.out.println(classpath);
        filePath = classpath;

        /** 生成word */
        WordUtil.createWord(dataMap, "freemaker操作說明書.ftl", filePath, fileOnlyName);

        return "createWordSuccess";
    }

     private String getImageStr() {
         String imgFile = "C:/Users/KingWang/Desktop/QQ截圖20170707203921.png";
         InputStream in = null;
         byte[] data = null;
         try {
             in = new FileInputStream(imgFile);
             data = new byte[in.available()];
             in.read(data);
             in.close();
         } catch (Exception e) {
             e.printStackTrace();
         }
         BASE64Encoder encoder = new BASE64Encoder();
         return encoder.encode(data);
     }

}

WordUtil.java

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * @Desc:word操作工具類
 */
public class WordUtil {

    /**
     * @Desc:生成word文件
     * @param dataMap
     *            word中需要展示的動態數據,用map集合來保存
     * @param templateName
     *            word模板名稱,例如:test.ftl
     * @param filePath
     *            文件生成的目標路徑,例如:D:/wordFile/
     * @param fileName
     *            生成的文件名稱,例如:test.doc
     */
    @SuppressWarnings("unchecked")
    public static void createWord(Map dataMap, String templateName, String filePath, String fileName) {
        try {
            // 創建配置實例
            Configuration configuration = new Configuration();

            // 設置編碼
            configuration.setDefaultEncoding("UTF-8");

            configuration.setClassForTemplateLoading(WordUtil.class, "/test/");

            // 獲取模板
            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();

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

3,運行結果

這裏寫圖片描述

生成的word之後的截圖

這裏寫圖片描述

4,結語

freemarker的官網手冊地址: http://freemarker.org/docs/index.html

freemarker教程: http://www.cnblogs.com/fx-blog/category/920072.html

對於剛接觸freemarker的你,可能需要了解一下freemarker的dom結構和變量之間的關係。
http://www.zheng-hang.com/chm/freemarker2_3_24/xgui_imperative_learn.html

本示例程序的代碼地址: https://pan.baidu.com/s/1mhLI3Y4

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