不靠GridView,動態匯出Word檔
今天遇到了必須將資料匯出成doc檔
上網查了很久,但大多數的資料都是靠GridView來完成匯出的動作
不然就是使用元件來做,搜尋了老半天,突然看到藍色小舖這篇文章
http://www.blueshop.com.tw/board/show.asp?subcde=BRD20071029161539W2I
雖然跟我要用的word沒啥關係,但突然有了靈感,要是word也能存成xml檔
我再利用replace換掉我要的資料,那不就有辦法動態產生了嗎?
馬上開始紀錄今天的心得。
首先先開一個word檔,最好是有表格的,完成之後才會感動
內容大概是這樣,然後另存新檔為Xml
存完檔之後,用一個好一點的編輯器打開稍微看一下(拜託請不要用記事本,看了眼睛會花)
我用vs2010開,還可以排個版,看起來比較順眼
打開後可以看到就是一堆tag加屬性,內容也不用太在乎,反正我不care。
知道檔案格式之後,再回到本來的word檔,把我們預計要替換掉的文字,更換一下(最好換成不會重複的)
我把內容改成這樣
存檔之後,再開XML來看,搜尋"動態Language” 檢查一下有沒有正確
很好,這次沒有錯。
但我今天下午在試驗的時候,有時候明明是同一句話,卻會分成兩個階層的tag,這時候只好
手動自己修正xml檔囉。還好階層都滿明確的(因為有排版過),所以也不會很難。
準備工作完成之後,開始寫Code
觀念很簡單,就是讀這隻Xml檔,然後用replace換掉我們要換的文字,再寫出成doc就好
首先開個新table,欄位及資料如下
接著開始寫Code
{
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=test.doc");//test是word的檔名
Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8"); //編碼utf-8
Response.ContentType = "application/vnd.ms-word"; //讓瀏覽器知道是word檔
Response.Charset = "";
string myDoc = "";
StreamReader sr = new StreamReader(Server.MapPath("~/App_Data/sample.xml"));//檔案放在App_Data裡面
myDoc = sr.ReadToEnd(); //從頭讀到尾
sr.Close();
//下面開始抓資料
MyDataContext db = new MyDataContext();
var data = db.ExportWords.FirstOrDefault();
if (data != null)
{
//將抓到的資料,替換掉我們剛剛設的文字
myDoc = myDoc.Replace("動態Language", data.Language);
myDoc = myDoc.Replace("動態Read", data.LanguageRead);
myDoc = myDoc.Replace("動態Write", data.LanguageWrite);
myDoc = myDoc.Replace("動態Speak", data.LanguageSpeak);
myDoc = myDoc.Replace("動態Listen", data.LanguageListen);
}
//寫出
Response.Write(myDoc);
Response.End();
return View();
}
簡單吧,完成之後執行,就是下載doc檔,打開內容就已經更換掉囉
這樣就達到我的目的啦,但...如果要多筆的話怎麼辦呢?
這時候又要去看一下Xml檔,去觀察一下xml的階層關係,
找出重複的地方剪下存到另一個檔案(我是存成repeat.txt,要注意的是,記得編碼存成utf-8)
,原來的地方用另一段話取代
repeat.txt
原來的xml的地方,我用"!重複的部分!" 取代
sample.xml
接下來的Code,就是先讀剛剛另外存的重複的檔,跑迴圈替換掉內容,再用字串相加
{
MyDataContext db = new MyDataContext();
var data = db.ExportWords;
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=test.doc");//word檔名
Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
Response.ContentType = "application/vnd.ms-word";
Response.Charset = "";
string myXML = "";
string myText = "";
StreamReader srXML = new StreamReader(Server.MapPath("~/App_Data/sample.xml"));
myXML = srXML.ReadToEnd();
srXML.Close();
//讀出剛剛建立的text,裡頭放等等要重複利用的xml
StreamReader srText = new StreamReader(Server.MapPath("~/App_Data/repeat.txt"));
myText = srText.ReadToEnd();
srText.Close();
if (data != null)
{
StringBuilder 最後要替代掉的字串 = new StringBuilder();
foreach (var item in data)
{
//先把讀出的xml複製一份,接著開始改
string tempdata = myText;
tempdata = tempdata.Replace("動態Language", item.Language);
tempdata = tempdata.Replace("動態Read", item.LanguageRead);
tempdata = tempdata.Replace("動態Write", item.LanguageWrite);
tempdata = tempdata.Replace("動態Speak", item.LanguageSpeak);
tempdata = tempdata.Replace("動態Listen", item.LanguageListen);
//改完加到最後的字串裡面
最後要替代掉的字串.Append(tempdata);
}
//最後替代掉最一開始的那個xml檔"!重複的部分!"
myXML = myXML.Replace("!重複的部分!" , 最後要替代掉的字串.ToString());
}
Response.Write(myXML);
Response.End();
return RedirectToAction("Index");
}
完成之後看看結果。
這樣就成功啦! 是不是超簡單。就是簡單的讀檔,替換,寫出而已。
也許我用的是比較笨的方法,聽同事說,轉存成html也可以,我剛試了一下,果然沒錯
而且看html的階層跟屬性更清楚。
用這個方法,要替換圖片應該也做得到,明天再來試試看!