使用FreeMarker自定義匯出word
根據網上的資料和自己在實踐過程中整理總結一下用freemarker自定義匯出word模板
1. 首先準備好一個Word模板
如圖所示,我定義了一個很簡單的模板,然後將所需變數用${}
副號定義,例:${username},如圖所示
說明:這裡填寫變數的時候需要按照順序
${username}
來填寫,如果先填寫了${}再寫username的話,word轉成xml檔案時會出現問題,如圖所示
2.定義好變數以後將Word另存為XML檔案
將word文件另存為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檔案即可,例如圖所示
說明: 注意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,執行測試用例即可在相應的目錄下找到對應的檔案