運行環境:WIN7 X64 + iis6.1
開發環境:vs2012+SQL2005
服務器環境:2003 X64 + SQL2005 + IIS 6.0
需求: 企業中需要各種各樣的報表諸如WORD,簡單還好說,稍微比較復雜點的,需要根據錄入的信息去生成特定格式的WORD.大概15頁左右包含[基本信息][業務情況][聯系人信息][店面圖片][記錄描述][財務指標數據][評分卡][信用評級][反饋信息]等;有些內容不固定諸如[記錄描述]中有可能有沒有記錄,有可能是1-5條數據 也有可能是超過10條的數據.還有要支持圖片的插入,WORD排版等因素.
方案:根本業務部門給出的WORD樣本制作WORD文檔模板(即xxx.dot文件)設置[書簽],然後用應用程序調用本地WORD的COM對象接口,查找[書簽]填充數據;
排版問題:文檔模板可以適用模板隨時可以調整,刪減內容還要刪減對應的[書簽]否則會有[書簽]找不到的問題.
圖片插入:[書簽]支持圖片插入;
不固定的記錄:我分為二種情況.1.動態數據量小的3條以內,那麼我就以最大為主在WORD中占位3條數據. 2.數據量大的咨詢業務部門實際數目設置最大數,然後用書簽占位,相當與把動態數據都搞成固定數.都是基於實際工作量戰線拉太長於實際實現不利.(有興趣的朋友可以去研究下[動態占位]問題,需要解決掉,因為模板設置,占位都需要參考業務部門給出樣本WORD來對比手工占位,系統占位就要考慮換行,空格等問題.)
其他:[書簽]使用方法,根據樣本WORD,打開WORD另存為.dot格式,鼠標點擊需要插入[書簽]的位置,點擊菜單欄[插入]-[書簽],鍵入書簽名即可.
查找[書簽],Ctrl+F 查找選擇[定位]選項卡 定位目標[書簽]
代碼實現思路:
1.整理需要填充到WORD模板中的數據
2.調用CCWordApp查找模板.dot 根據[書簽]去填充(文本,數字,圖片)
3.保存WORD(id標識+日期 防止文件重復.)然後供用戶下載.(擴展,可以安裝WORD轉PDF組件 在服務端就可以找到生成後的WORD轉換PDF供用戶下載,滿足一部分文件安全性要求比較高,不允許用戶修改.)
具體代碼如下:
業務代碼
using Microsoft.Office.Interop.Word; using System; using System.Collections.Generic; using System.Configuration; using System.Data.SqlClient; using System.IO; using System.Reflection; using System.Web; using System.Web.UI.WebControls; public partial class CustInfoManage_PrintPage : System.Web.UI.Page { object missing = System.Reflection.Missing.Value; object readOnly = false; object isVisible = true; private CCWordApp test; DAL Da = new DAL(); ////// 使用模板 /// public void OpenModelWordSave(object sender, EventArgs e) { //根據 客戶編碼 獲取並組織WORD文檔所需的所有信息. string CustCode = ShowCustLabel.Text; if (CustCode == ) { return; } #region 填充信息整理 此處省略 //String gsmc = Dr1[SaleComp].ToString();//公司名稱 #endregion try { test = new CCWordApp(); test.Open(System.Configuration.ConfigurationManager.AppSettings[WordMod] + template1.dot); #region 查找書簽並替換 test.GotoBookMark(gsmc); test.InsertText(gsmc); test.SetFont(nothing); test.GotoBookMark(dmcqxz_C); test.InsertText(dmcqxz_C); test.SetFont(nothing); if (!String.IsNullOrWhiteSpace(dmtp1_C)) { test.GotoBookMark(dmtp1_C); test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings[OtherImage] + dmtp1_C); test.SetFont(nothing); } if (!String.IsNullOrWhiteSpace(dmtp2_C)) { test.GotoBookMark(dmtp2_C); test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings[OtherImage] + dmtp2_C); test.SetFont(nothing); } if (!String.IsNullOrWhiteSpace(cktp1_C)) { test.GotoBookMark(cktp1_C); test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings[OtherImage] + cktp1_C); test.SetFont(nothing); } if (!String.IsNullOrWhiteSpace(cktp2_C)) { test.GotoBookMark(cktp2_C); test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings[OtherImage] + cktp2_C); test.SetFont(nothing); } test.GotoBookMark(dyfxjhyhck_D); test.InsertText(dyfxjhyhck_D); test.SetFont(nothing); #endregion string createTime = DateTime.Now.ToString(yyyyMMddHHmmss); string fileName = CustCode + _ + createTime + .doc; test.SaveAs(System.Configuration.ConfigurationManager.AppSettings[WordDoc] + fileName); test.Quit(); #region 保存到數據庫 string InsertCommand = INSERT INTO [CRM_CB_DownFileWord] + ( [CustCode],[fileName], [createTime]) + VALUES + (@CustCode,@fileName, @createTime); SqlCommand SqlCmd = new SqlCommand(InsertCommand); SqlCmd.Parameters.Add(@CustCode, System.Data.SqlDbType.Decimal).Value = CustCode; SqlCmd.Parameters.Add(@fileName, System.Data.SqlDbType.NVarChar).Value = fileName; SqlCmd.Parameters.Add(@createTime, System.Data.SqlDbType.NVarChar).Value = createTime; string Mess = ; if (Da.ExecuteNonQuery(SqlCmd)) { Mess = CustCode + 保存成功!; BaseCls.Alert(Page, Mess); } else { BaseCls.Alert(Page, 錯誤,請檢查!); return; } #endregion } catch (Exception exc) { test.Quit(); throw (exc); } } }
CCWordApp實體類:
using System; using System.ComponentModel; public class CCWordApp { private Microsoft.Office.Interop.Word.ApplicationClass oWordApplic; // a reference to Word application 引用Word應用程序 private Microsoft.Office.Interop.Word.Document oDoc; // a reference to the document 引用文檔 public CCWordApp() { // activate the interface with the COM object of Microsoft Word //激活與Microsoft Word的COM對象的接口 oWordApplic = new Microsoft.Office.Interop.Word.ApplicationClass(); } ////// 插入圖片 /// /// public void InsertPicture(string picPath) { object missing = System.Reflection.Missing.Value; oWordApplic.Selection.InlineShapes.AddPicture(picPath, ref missing, ref missing, ref missing); } // Open a file (the file must exists) and activate it 打開一個文件(該文件必須存在),並激活它 public void Open(string strFileName) { object fileName = strFileName; object readOnly = false; object isVisible = true; object missing = System.Reflection.Missing.Value; oDoc = oWordApplic.Documents.Open(ref fileName, ref missing, ref readOnly, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref isVisible, ref missing, ref missing, ref missing); oDoc.Activate(); } // Open a new document打開一個新文檔 public void Open() { object missing = System.Reflection.Missing.Value; oDoc = oWordApplic.Documents.Add(ref missing, ref missing, ref missing, ref missing); oDoc.Activate(); } public void Quit() { object missing = System.Reflection.Missing.Value; oWordApplic.Application.Quit(ref missing, ref missing, ref missing); } public void Save() { oDoc.Save(); } public void SaveAs(string strFileName) { object missing = System.Reflection.Missing.Value; object fileName = strFileName; oDoc.SaveAs(ref fileName, 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); } // Save the document in HTML format 以HTML格式保存文檔 public void SaveAsHtml(string strFileName) { object missing = System.Reflection.Missing.Value; object fileName = strFileName; object Format = (int)Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatHTML; oDoc.SaveAs(ref fileName, ref Format, 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); } public void InsertText(string strText) { oWordApplic.Selection.TypeText(strText); } public void InsertLineBreak() { oWordApplic.Selection.TypeParagraph(); } public void InsertLineBreak(int nline) { for (int i = 0; i < nline; i++) oWordApplic.Selection.TypeParagraph(); } // Change the paragraph alignement 更改段落對齊鍵相 public void SetAlignment(string strType) { switch (strType) { case Center: oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter; break; case Left: oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphLeft; break; case Right: oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight; break; case Justify: oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphJustify; break; } } // if you use thif function to change the font you should call it again with 如果您使用此功能來改變字體,你應該再次調用它 // no parameter in order to set the font without a particular format 為了不帶參數設置字體沒有特定的格式 public void SetFont(string strType) { switch (strType) { case Bold: oWordApplic.Selection.Font.Bold = 1; break; case Italic: oWordApplic.Selection.Font.Italic = 1; break; case Underlined: oWordApplic.Selection.Font.Subscript = 0; break; } } // disable all the style 禁用所有的風格 public void SetFont() { oWordApplic.Selection.Font.Bold = 0; oWordApplic.Selection.Font.Italic = 0; oWordApplic.Selection.Font.Subscript = 0; } public void SetFontName(string strType) { oWordApplic.Selection.Font.Name = strType; } public void SetFontSize(int nSize) { oWordApplic.Selection.Font.Size = nSize; } public void InsertPagebreak() { // VB : Selection.InsertBreak Type:=wdPageBreak object pBreak = (int)Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak; oWordApplic.Selection.InsertBreak(ref pBreak); } // Go to a predefined bookmark, if the bookmark doesn't exists the application will raise an error //去到一個預先定義的書簽,如果書簽不存在應用程序將引發錯誤 public void GotoBookMark(string strBookMarkName) { // VB : Selection.GoTo What:=wdGoToBookmark, Name:=nome object missing = System.Reflection.Missing.Value; object Bookmark = (int)Microsoft.Office.Interop.Word.WdGoToItem.wdGoToBookmark; object NameBookMark = strBookMarkName; oWordApplic.Selection.GoTo(ref Bookmark, ref missing, ref missing, ref NameBookMark); } public void GoToTheEnd() { // VB : Selection.EndKey Unit:=wdStory object missing = System.Reflection.Missing.Value; object unit; unit = Microsoft.Office.Interop.Word.WdUnits.wdStory; oWordApplic.Selection.EndKey(ref unit, ref missing); } public void GoToTheBeginning() { // VB : Selection.HomeKey Unit:=wdStory object missing = System.Reflection.Missing.Value; object unit; unit = Microsoft.Office.Interop.Word.WdUnits.wdStory; oWordApplic.Selection.HomeKey(ref unit, ref missing); } public void GoToTheTable(int ntable) { // Selection.GoTo What:=wdGoToTable, Which:=wdGoToFirst, Count:=1, Name:= // Selection.Find.ClearFormatting // With Selection.Find // .Text = // .Replacement.Text = // .Forward = True // .Wrap = wdFindContinue // .Format = False // .MatchCase = False // .MatchWholeWord = False // .MatchWildcards = False // .MatchSoundsLike = False // .MatchAllWordForms = False // End With object missing = System.Reflection.Missing.Value; object what; what = Microsoft.Office.Interop.Word.WdUnits.wdTable; object which; which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToFirst; object count; count = 1; oWordApplic.Selection.GoTo(ref what, ref which, ref count, ref missing); oWordApplic.Selection.Find.ClearFormatting(); oWordApplic.Selection.Text = ; } public void GoToRightCell() { // Selection.MoveRight Unit:=wdCell object missing = System.Reflection.Missing.Value; object direction; direction = Microsoft.Office.Interop.Word.WdUnits.wdCell; oWordApplic.Selection.MoveRight(ref direction, ref missing, ref missing); } public void GoToLeftCell() { // Selection.MoveRight Unit:=wdCell object missing = System.Reflection.Missing.Value; object direction; direction = Microsoft.Office.Interop.Word.WdUnits.wdCell; oWordApplic.Selection.MoveLeft(ref direction, ref missing, ref missing); } public void GoToDownCell() { // Selection.MoveRight Unit:=wdCell object missing = System.Reflection.Missing.Value; object direction; direction = Microsoft.Office.Interop.Word.WdUnits.wdLine; oWordApplic.Selection.MoveDown(ref direction, ref missing, ref missing); } public void GoToUpCell() { // Selection.MoveRight Unit:=wdCell object missing = System.Reflection.Missing.Value; object direction; direction = Microsoft.Office.Interop.Word.WdUnits.wdLine; oWordApplic.Selection.MoveUp(ref direction, ref missing, ref missing); } // this function doesn't work 這個功能不起作用 public void InsertPageNumber(string strType, bool bHeader) { object missing = System.Reflection.Missing.Value; object alignment; object bFirstPage = false; object bF = true; //if (bHeader == true) //WordApplic.Selection.HeaderFooter.PageNumbers.ShowFirstPageNumber = bF; switch (strType) { case Center: alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberCenter; //WordApplic.Selection.HeaderFooter.PageNumbers.Add(ref alignment,ref bFirstPage); //Word.Selection objSelection = WordApplic.pSelection; //oWordApplic.Selection.HeaderFooter.PageNumbers.Item(1).Alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberCenter; break; case Right: alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberRight; //oWordApplic.Selection.HeaderFooter.PageNumbers.Item(1).Alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberRight; break; case Left: alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberLeft; oWordApplic.Selection.HeaderFooter.PageNumbers.Add(ref alignment, ref bFirstPage); break; } } } //object units = WdUnits.wdCharacter; //object last=doc.Characters.Count; //doc.Range(ref first, ref last).Delete(ref units, ref last)
發布測試環境可能會遇到的問題1:
行 1679: catch (Exception exc) 行 1680: { 行 1681: throw (exc); 行 1682: //StatusMessage.Text = exc.Message; 行 1683: //StatusMessage.Visible = true;
[UnauthorizedAccessException: 檢索 COM 類工廠中 CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件失敗,原因是出現以下錯誤: 80070005 拒絕訪問。 (異常來自 HRESULT:0x80070005 (E_ACCESSDENIED))。] CustInfoManage_PrintPage.OpenModelWordSave(Object sender, EventArgs e) in e:T1Web - 測試CustInfoManagePrintPage.aspx.cs:1681 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9556538 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +103 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724
解決方案:
參考此文鏈接:http://axislover.blog.163.com/blog/static/10776515200832531059319/
如果無法訪問摘錄如下:
Application當程序運行到這句時出現下面的錯誤:檢索 COM 類工廠中 CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件時失敗,原因是出現以下錯誤: 80070005。3.單擊安全選項卡,分別在啟動和激活權限和訪問權限組中選中自定義,然後 自定義->編輯->添加ASP.NET賬戶和IUSER_計算機名。解決方法二:如果上述方法不能解決問題,就應該是權限問題,請嘗試用下面 的方法:在web.config中使用身份模擬,在
1:在服務器上安裝office的word軟件.
2:在開始- >運行中輸入dcomcnfg.exe啟動組件服務
3:依次雙擊組件服務- >計算機- >我的電腦- >DCOM配置
4:在DCOM配置中找到Microsoft word應用程序,在它上面點擊右鍵,然後點擊屬性,彈出Microsoft word應用程序屬性對話框
5:點擊標識標簽,選擇交互式用戶
6:點擊安全標簽,在啟動和激活權限上點擊自定義,然後點擊對應的編輯按鈕,在彈出的安全性對話框中填加
一個NETWORK SERVICE用戶(注意要選擇本計算機名),並給它賦予本地啟動和本地激活權限.
7:依然是安全標簽,在訪問權限上點擊自定義,然後點擊編輯,在彈出的安全性對話框中也填加一個NETWORK
SERVICE用戶,然後賦予本地訪問權限.
這樣,我們便配置好了相應的word的DCOM權限.
注意:這是在WIN2003上配置的,在2000上,可能是配置ASPNET用戶
由於word是在服務器上打開的,所以應該寫一個把導出數據保存在服務器上,然後再傳遞給客戶端的方法,最後每次調用這個功能的時候再刪除以前在服務器上所生成的所有word
檢索 COM 類工廠中 CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件時失敗,原因是出現以下錯誤: 80070005
在CSDN上總是有網友問這個問題,自己也遇到過,因些寫出來供參考:
症狀:
oWordApplic = New Word.Application
當程序運行到這句時出現下面的錯誤:
檢索 COM 類工廠中 CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件時失敗,原因是出現以下錯誤: 80070005。
oWordApplic = New Word.Application
當程序運行到這句時出現下面的錯誤:
檢索 COM 類工廠中 CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件時失敗,原因是出現以下錯誤: 80070005。
解決方法一:
控制面板-》管理工具-》組件服務-》計算機-》我的電腦-》DCom配置-》找到Microsoft Word文檔
之後
單擊屬性打開此應用程序的屬性對話框。
2. 單擊標識選項卡,然後選擇交互式用戶。
3.單擊安全選項卡,分別在啟動和激活權限和訪問權限組中選中自定義,然後
自定義->編輯->添加ASP.NET賬戶和IUSER_計算機名
* 這些帳戶僅在計算機上安裝有 IIS 的情況下才存在。
13. 確保允許每個用戶訪問,然後單擊確定。
14. 單擊確定關閉 DCOMCNFG。
解決方法二:
如果上述方法不能解決問題,就應該是權限問題,請嘗試用下面的方法:
在web.config中使用身份模擬,在
PS:進我自己測試,做完1-7步驟就已經可以修復這個問題了.
發布測試環境可能會遇到的問題2:
明明有裝Word2007, 並且程序也能用這個組件來操作Word, 可為什麼組件服務裡面看不到CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件?我是希望能顯示CLSID 為 {000209FF-0000-0000-C000-000000000046} 的組件, 好設置它的權限了。 省得ASP.NET要模擬帳戶
在64bit系統中的DCOM管理中添加32Bit的Excel、Word等的管理)
1).開始--〉運行--〉cmd
2)命令提示符下面,輸入“mmc -32”回車,打開32的控制台
3).文件菜單中,添加刪除管理單元--〉“組件服務”(在最下面),確認後,關閉即可。
4).開始-管理工具-組件服務,在DCOM配置中,可以找到“Microsoft Excel 應用程序”了。找到“Microsoft Excel 應用程序”,在它上面點擊右鍵,然後點擊屬性,彈出Microsoft Excel 應用程序屬性對話框 5).點擊“標識”標簽,選擇“交互式用戶” **:這個在32Bit的2003上或XP上不需要,但這裡需要。 6).點擊安全標簽,在啟動和激活權限上點擊自定義,然後點擊對應的編輯按鈕,在彈出的安全性對話框中填加一個NETWORK SERVICE用戶(注意要選擇本計算機名),並給它賦予本地啟動和本地激活權限
7).依然是安全標簽,在訪問權限上點擊自定義,然後點擊編輯,在彈出的安全性對話框中也填加一個NETWORK SERVICE用戶,然後賦予本地訪問權限.
PS:這個問題算是誤導了.我是先碰到問題2的,但是按此方法無法解決,用問題1中在開始- >運行中輸入dcomcnfg.exe啟動組件服務即可查到WORD組件.
發布測試環境可能會遇到的問題3:
執行當前 Web 請求期間生成了未經處理的異常。可以使用下面的異常堆棧跟蹤信息確定有關異常原因和發生位置的信息。
[HttpException (0x80004005): 當前標識(IT-CHENXIAOPENG est)沒有對“C:WindowsMicrosoft.NETFramework4.0.30319Temporary ASP.NET Files”的寫訪問權限。] System.Web.HttpRuntime.SetUpCodegenDirectory(CompilationSection compilationSection) +9902226 System.Web.HttpRuntime.HostingInit(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException) +199 [HttpException (0x80004005): 當前標識(IT-CHENXIAOPENG est)沒有對“C:WindowsMicrosoft.NETFramework4.0.30319Temporary ASP.NET Files”的寫訪問權限。] System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9880168 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +101 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254
版本信息: Microsoft .NET Framework 版本:4.0.30319; ASP.NET 版本:4.0.30319.18067