1. 程式人生 > >使用FreeMarker自定義匯出word

使用FreeMarker自定義匯出word

根據網上的資料和自己在實踐過程中整理總結一下用freemarker自定義匯出word模板

1. 首先準備好一個Word模板

如圖所示,我定義了一個很簡單的模板,然後將所需變數用${}副號定義,例:${username},如圖所示

定義模板

說明:這裡填寫變數的時候需要按照順序${username}來填寫,如果先填寫了${}再寫username的話,word轉成xml檔案時會出現問題,如圖所示

注意變數書寫順序

2.定義好變數以後將Word另存為XML檔案

將word文件另存為xml檔案,如圖所示

轉存XML

說明:網上有些人說選擇Word XML文件時會有問題,還沒驗證過,所以這裡選擇的是Word 2003 XML

3.編輯開啟XML檔案

我這裡選用Notepad++來開啟的,如圖所示

格式化後的檔案

說明:剛轉換完後,如果Notepad++沒有安裝XML格式化外掛的話,開啟的會是橫著排列的一行,建議用Notepad++自帶的外掛瀏覽器下載XML外掛,如圖所示
下載方法:外掛–>Plugin Manager–>Show Plugin Manager–>Available–>XML Tools–>Install
使用方法:外掛–>XML Tools–>Pretty print(XML only - with line breaks)

未格式化的檔案


下載格式化工具
使用方法

4.編輯XML檔案,另存為ftl檔案

如果需要遍歷出多行資料,則需要在<w:tr>前加上list遍歷,例:<#list newsList as listKey>這裡的newsList只是一個變數名稱,裡面的變數則需要listKey.username,後臺其實就是用的Map<String,List>,具體語法可參照
https://www.baidu.com/link?url=HsppryccH7jtBxyb-VOyQXOHAHlK0faxVuGUK8JBho2L6uKabgCltmsXXNTO_rahbx227tzAsfqu8m2PizwOsq&wd=&eqid=eb38bc4c000014650000000658ae53d5

這裡的結構不難看出<w:tr>為一行,<w:tc>為一列,所以在<w:tr>前後對應的位置加上<#list>標籤即可,編輯完後,將檔名稱直接修改為.ftl檔案即可,例如圖所示

編輯XML檔案

說明: 注意freemarker以及XML的語法結構

5.後臺工具類編寫

這裡用的是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 org.apache.log4j.Logger;

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

/**
 * @ClassName: WordUtil
 * @Description: word模板
 * @author sly.shuai
 * @date2017年2月22日 上午9:55:35
 * @version V1.0
 */
@SuppressWarnings("rawtypes")
public class WordUtil
{
    private final static Logger logger = Logger.getLogger(WordUtil.class);

    /**
     * @Title: createWord
     * @Description: 建立word
     * @param dataMap
     *        word中展示的動態資料,用Map儲存
     * @param templatePath
     *        模板儲存路徑
     * @param templateName
     *        模板名字
     * @param filePath
     *        生成word檔案路徑
     * @param fileName
     *        生成word檔名字 void
     * @throws
     * @變更記錄 2017年2月22日 上午10:13:25 sly.shuai 建立
     */
    public static void createWord(Map dataMap, String templatePath, String templateName, String filePath,
        String fileName) {
        Writer out = null;
        try {
            // 建立配置例項
            Configuration configuration = new Configuration();

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

            // ftl模板檔案
            configuration.setDirectoryForTemplateLoading(new File(templatePath));

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

            // 輸出檔案
            File outFile = new File(filePath + File.separator + fileName);

            // 如果輸出目標資料夾不存在,則建立
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }

            // 將模板和資料模型合併生成檔案
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));

            // 生成檔案
            template.process(dataMap, out);

        } catch (Exception e) {
            logger.error("建立word出錯:" + e);
            throw new RuntimeException("建立word出錯");
        } finally {
            try {
                if (out != null) {
                    // 關閉流
                    out.flush();
                    out.close();
                }
            } catch (Exception e) {
                logger.error("建立word出錯:" + e);
            }
        }
    }
}


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Ignore;
import org.junit.Test;

import com.yihuacomputer.yhcloud.service.util.WordPropertyUtil;
import com.yihuacomputer.yhcloud.service.util.WordUtil;

/**
 * @ClassName: WordTest
 * @Description: word匯出測試
 * @author sly.shuai
 * @date2017年2月22日 上午10:35:32
 * @version V1.0
 */
public class WordTest extends BaseSpringJunit
{
    @Test
    public void createWord() {
        Map<String, Object> dataMap = new HashMap<String, Object>();

        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("username", "使用者名稱" + i);
            map.put("password", "密碼" + (i * 2));
            map.put("phone", "電話" + (i * 3));
            newsList.add(map);
        }
        dataMap.put("newsList", newsList);

        WordUtil.createWord(dataMap, "/word/templatePath/", "test.ftl", "/word/filePath/", "test.doc");
    }
}

執行結果

說明:這裡只是提供了一個公用工具類,dataMap是傳入的資料,用Map封裝List,執行測試用例即可在相應的目錄下找到對應的檔案