關鍵詞:ASP.NET; C#; Word; 自動化; VBA; COM; 死進程;
1. 創建工程
在ASP.NET裏操做Word的第一步就是添加COM引用到你的工程裏,經過右鍵點擊「解決方案資源管理器」的「引用」,添加引用。選擇COM選項卡,添加Microsoft Word 12.0 Object Library(其中12.0是Word版本號,根據當前電腦上安裝的Word版本肯定)。 ASP.Net會自動生成Word的COM包裝類程序集添加到應用程序目錄裏。
2. 代碼邏輯
在服務器端訪問本地存在的Word文件,並根據他新建一個文件,利用Word的標籤訂位賦值。客戶端瀏覽器經過文件連接訪問到這個新生成的Word文件。
具體代碼以下:
private void Page_Load(object sender, System.EventArgs e)
{
// 在此處放置用戶代碼以初始化頁面
object Missing = Type.Missing;
//取得Word文件路徑
string strTemp = "doc/test.doc";
//新Word文件保存路徑
string newFileName = "doc/test2.doc";
//建立一個名爲WordApp的組件對象
Application WordApp = new ApplicationClass();
//必須設置爲不可見
WordApp.Visible = false;
try
{
//建立以strTemp爲模板的文檔
object oTemplate = Server.MapPath(strTemp);
Document WordDoc = WordApp.Documents.Add(ref oTemplate, ref Missing,ref Missing, ref Missing);
WordDoc.Activate();
//對標籤"Title"進行填充
string strBM = "Title";
object objBM = strBM;
if(WordApp.ActiveDocument.Bookmarks.Exists(strBM) == true)
{
WordApp.ActiveDocument.Bookmarks.get_Item(ref objBM).Select();
WordApp.Selection.TypeText("公文標題");
}
//保存爲新文件
object oNewFileName = Server.MapPath(newFileName);
WordDoc.SaveAs(ref oNewFileName, ref Missing,ref Missing, ref Missing,ref Missing,ref Missing,ref Missing,
ref Missing,ref Missing,ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing);
WordDoc.Close(ref Missing, ref Missing, ref Missing);
WordApp.Quit(ref Missing, ref Missing, ref Missing);
}
catch(Exception Ex)
{
throw new Exception(Ex.Message);
}
//瀏覽器彈出下載框
Page.RegisterStartupScript("", "<script>window.open('"+newFileName+"')</script>");
}
運行前,工程目錄下建文件夾doc, doc裏新建一個test.doc,內容本身定,手動插入一個名爲「Title」的標籤。
此代碼在 VS.Net2003+WinXP+Office2007 下運行經過。
若是你在運行時出現下面的調試錯誤:
拒絕訪問。
說明: 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息,以瞭解有關該錯誤以及代碼中致使錯誤的出處的詳細信息。
異常詳細信息: System.UnauthorizedAccessException: 拒絕訪問。
ASP.NET 未被受權訪問所請求的資源。請考慮授予 ASP.NET 請求標識訪問此資源的權限。ASP.NET 有一個在應用程序沒有模擬時使用的基進程標識(一般,在 IIS 5 上爲 {MACHINE}\ASPNET,在 IIS 6 上爲網絡服務)。若是應用程序正在經過 <identity impersonate="true"/> 模擬,則標識將爲匿名用戶(一般爲 IUSR_MACHINENAME)或通過身份驗證的請求用戶。
若要授予 ASP.NET 對文件的寫訪問權,請在資源管理器中右擊該文件,選擇「屬性」,而後選擇「安全」選項卡。單擊「添加」添加適當的用戶或組。突出顯示 ASP.NET 賬戶,選中所需訪問權限對應的框。
出現以上錯誤時,代表ASP.NET進程沒法對具備用戶界面的Word進行自動化調用,必須由一個擁有桌面的用戶角色來啓動ASP.NET進程。解決方法:在Web.config文件的System.Web節裏添加<identity impersonate="true" userName="*" password="*" />,其中userName和password是你電腦裏的Windows登陸帳戶。
3. 方案總結
Web服務器端自動化調用Word在實際應用中發現的問題:
1、開發難易度:Word自動化中的調用都基於VBA語法,須要開發者對VBA很熟悉。VBA中Word對象衆多、邏輯複雜,COM調用方式難於理解。通常開發者不多接觸VBA和COM,所以開發起來比較麻煩。
2、代碼安全性:上述運行錯誤「拒絕訪問」的最佳解決方法就是添加<identity impersonate="true" userName="*" password="*" />,不過缺點是在Web.config裏能夠看到你的帳戶密碼,儘管Web.config不會輕易被人下載到,但仍是具備必定的危險性。另外也能夠運行Dcomcnfg.exe工具提高ASPNET帳戶權限爲交互式用戶,固然這樣也會增長服務器的風險。網上搜索發現有網友的解決方法是:在.net 安裝根目錄下找到config文件夾下的machine.config文件將processModel 中的username屬性改成SYSTEM。還有網友的解決方法是:將IIS默認的帳戶改成管理員帳戶。這兩個方法更加危險,一旦***得到了ASP.Net進程的權限,他就能徹底控制你的服務器。
3、運行穩定性:微軟Office是主要針對普通用戶開發的桌面辦公應用軟件,它具備豐富的UI(用戶界面)元素,是一套純粹的本地運行軟件或者說是客戶端軟件。Word自動化接口主要是爲了方便窗口應用程序調用而設計的。例如Delphi、VB、C# Winform等開發的本地應用程序。雖然能夠強制Visible爲false,Word能夠運行在服務器端代碼裏,但畢竟仍是會帶來許多棘手問題。1. ASP.NET是基於B/S架構的。B/S架構下用戶訪問都是併發的,也就是說常常會出現同時N個用戶對一個服務器頁面發出請求。在這種狀況下Word自動化調用會時常出現死進程。2. 因爲隱藏界面運行,一些涉及界面的能夠在窗口程序裏成功調用的接口,在服務器端調用就會失敗,甚至崩潰,這種狀況也會常常致使死進程。3. 因爲Word是複雜的桌面程序,並不符合通常Web服務程序簡潔高效的標準,因此在服務器端運行時速度慢,而且還會消耗大量資源(CPU、內存),尤爲不能支持大量用戶同時訪問,資源會很快耗盡。4. 絕大部分開發者對COM技術比較陌生,在編程調用Word接口時常常存在一些代碼錯誤,而又很難檢查到問題所在,這又是致使死進程的常常因素。Word死進程不只會消耗服務器資源,還常常會致使服務器頁面不能建立新的Word自動化對象而沒法繼續工做。有網友提出死進程解決方法:編程Kill掉Word死進程,這樣是治標不治本的作法,Word死進程是不在了,但是Word非正常關閉會致使不少資源沒法及時釋放。這樣的Web服務器能持續工做多久恐怕就很難說了。
既然在Web服務器端自動化調用Word存在這麼多問題,那麼能不能在客戶端瀏覽器裏調用Word呢?用JavaScript確定能夠,不過要想運行就得把瀏覽器的安全性降到最低,呵呵,恐怕沒有幾個用戶願意這麼作啊。即便不存在安全問題,原本寫在服務器端的代碼邏輯要寫在JavaScript裏,由此帶來的大量麻煩(打開、傳值、取值、保存到服務器等)也會讓人難以容忍。
4. 解決方案
爲了解決這些問題,筆者通過全面研究比較,發現網上有一款軟件PageOffice,徹底消除了以上問題,推薦給你們分享。
PageOffice for ASP.NET是一款很是優秀的專業的集成微軟OFFICE功能的ASP.NET控件平臺,可以幫助Web開發人員輕鬆實如今網頁中嵌入運行微軟Office的特殊功能。PageOffice把微軟複雜的Office編程接口(COM API)有效地整合於 ASP.NET 環境,經過簡化的。NET類庫接口爲開發者提供了在Web項目裏得到Office衆多強大功能的機會,而且可以同時利用來自 .NET Framework 的開發效率和軟件功能。服務器端調用WebOpen打開文檔後,瀏覽器頁面裏客戶端控件會啓動客戶機上的Word而且運行在網頁裏而不是本地打開。服務器端無需安裝Office軟件。
PageOffice的架構很巧妙,開發者只需關注服務器端編程邏輯,客戶端如何工做都交由控件自動完成。PageOffice充分利用了分佈式計算的思想,把原本要在服務器端運行的Word運算量交給了客戶機。也就是說,原來採用服務器端自動化技術的網頁同時要處理N個Word任務如今交給了N個客戶機,每一個客戶機運行一個Word。服務器只需處理須要服務器處理的業務邏輯,一切與界面有關、與Word程序自己有關的工做由客戶機運行,固然這也是客戶機的強項。
PageOffice的架構消除了服務器端運行Word、Excel的風險,又充分利用了客戶機閒置的計算資源,這種架構不但解決了ASP、ASP.NET等Windows web服務調用Word、Excel的問題,並且還給Java寫的Web服務調用Word、Excel提供瞭解決方案(Unix、linux等沒法自動化Word、Excel)。
PageOffice可以讓用戶直接在網頁裏看到word文件內容,而且能夠直接編輯、保存回Web服務器,給用戶省去了先下載下來,修改完後再上傳的麻煩。PageOffice還有其餘更多自動化調用Word沒法作到的強悍功能,好比只讀、防下載、防複製等,你就下載一個慢慢琢磨吧。
附上利用 PageOffice完成本實例相同功能 + 只讀防下載功能的代碼:
private void Page_Load(object sender, System.EventArgs e)
{
// 在此處放置用戶代碼以初始化頁面
PageOffice.WordWriter.WordDocument doc = new PageOffice.WordWriter.WordDocument();
//對數據區域"Title"進行填充
doc.OpenDataRegion("Title").Value = "公文標題";
// 設置界面樣式
PageOfficeCtrl1.Theme = PageOffice.ThemeType.Office2010;linux
PageOfficeCtrl1.Caption = "動態生成文檔";
PageOfficeCtrl1.Menubar = false;
PageOfficeCtrl1.OfficeToolbars = false;
PageOfficeCtrl1.AllowCopy = false;//禁止下載、複製粘貼等
// 獲取數據對象
PageOfficeCtrl1.SetWriter(doc);
// 只讀打開生成的文檔
PageOfficeCtrl1.WebOpen("doc/test.doc", PageOffice.OpenModeType.docReadOnly, "張三");
}web