項目開發過程當中,咱們要把數據以各類各樣的形式展示給客戶。把數據以文檔的形式展示給客戶相信是一種比較頭疼的問題,若是沒有好的方法會html
使得個人開發繁瑣,並且知足不了客戶的需求。接下來我會經過兩種開發方式介紹如何將數據輸出到Word 文檔上。我會分兩篇文章介紹,第一篇前端
介紹不使用插件的狀況下操做word,第二篇文章將介紹一種強大的插件操做word。下面開始第一篇文章。[本次實例源代碼從這裏下載]後端
文章梗概:服務器
♦ 不使用模板將數據輸出到 wordapp
♦ 輸出數據到 word 在後端設置輸出內容ide
♦ 輸出數據到 word 在前端設置輸出內容post
♦ 經過把word另存爲html 文件的形式作成模板輸出到word字體
♦ 經過把word另存爲mht 文件的形式作成模板輸出到wordui
前端定義兩個服務器按鈕:
1 <div id="container" style=""> 2 不利用模板:<br /> 3 <br /> 4 <asp:Button ID="CreateWordBehind" runat="server" Text="輸出數據到word(後臺設置內容)" OnClick="CreateWordBehind_Click" /> 5 <asp:Button ID="CreateWordFront" runat="server" Text="輸出數據到word(前臺設置內容)" OnClick="CreateWordFront_Click" /> 6 <hr /> 7 </div>
後端代碼輸出到word,代碼很簡單隻要設置輸出頭爲word,而輸出的內容放到 StringBuilder 裏,而且經過 StringBuilder實例,去設置要輸出的內容,包括字體、顏色....
1 /// <summary> 2 /// 輸出數據到word(後臺設置內容) 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 protected void CreateWordBehind_Click(object sender, EventArgs e) 7 { 8 HttpContext.Current.Response.Clear(); 9 HttpContext.Current.Response.Buffer = true; 10 HttpContext.Current.Response.Charset = ""; 11 12 // 設置輸出頭 13 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + System.Web.HttpUtility.UrlEncode("CreateWord", System.Text.Encoding.UTF8) + ".doc"); 14 15 // 設置輸出的編碼格式 16 HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Default; 17 18 // Response.ContentType指定文件類型 能夠爲application/ms-excel || application/ms-word || application/ms-txt || application/ms-html 19 // 由於是輸出word 因此這裏就指定爲 application/ms-word 20 HttpContext.Current.Response.ContentType = "application/ms-word"; 21 22 // 定義StringBuilder 把要輸出的內容寫到裏面,而且能夠設置字體、顏色、大小等... 23 StringBuilder sb = new StringBuilder(); 24 sb.AppendLine("<div style='text-align:center;font-size:18px;font-weight:bold;'>導出數據到word</div>"); 25 sb.AppendLine("這是導出到word的數據<br />"); 26 sb.AppendLine("<span style='color:blue;'>這是導出到word的數據</span>"); 27 28 HttpContext.Current.Response.Output.Write(sb); 29 HttpContext.Current.Response.Flush(); 30 HttpContext.Current.Response.End(); 31 }
運行、點擊按鈕、打開word文檔,效果以下:
前端設置輸出的html內容。以輸出一個表格爲例。其中有兩個div 標記了runat="server",這樣後臺就能夠取到這個id,用途一會介紹。
1 <div id="WordContent" runat="server"> 2 <div runat="server" id="title">表頭</div> 3 <table border="1" style="width:400px;line-height: 25px;"> 4 <tr style="width:400px; height:25px;"> 5 <td> 6 編號 7 </td> 8 <td> 9 姓名 10 </td> 11 <td> 12 成績 13 </td> 14 </tr> 15 <tr style="width:400px; height:25px;"> 16 <td> 17 </td> 18 <td> 19 </td> 20 <td> 21 </td> 22 </tr> 23 </table> 24 </div>
至此前端的所有代碼以下:
1 <form id="form1" runat="server"> 2 <div id="WordContent" runat="server"> 3 <div runat="server" id="title">表頭</div> 4 <table border="1" style="width:400px;line-height: 25px;"> 5 <tr style="width:400px; height:25px;"> 6 <td> 7 編號 8 </td> 9 <td> 10 姓名 11 </td> 12 <td> 13 成績 14 </td> 15 </tr> 16 <tr style="width:400px; height:25px;"> 17 <td> 18 </td> 19 <td> 20 </td> 21 <td> 22 </td> 23 </tr> 24 </table> 25 </div> 26 <div id="container" style=""> 27 不利用模板:<br /> 28 <br /> 29 <asp:Button ID="CreateWordBehind" runat="server" Text="輸出數據到word(後臺設置內容)" OnClick="CreateWordBehind_Click" /> 30 <asp:Button ID="CreateWordFront" runat="server" Text="輸出數據到word(前臺設置內容)" OnClick="CreateWordFront_Click" /> 31 <hr /> 32 </div> 33 </form>
後端代碼輸出到word的代碼和就是把以前的StringBuilder 換成了StringWriter,StringWriter的信息其實也是經過Stringbulider存儲的。另外加上一個
HtmlTextWriter對象,HtmlTextWriter能夠把前端渲染後的頁面以流的形式輸出。
這是候咱們就能夠看出在前端html中標記的id的用途了,這樣就能夠把id標記爲WordContent的裏面的內容所有輸出到word,而其餘的內容也不會輸出到word上了。
又因爲前端html中id標記了title的div標籤在後臺設置了title.Style.Add(HtmlTextWriterStyle.Display, "none");因此它也不會被輸出到word上。
1 /// <summary> 2 /// 輸出數據到word(前臺設置內容) 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 protected void CreateWordFront_Click(object sender, EventArgs e) 7 { 8 HttpContext.Current.Response.Clear(); 9 HttpContext.Current.Response.Buffer = true; 10 HttpContext.Current.Response.Charset = ""; 11 12 // 設置輸出頭 13 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + System.Web.HttpUtility.UrlEncode("CreateWord", System.Text.Encoding.UTF8) + ".doc"); 14 15 // 設置輸出的編碼格式 16 HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Default; 17 18 // Response.ContentType指定文件類型 能夠爲application/ms-excel || application/ms-word || application/ms-txt || application/ms-html 19 // 由於是輸出word 因此這裏就指定爲 application/ms-word 20 HttpContext.Current.Response.ContentType = "application/ms-word"; 21 22 // 定義輸出流,其信息也是存儲在StringBuilder中的 23 System.IO.StringWriter oStringWriter = new System.IO.StringWriter(); 24 25 // 定義一個服務器控件輸出流(能夠把前端渲染後的頁面以流的形式輸出) 26 System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter); 27 28 // 控制前端的樣式 (HtmlTextWriterStyle 枚舉用來控制 顯示、字體、大小、顏色...) 29 title.Style.Add(HtmlTextWriterStyle.Display, "none"); 30 31 // 這樣會把前端的整個頁面輸出,因爲有些其餘元素不須要輸出,因此註釋 32 //this.RenderControl(oHtmlTextWriter); 33 34 // 指定咱們前端標記要輸出的容器,容器包含的內容均可以輸出 35 this.WordContent.RenderControl(oHtmlTextWriter); 36 37 HttpContext.Current.Response.Output.Write(oStringWriter); 38 HttpContext.Current.Response.Flush(); 39 HttpContext.Current.Response.End(); 40 }
運行、點擊按鈕發現報錯,提示"只能在執行 Render() 的過程當中調用 RegisterForEventValidation;"這個錯誤的緣由就是懷疑經過post方法發送惡意的數據,解決方法:
在當前aspx頁面頭部加上:EnableEventValidation="false",默認爲true。
1 <%@ Page Language="C#" AutoEventWireup="true" EnableEventValidation="false" CodeBehind="OperateWord.aspx.cs" 2 Inherits="OperateWordPro.OperateWordDemo1.OperateWord" %>
再運行、點擊按鈕、打開word,效果以下(固然需求不可能那麼簡單,具體輸出的樣式就要在html中慢慢的調整了):
由於若是用前面的方式,將數據都是本身拼接的,包括樣式全是本身控制,難度將很是大,而且效果也很讓到客戶的滿意(如:要求頁眉、頁腳)。因此若是可以程序直接讀取word模板把要輸出的內容填充進去將會大大的縮短咱們的時間,最主要的是版式不用咱們太關心。
一、 經過把word另存爲html 文件的形式作成模板輸出到word
把word文檔作成模板的思路就是把word文檔保存爲html程序能夠直接讀取的形式。因爲篇幅的問題,具體把word另存爲html的細節能夠請參考這篇博文。下面有這樣一個結構的word文檔須要輸出,經過用讀取模板的形式咱們只要把下面幾個站位符替換掉就能夠了(如,要輸出名字的地方加上了{name}...),思路很簡單。
前臺html代碼:
1 利用模板輸出到word:<br /><br /> 2 <asp:Button ID="CreateWordByHtmlTemplate" runat="server" Text="經過htm模板生成Word" OnClick="CreateWordByHtmlTemplate_Click" /> 3 <asp:Button ID="CreateWordBymhtTemplate" runat="server" Text="經過mht模板生成Word" OnClick="CreateWordBymhtTemplate_Click" />
在項目中添加一個Document文件夾,將模板文件「通知.html」拷貝到這個問價夾下。
下面是後臺代碼:
1 /// <summary> 2 /// 經過htm模板生成Word 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 protected void CreateWordByHtmlTemplate_Click(object sender, EventArgs e) 7 { 8 // 獲取模板的路徑 經過ExprotToWord處理返回 字符串 9 string strWord = DealTemplate(Server.MapPath("../Document/通知.html")); 10 11 Response.ContentEncoding = System.Text.Encoding.Default; 12 Response.ClearContent(); 13 Response.ClearHeaders(); 14 Response.AddHeader("content-disposition", "attachment;filename=合同.doc"); //必須的 15 Response.AddHeader("Content-type", "application"); 16 Response.ContentType = "application/ms-html"; 17 Response.ContentEncoding = System.Text.Encoding.Default; 18 19 Response.Write(strWord); 20 Response.Flush(); 21 Response.Close(); 22 } 23 24 /// <summary> 25 /// 處理模板 返回處理結果 26 /// </summary> 27 /// <param name="templatePath"></param> 28 /// <returns></returns> 29 public string DealTemplate(string templatePath) 30 { 31 StringBuilder sb = new StringBuilder(1024); 32 33 // 讀取文檔內容並轉換成流的形式 編碼爲默認編碼 34 StreamReader sr = new StreamReader(templatePath, Encoding.Default); 35 36 // 將流轉換成字符串加進StringBuilder中 37 sb.Append(Encoding.Default.GetString(Encoding.Default.GetBytes(sr.ReadToEnd()))); 38 39 // 把文檔中咱們設置的標誌位換成咱們想要的內容 40 sb.Replace("{name}", "張三"); 41 sb.Replace("{orderNumber}", "ooxx124512"); 42 sb.Replace("{tel}", "1383838383"); 43 44 return sb.ToString(); 45 }
運行、點擊按鈕、打開word,效果以下
二、 經過把word另存爲mht 文件的形式作成模板輸出到word
經過把word存儲爲html的形式解決了大量手工拼接數據和word的基本版式問題,可是若是這個word中含有圖片和頁眉頁腳就沒法經過這種方式處理了,由於html存儲的是單文件,是和圖片這些「其餘元素」分開的。因此若是仍是要經過模板的方式解決那麼這個模板要含有文字、圖片、頁眉設置、頁腳設置。通過一番測試,發現把word另存爲.mht的方式能夠解決這個問題。上網查了資料說.mht就是htm和圖片等的複合文件。那麼咱們繼續吧。
製做一個word在上一個word的基礎上添加了一個含有圖片的word:
把這個word另存爲"通知2.mht",並複製到Document文件夾下。
後臺代碼和上面代碼同樣,只是換了個模板而已,可是編碼格式要作微調,紅字部分標註了:
1 /// <summary> 2 /// 經過mht模板生成Word 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 protected void CreateWordBymhtTemplate_Click(object sender, EventArgs e) 7 { 8 // 獲取模板的路徑 經過ExprotToWord處理返回 字符串 9 string strWord = DealTemplate(Server.MapPath("../Document/通知2.mht")); 10 11 Response.ContentEncoding = System.Text.Encoding.Default; 12 Response.ClearContent(); 13 Response.ClearHeaders(); 14 Response.AddHeader("content-disposition", "attachment;filename=合同.doc"); //必須的 15 Response.AddHeader("Content-type", "application"); 16 Response.ContentType = "application/ms-html"; 17 Response.ContentEncoding = System.Text.Encoding.Default; 18 19 Response.Write(strWord); 20 Response.Flush(); 21 Response.Close(); 22 } 23 24 /// <summary> 25 /// 處理模板 返回處理結果 26 /// </summary> 27 /// <param name="templatePath"></param> 28 /// <returns></returns> 29 public string DealTemplate(string templatePath) 30 { 31 StringBuilder sb = new StringBuilder(1024); 32 33 // 讀取文檔內容並轉換成流的形式 此處編碼要設置爲UTF8 34 StreamReader sr = new StreamReader(templatePath, Encoding.UTF8); 35 36 // 將流轉換成字符串加進StringBuilder中 37 sb.Append(Encoding.Default.GetString(Encoding.Default.GetBytes(sr.ReadToEnd()))); 38 39 // 把文檔中咱們設置的標誌位換成咱們想要的內容 40 sb.Replace("{name}", "張三"); 41 sb.Replace("{orderNumber}", "ooxx124512"); 42 sb.Replace("{tel}", "1383838383"); 43 44 return sb.ToString(); 45 }
運行、點擊按鈕、打開word效果以下:
總結
以上文章介紹的是沒有經過組件將數據輸出到word上,若是客戶需求簡單,格式不是太難控制徹底能夠根據文章中經過模板的方式輸出到word。其中最容易出問題的我認爲就是編碼問題,模板格式不同可能程序中的編碼格式也要作相應的調整。
雖然以上方式演示沒問題,可是實際開發中需求並無上面的例子簡單。若是客戶要求的word版式比較複雜,且數據要循環輸出那麼經過上面任何一種方式都很差解決。可是經過第三方組件就能夠解決這種問題,若是這個組件用熟練了,上面的方式我相信你幾乎不會用的。下一篇文章將介紹用第三方組件的方式把內容輸出到word。