java Web項目中通過FreeMarker生成指定格式的Word文檔

1.首先需要借助office將需要的word模板轉(zhuǎn)成xml文件

在此操作之前需要將需要填入內(nèi)容的地方用${name}進(jìn)行占位,其中name為屬性值侦锯,可以為map的key。
如下圖:

Paste_Image.png

其中keycodeunitname為我接下來需要填入的相應(yīng)框中的一個查詢結(jié)果的類中的兩個屬性,當(dāng)然為了處理的方便我也將它們存入了一個map

設(shè)計好模板后然后用word(ps:WPS不行)的另存為功能猩谊,存為xml文件。

2.將xml文件轉(zhuǎn)為ftl文件

接下來我們需要處理一下轉(zhuǎn)成的xml文件祭刚,因為有時這些占位符的內(nèi)容會被一對格式分開牌捷,這樣的話freemarker引擎就無法正常解析了
需要成為如下的樣子,也就是保持占位符還是書寫時的樣子

Paste_Image.png

修改完畢后保存涡驮,然后將其另存為ftl格式的文件

3.引入freemarkerjar包

可去如下地址下載:
http://freemarker.org/freemarkerdownload.html

4.主要代碼

Paste_Image.png

上圖是我的web程序有關(guān)導(dǎo)出word的主要部分暗甥,jar放在lib下
這里我用的struts2當(dāng)然servlet springmvc也是可以的

/**
     * 將新增的查封出一個審批表
     * @throws IOException 
     */
    public void exportCFw() throws IOException {
        Session session = SessionHelper.currentSession();
        HttpServletRequest req = ServletActionContext.getRequest();
        HttpServletResponse response=ServletActionContext.getResponse();
        Map<String, Object> map = new HashMap<String, Object>();
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            cfkId="0000C3C1-DC90-4A3A-A5B3-3104623C64C5";
            req.setCharacterEncoding("utf-8");
            Query query = session.createQuery("from Cfk c where c.proid='" + cfkId + "'");
            Cfk cfk = (Cfk) query.list().get(0);
            // 為了通用性將model類存儲為map
            map = ConvertModel2Map(map, cfk);
            // 調(diào)用工具類WordGenerator的createDoc方法生成Word文檔  
            file=WordGenerator.createDoc(map, "cfk");
            fin=new FileInputStream(file);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            response.setHeader("Content-Disposition", "attachment;filename=cfk.doc");
            out=response.getOutputStream();
            byte[] buffer=new byte[512];
            int byteToRead=-1;
            while((byteToRead=fin.read(buffer))!=-1){
                out.write(buffer, 0, byteToRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(fin != null) fin.close();  
            if(out != null) out.close();  
            if(file != null) file.delete(); // 刪除臨時文件  
            
        }

    }

    private Map<String, Object> ConvertModel2Map(Map<String, Object> map, Object model) {
        Field[] fields = model.getClass().getDeclaredFields();// 獲取實體類的所有屬性,返回Field數(shù)組
        try {
            for (Field field : fields) { // 遍歷所有屬性
                String name = field.getName(); // 獲取屬性的名字
                field.setAccessible(true);// 設(shè)置當(dāng)前對象對model私有屬性的訪問權(quán)限
                Object value = field.get(model);// 獲取屬性值
                if(value==null){
                    value="";
                }
                map.put(name, value);
            }
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return map;
    }
package com.fquery.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateNotFoundException;

public class WordGenerator {
    private static Configuration configuration=null;
    private static Map<String, Template> allTemplates = null;  
    static{
        configuration=new Configuration();
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(WordGenerator.class, "/com/fquery/ftl");
        allTemplates=new HashMap<String, Template>();
        try {
            allTemplates.put("cfk", configuration.getTemplate("cfk.ftl"));
        
        } catch (IOException e) {
            e.printStackTrace();
             throw new RuntimeException(e);
        }
    }
    
    private WordGenerator() {  
        throw new AssertionError();  
    }
     public static File createDoc(Map<?, ?> dataMap, String type) {  
            String name = "temp" + (int) (Math.random() * 100000) + ".doc";  
            File f = new File(name);  
            Template t = allTemplates.get(type);  
            try {  
                // 這個地方不能使用FileWriter因為需要指定編碼類型否則生成的Word文檔會因為有無法識別的編碼而無法打開  
                Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");  
                t.process(dataMap, w);  
                w.close();  
            } catch (Exception ex) {  
                ex.printStackTrace();  
                throw new RuntimeException(ex);  
            }  
            return f;  
        }  

}

struts2

        <action name="exportCFw" class="com.fquery.action.Export" method="exportCFw">
        </action>

前端調(diào)用action
這里為了測試方便捉捅,直接給了查詢指定的條件撤防,實際中應(yīng)該是從前臺傳過去

function exportCF3(){
         location.href="exportCFw.action";    
     }

本文參考如下文章,特此感謝作者:http://blog.csdn.net/jackfrued/article/details/39449021

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棒口,一起剝皮案震驚了整個濱河市寄月,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌无牵,老刑警劉巖漾肮,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茎毁,居然都是意外死亡克懊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門七蜘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谭溉,“玉大人,你說我怎么就攤上這事崔梗∫怪唬” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵蒜魄,是天一觀的道長扔亥。 經(jīng)常有香客問我,道長谈为,這世上最難降的妖魔是什么旅挤? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮伞鲫,結(jié)果婚禮上粘茄,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好柒瓣,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布儒搭。 她就那樣靜靜地躺著,像睡著了一般芙贫。 火紅的嫁衣襯著肌膚如雪搂鲫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天磺平,我揣著相機與錄音魂仍,去河邊找鬼。 笑死拣挪,一個胖子當(dāng)著我的面吹牛擦酌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播菠劝,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼赊舶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赶诊?” 一聲冷哼從身側(cè)響起锯岖,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甫何,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遇伞,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡辙喂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸠珠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巍耗。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖渐排,靈堂內(nèi)的尸體忽然破棺而出炬太,到底是詐尸還是另有隱情,我是刑警寧澤驯耻,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布亲族,位于F島的核電站,受9級特大地震影響可缚,放射性物質(zhì)發(fā)生泄漏霎迫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一帘靡、第九天 我趴在偏房一處隱蔽的房頂上張望知给。 院中可真熱鬧,春花似錦、人聲如沸涩赢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筒扒。三九已至怯邪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霎肯,已是汗流浹背擎颖。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留观游,地道東北人搂捧。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像懂缕,于是被迫代替她去往敵國和親允跑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

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

  • spring mvc 工作機制(原理): DispatcherServlet主要用作職責(zé)調(diào)度工作搪柑,本身主要用于控制...
    java大濕兄閱讀 1,891評論 5 24
  • 目錄 前言 FTL指令規(guī)則 插值規(guī)則 表達(dá)式 FreeMarker的常用指令 高級方法 前言 FreeMarker...
    garyond閱讀 4,693評論 0 8
  • FreeMarker的模板文件并不比HTML頁面復(fù)雜多少,FreeMarker模板文件主要由如下4個部分組成: 1...
    年輕小伙程序員閱讀 2,965評論 0 5
  • 開心一笑 感冒了很難受聋丝,她悶在被窩里給男朋友發(fā)短信"我感冒了..."并決定如果對方回答"多喝點水"就一腳踹了他。過...
    架構(gòu)師啟示錄閱讀 14,974評論 8 13
  • 好友今天又朝我哭訴吐槽自己的男友多么多么不愛惜自己工碾,還要給喜歡過的女生天天螞蟻森林澆水弱睦。 我一向是讓她自己決定感情...
    NUMBLER閱讀 177評論 0 0