Freemarker java導(dǎo)出word文檔


本文記錄使用freemarker技術(shù)在web后臺導(dǎo)出word文檔的過程柑营。
整個過程分為以下幾步。后面會用一個例子加以說明。

  • 生成word模版
  • 修改ftl模版
  • 填充數(shù)值繁成,導(dǎo)出word模板
  1. 生成Word模板
    生產(chǎn)word模版主要分為兩步,一個是把word文檔另存為xml文檔己儒,注意是另存為崎岂。然后把xml文檔后綴改為ftl文檔。在編輯word文檔的時候闪湾,最好把需要填充或替換的位置冲甘,以一種特殊的標(biāo)識符替代。不然后面編輯ftl模版就很痛苦途样。下面舉個例江醇。


    原始模版.png

    里面的Tb1開頭就是我們需要替換的占位字段,這里的占位字段不要太復(fù)雜何暇,比如${Tb123}陶夜,因為后面另存為xml后,多種類型的字符會發(fā)生拆分裆站。

  2. 編輯ftl模版
    在文本編輯器里面打開ftl模版条辟。然后搜索在word里填充的占位符。然后替換成后面能被替換的格式宏胯。比如羽嫡,把Tb111,替換成${tb111}肩袍。這里可能原始的占位符發(fā)生了截斷杭棵,比如本來是Tb111,但是在ftl模版里面成了Tb1~~<dafda<11氛赐。這時就要把中間的那些刪掉颜屠。最后替換后的格式就是標(biāo)準(zhǔn)的可替換參數(shù)。


    ftl模版.png
  3. 修改代碼
    這塊基本邏輯就是生產(chǎn)參數(shù)鹰祸,填充到模板甫窟。
       <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class WordExportUtil {
    private static Logger LOGGER = LoggerFactory.getLogger(WordExportUtil.class);
    
    private static WordExportUtil service = null; 

    private WordExportUtil() {
        super();
    }
    
    public static WordExportUtil getInstance() {
        if(service == null) {
            synchronized(WordExportUtil.class){
                if(service == null) {
                    service = new WordExportUtil();
                }
            }
        }
        return service;
    }

    
    
    /**
     * 
     * @param templateFilePath  eg: /template/test/test.ftl
     * @param dataMap
     * @param exportFilePath  eg: /tmp/test/test123.doc
     * @param loadType  設(shè)置路徑加載方式。1-絕對路徑蛙婴,2-項目相對路徑
     * @return
     * @throws Exception 
     */
    public File createDocFile(String templateFilePath,Map<String, Object> dataMap, String exportFilePath, int loadType) throws Exception {
        Template t = null;
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");
        try {
            templateFilePath = pathReplace(templateFilePath); 
            String ftlPath = templateFilePath.substring(0, templateFilePath.lastIndexOf("/"));
            if(loadType == 1) {
                configuration.setDirectoryForTemplateLoading(new File(ftlPath)); // FTL文件所存在的位置
            }else {
                configuration.setClassForTemplateLoading(this.getClass(), ftlPath);//以類加載的方式查找模版文件路徑
            }
            

            String ftlFile = templateFilePath.substring(templateFilePath.lastIndexOf("/")+1);
            t = configuration.getTemplate(ftlFile); // 模板文件名
            
            File outFile = new File(exportFilePath);
            Writer out = null;
            
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            
            t.process(dataMap, out);
        } catch (Exception e) {
            LOGGER.error("導(dǎo)出word文檔出錯", e);
            throw e;
        }
        
        return null;
    }
    
    /**
     *  把路徑的\替換成/
     * @param path
     * @return
     */
    private String pathReplace(String path) {
        while(path != null && path.contains("\\")) {
            path = path.replace("\\", "/");
        }
        return path;
    }
    
    public static void main(String[] args) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        getData(dataMap);
        String templateFile = "C:\\Users\\luke\\Desktop\\tmpStore\\exportTemplate.ftl";
        String exportFile = "C:\\Users\\luke\\Desktop\\tmpStore\\luedf.doc";
                
        try {
            WordExportUtil.getInstance().createDocFile(templateFile, dataMap, exportFile, 1);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 測試用的
     * @param dataMap
     */
    public static void getData(Map<String, Object> dataMap) {
        dataMap.put("tb11", "10");
        dataMap.put("tb12", "2012");
        dataMap.put("tb13", "2");
        dataMap.put("tb111", "13");
        dataMap.put("tb112", "13");
        dataMap.put("tb113", "13");
        dataMap.put("tb114", "13");
        dataMap.put("tb115", "13");
        dataMap.put("tb116", "13");
        dataMap.put("tb117", "13");
        dataMap.put("tb118", "13");
        dataMap.put("tb119", "13");
        dataMap.put("tb1110", "13");
        dataMap.put("tb1111", "13");
    }
}

最后導(dǎo)出的文檔樣式如下粗井。


導(dǎo)出文檔.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市街图,隨后出現(xiàn)的幾起案子浇衬,更是在濱河造成了極大的恐慌,老刑警劉巖餐济,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耘擂,死亡現(xiàn)場離奇詭異,居然都是意外死亡絮姆,警方通過查閱死者的電腦和手機醉冤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門秩霍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚁阳,你說我怎么就攤上這事铃绒。” “怎么了螺捐?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵颠悬,是天一觀的道長。 經(jīng)常有香客問我定血,道長赔癌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任澜沟,我火速辦了婚禮灾票,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘倔喂。我一直安慰自己铝条,他們只是感情好靖苇,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布席噩。 她就那樣靜靜地躺著,像睡著了一般贤壁。 火紅的嫁衣襯著肌膚如雪悼枢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天脾拆,我揣著相機與錄音馒索,去河邊找鬼。 笑死名船,一個胖子當(dāng)著我的面吹牛绰上,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播渠驼,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼蜈块,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了迷扇?” 一聲冷哼從身側(cè)響起百揭,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜓席,沒想到半個月后器一,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡厨内,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年碰逸,在試婚紗的時候發(fā)現(xiàn)自己被綠了琅拌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片详瑞。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖癣亚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情获印,我是刑警寧澤述雾,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站兼丰,受9級特大地震影響玻孟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鳍征,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一黍翎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艳丛,春花似錦匣掸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戴差,卻和暖如春送爸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暖释。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工袭厂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人球匕。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓纹磺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親亮曹。 傳聞我的和親對象是個殘疾皇子橄杨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容