Asp.net下C#調用Word功能的實例與總結

本文通過一個實用例子完整演示瞭如何使用C#在ASP.NET裏調用Word、自動化Word,並且總結了實際應用中發現的問題,最後提出了有效的解決方案

關鍵詞: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在實際應用中發現的問題:
一、開發難易度:Word自動化中的調用都基於VBA語法,需要開發者對VBA很熟悉。VBA中Word對象衆多、邏輯複雜,COM調用方式難於理解。一般開發者很少接觸VBA和COM,因此開發起來比較麻煩。
二、代碼安全性:上述運行錯誤“拒絕訪問”的最佳解決方法就是添加<identity impersonate="true" userName="*" password="*" />,不過缺點是在Web.config裏可以看到你的賬戶密碼,儘管Web.config不會輕易被人下載到,但還是具有一定的危險性。另外也可以運行Dcomcnfg.exe工具提升ASPNET賬戶權限爲交互式用戶,當然這樣也會增加服務器的風險。網上搜索發現有網友的解決方法是:在.net 安裝根目錄下找到config文件夾下的machine.config文件將processModel 中的username屬性改爲SYSTEM。還有網友的解決方法是:將IIS默認的賬戶改爲管理員賬戶。這兩個方法更加危險,一旦***獲得了ASP.Net進程的權限,他就能完全控制你的服務器。
三、運行穩定性:微軟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;

PageOfficeCtrl1.Caption = "動態生成文檔";
PageOfficeCtrl1.Menubar = false;
PageOfficeCtrl1.OfficeToolbars = false;
PageOfficeCtrl1.AllowCopy = false;//禁止下載、複製粘貼等
// 獲取數據對象
PageOfficeCtrl1.SetWriter(doc);
// 只讀打開生成的文檔
PageOfficeCtrl1.WebOpen("doc/test.doc", PageOffice.OpenModeType.docReadOnly, "張三");
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章