我們平時在開發過程中經常遇到一些這樣的情況:就是需要把頁面上的一個gridview或table內容以word的形式下載到客戶端.
最快的寫法是以文本的方式生成word檔案,如下:
private void CreateWord(string content)
{
Response.Clear();
Response.Buffer = true;
Response.AppendHeader("Content-Disposition", "attachment;filename=Report.doc");
Response.ContentType = "application/ms-word";
Response.Write(content);
Response.End();
}
protected void Button1_Click(object sender, EventArgs e)
{
StringWriter w = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(w);
gridview1.RenderControl(htw);
CreateWord(w.ToString());
}
// 去掉gridview1必須放在runat='server'的from控件內的錯誤
public override void VerifyRenderingInServerForm(Control control)
{
//base.VerifyRenderingInServerForm(control);
}
這種方法可以說是最簡單,最方便的了,但確不能很好的操作word,如現在客戶需要你給生成的doc文件加上頁眉頁腳該怎麼辦呢?
有人說使用Word的API來操作就行了,確實使用Word的API可以實現這樣的效果,但會出現當你使用完以後並沒有關閉word進程的情況,那麼隨著使用次數的增多服務器上的word進程數也會越來越多.
這下怎麼辦呢?
先來看看這樣的情況:
我們新建一個docx檔,在這個docx檔里面加入頁眉頁腳,然後保存為網頁test.htm,這個時候我們可以看到會成成一個text.htm文件和一個test.files的目錄,在test.files目錄下存在著filelist.xml,header.htm,themedata.thmx,colorschememapping.xml四個文件,好了,我們現在將test.htm改名為test.doc文件再打開這個新的doc文件,可以看到原來的頁眉頁腳還存在,這就說明doc文件的頁眉頁腳文件是可以自己定制的,再來我們使用記事本打開test.doc文件,將里面的
<link rel=File-List href="XX.files/filelist.xml">
<link rel=themeData href="XX.files/themedata.thmx">
<link rel=colorSchemeMapping href="XX.files/colorschememapping.xml">
一個一個的去掉,看哪些會影響到test.doc文件的頁眉頁腳,結果發現
<link rel=File-List href="XX.files/filelist.xml">
這個文件去掉會,那麼每次打開都現彈出一個對話框了,所以還是不要去掉得好..
另分析test.doc可以看得出header.htm就是控制doc文件頁眉頁腳的,所以也是必不可少的.
好了,我們現在可以得出如需給doc添加頁眉頁腳的話,至少需要附加兩個文件,那麼我們怎麼實現呢?
1. 新建一個word檔案,設置好頁眉頁腳,將這個word檔案另存為網頁doc.htm
2. 刪除themedata.thmx,colorschememapping.xml文件
3. 將filelist.xml的內容改為
<xml xmlns:o="urn:schemas-microsoft-com:office:office">
<o:File HRef="header.htm"/>
<o:File HRef="filelist.xml"/>
</xml>
4. 將header.htm文件中的<link id=Main-File rel=Main-File href="../doc.htm">去掉
5. 將doc.htm文件中的
<link rel=themeData href="doc.files/themedata.thmx">
<link rel=colorSchemeMapping href="doc.files/colorschememapping.xml">
去掉
6. 將doc.htm文件中的所有的doc.files/改名為<doc_fileName/>.files/
7. 將<div class=Section1>中的內容清空加上<doc_content />
8. 將doc.files目錄改名為files
9. 以上1 ~ 8步為模板的制作, 制作完成後將files文件夾拷貝到專案目錄~/DownFiles下,將doc.htm文件拷貝到~/DownFiles/files目錄下
10. 接下來的工作就是生成doc文件了,這里的工作原理是:先在服務器端成了doc文件,然後將doc文件和與doc文件相關的header.htm,filelist.xml打包下載,這里當客戶下載解壓後打開doc文檔就可以看到doc文檔中的頁眉頁腳了
11. asp.net 代碼如下:
private string _modelPath = Server.MapPath("~/DownFiles");
private string Right(string str)
{
str = "00" + str;
return str.Substring(str.Length-2);
}
// 取得文件名
private string GetFileName()
{
Random randow = new Random();
string fileName = DateTime.Now.Year.ToString() + Right(DateTime.Now.Month.ToString()) + Right(DateTime.Now.Day.ToString());
fileName += Right(DateTime.Now.Hour.ToString()) + Right(DateTime.Now.Minute.ToString()) + Right(DateTime.Now.Second.ToString());
fileName += randow.Next(10000).ToString();
return fileName;
}
//創建doc文件
private void CreateDoc(string content)
{
string fileName = GetFileName();
while (Directory.Exists(String.Format(_modelPath + "/{0}.files", fileName)) || File.Exists(String.Format(_modelPath + "/{0}.doc", fileName)))
{
fileName = GetFileName();
}
string pathName = String.Format(_modelPath + "/{0}.files", fileName);
string filePath = String.Format(_modelPath + "/{0}.doc", fileName);
DirectoryInfo dir = Directory.CreateDirectory(pathName);
File.Copy(_modelPath + "/files/filelist.xml", pathName + "/filelist.xml");
File.Copy(_modelPath + "/files/header.htm", pathName + "/header.htm");
using (StreamWriter doc = new StreamWriter(filePath))
{
string docContent = String.Empty;
using (StreamReader reader = new StreamReader(_modelPath + "/files/doc.htm"))
{
docContent = reader.ReadToEnd();
reader.Close();
}
docContent = docContent.Replace("<doc_fileName/>", fileName);
doc.Write(docContent.Replace("<doc_content />", content));
doc.Close();
}
}
12. 這個時候我們已經在~/DownFiles目錄下生成了對應的doc文件及這個doc文件相關的目錄了,現在只需要將這兩者打包下載即可..