asp.net讀寫Word、拼接Word檔案
ASP.NET呼叫Word進行檔案處理說明
一、 程式設計
1) 新增引用
2) 程式碼
利用標籤對文件內容進行修改
將多個文件進行合併
#region 開啟檔案 private Document objDocLast = null; private Document objDocBeforeLast = null; Microsoft.Office.Interop.Word.Application objApp =null; // 文件第一部分 const string sDocPart1 = "/doc/Model1.doc" // 文件第三部分 const string sDocPart3 = "/doc/Model3.doc"; // 合併後文檔 const string sDocMerge = "/doc/Model_All.doc"; // 新文件字首[新文件為檔案字首+使用者ID] const string sDocProv = "/doc/New"; // 開啟Word文件,不能以只讀方式開啟 // 如果出現共享開啟的時候,可以複製一份,再開啟 private void Open(string { // 變數定義 object objTempDoc = tempDoc; object objMissing = System.Reflection.Missing.Value; object objReadOnly = true; //建立一個名為WordApp的元件物件 objApp = new Microsoft.Office.Interop.Word.Application(); objApp.Visible = false // 開啟文件 objDocLast = objApp.Documents.Open( ref objTempDoc, //FileName ref objMissing, //ConfirmVersions ref objMissing, //ReadOnly ref objMissing, //AddToRecentFiles ref objMissing, //PasswordDocument ref objMissing, //PasswordTemplate ref objMissing, //Revert ref objMissing, //WritePasswordDocument ref objMissing, //WritePasswordTemplate ref objMissing, //Format ref objMissing, //Enconding ref objMissing, //Visible ref objMissing, //OpenAndRepair ref objMissing, //DocumentDirection ref objMissing, //NoEncodingDialog ref objMissing //XMLTransform ); objDocLast.Activate(); } #endregion #region 儲存檔案到輸出模板 private void SaveAs(string outDoc) { object objMissing = System.Reflection.Missing.Value; object objOutDoc = outDoc; objDocLast.SaveAs( ref objOutDoc, //FileName ref objMissing, //FileFormat ref objMissing, //LockComments ref objMissing, //PassWord ref objMissing, //AddToRecentFiles ref objMissing, //WritePassword ref objMissing, //ReadOnlyRecommended ref objMissing, //EmbedTrueTypeFonts ref objMissing, //SaveNativePictureFormat ref objMissing, //SaveFormsData ref objMissing, //SaveAsAOCELetter, ref objMissing, //Encoding ref objMissing, //InsertLineBreaks ref objMissing, //AllowSubstitutions ref objMissing, //LineEnding ref objMissing //AddBiDiMarks ); } #endregion #region 迴圈合併多個檔案(插入合併檔案) ///<summary> ///迴圈合併多個檔案(插入合併檔案) ///</summary> ///<param name="tempDoc">模板檔案</param> ///<param name="arrCopies">需要合併的檔案</param> ///<param name="outDoc">合併後的輸出檔案</param> /// ///其他參考程式碼 /* 測試程式碼,把游標放在文件尾部 //object start = objApp.ActiveWindow.Selection.End; //object end = objApp.ActiveWindow.Selection.End; //Range rng = objDocLast.Range(ref start, ref end); //rng.Select(); ////rng.Paste(); //object objEnd = rng; //objDocLast.ActiveWindow.Document.Range(ref start, ref end); 合併文件 //objDocLast.Merge( // strCopy, //FileName // ref objTarget, //MergeTarget // ref objMissing, //DetectFormatChanges // ref objUseFormatFrom, //UseFormattingFrom // ref objMissing //AddToRecentFiles // ); // objDocBeforeLast = objDocLast; // objDocLast = objApp.ActiveDocument; // if (objDocBeforeLast != null) // { // objDocBeforeLast.Close( // ref objFalse, //SaveChanges // ref objMissing, //OriginalFormat // ref objMissing //RouteDocument // ); // } */ // 進行檔案合併 public void InsertMerge(string tempDoc, string[] arrCopies, string outDoc) { object objMissing = Missing.Value; object objFalse = false; object confirmConversion =false; object link = false; object attachment = false; object objTarget = WdMergeTarget.wdMergeTargetSelected; object objUseFormatFrom =WdUseFormattingFrom.wdFormattingFromSelected; try { //只讀方式開啟模板檔案 Open(tempDoc); foreach (string strCopyin arrCopies) { // 文件尾部追加 Object objUnit =WdUnits.wdStory; objApp.Selection.EndKey(ref objUnit); objApp.ActiveWindow.Selection.PasteAndFormat(WdRecoveryType.wdPasteDefault); // 插入文件 objApp.Selection.InsertFile( strCopy, ref objMissing, ref confirmConversion, ref link, ref attachment ); } //儲存到輸出檔案 SaveAs(outDoc); foreach (Document objDocumentin objApp.Documents) { objDocument.Close( ref objFalse,//SaveChanges ref objMissing,//OriginalFormat ref objMissing//RouteDocument ); } } catch(Exception ex) { objApp.Quit( ref objMissing,//SaveChanges ref objMissing,//OriginalFormat ref objMissing//RoutDocument ); objApp = null; throw new Exception(ex.Message); } finally { if (objApp != null) objApp.Quit( ref objMissing,//SaveChanges ref objMissing,//OriginalFormat ref objMissing//RoutDocument ); objApp = null; } } #endregion public ActionResult GetDataSource() { int jdmxID = 0; jdmxID = Convert.ToInt32(Request["id"]); WB_RWS model = xmService.GetModel(jdmxID); RWSModel rwsModel = AutoCopy(model); rwsModel.rws01 = xmService.GetModel01(model.ID); rwsModel.rws02 = xmService.GetModel02(model.ID); rwsModel.wllj = string.Format(@"" +ConfigurationManager.AppSettings["AttachmentPath"].ToString() +"\\" + model.XWJM); rwsModel.url = "http://" + Request.Url.Host +"/" + model.XWJM; // 對文件進行合併時,記錄合併檔案路徑及順序 string[] arrCopies = new string[2]; arrCopies[0] = rwsModel.wllj;// Server.MapPath("/doc/Model2.doc"); arrCopies[1] = Server.MapPath(sDocPart3); // 對文件進行合併 InsertMerge(Server.MapPath(sDocPart1), arrCopies, Server.MapPath(sDocMerge)); // 給HashTable付值 Hashtable htCon; WorldModel world = kkk(rwsModel,out htCon); // 標籤內容寫入Word文件 string FullFileName = Server.MapPath(GenWordDocument(sDocMerge, htCon)); // 下載文件[測試用] FileInfo DownloadFile =newFileInfo(FullFileName); if (DownloadFile.Exists) { Response.Clear(); Response.ClearHeaders(); Response.Buffer = false; Response.ContentType = "application/octet-stream"; Response.AppendHeader("Content-Disposition","attachment;filename=" +HttpUtility.UrlEncode(DownloadFile.FullName, System.Text.Encoding.ASCII)); Response.AppendHeader("Content-Length", DownloadFile.Length.ToString()); Response.WriteFile(DownloadFile.FullName); Response.Flush(); Response.End(); } else { //檔案不存在 } //string Json字串 = JsonConvert.SerializeObject(rwsModel); //RWSModel dd = new WB_RWS(); return null; } // 生成Word文件文件,返回檔案下載相對路徑 public string GenWordDocument(string t_filename, Hashtable htCont) { object Missing = Type.Missing; // 取得Word檔案路徑 string strTemp = t_filename; // 新Word檔案儲存路徑 CMS_Users user = Session["UserInfo"]asCMS_Users; string newFileName = sDocProv + user.Id +".doc"; // 建立一個名為WordApp的元件物件 Microsoft.Office.Interop.Word.Application WordApp =new Microsoft.Office.Interop.Word.Application(); //必須設定為不可見 WordApp.Visible = false; try { //建立以strTemp為模板的文件 object oTemplate = Server.MapPath(strTemp); Microsoft.Office.Interop.Word.Document WordDoc = WordApp.Documents.Add(ref oTemplate,ref Missing,ref Missing,ref Missing); WordDoc.Activate(); //對標籤進行迴圈填充 System.Collections.IEnumerator enu = WordApp.ActiveDocument.Bookmarks.GetEnumerator(); while (enu.MoveNext()) { Microsoft.Office.Interop.Word.Bookmark bk = (Microsoft.Office.Interop.Word.Bookmark)enu.Current; string strBM = bk.Name.ToString(); object objBM = strBM; if (WordApp.ActiveDocument.Bookmarks.Exists(strBM) ==true) { WordApp.ActiveDocument.Bookmarks.get_Item(ref objBM).Select(); if (htCont.ContainsKey(strBM)) WordApp.Selection.TypeText(htCont[strBM].ToString()); else { // 標籤定義有問題。如果是有未找到的,說明書籤有漏寫部分 } } } //儲存為新檔案 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) { WordApp.Quit(ref Missing,ref Missing,ref Missing); throw new Exception(Ex.Message); } return newFileName; } 二、 |
問題點及解決:
1、當伺服器貼上板中有內容時,在檔案拼接的接縫處會將內容寫入。原因待查。
2、如果有多個人同時操作,文件可能會出現共享讀寫的問題。可以定製相關模板如果多人同時操作,複製一份模板各自進行操作可以滿足,但臨時檔案可能較多。
三、 部署
由於ASP.NET訪問Word,需要相關許可權,經過網上相關資料查詢,一般情況下可以使用如下方法解決:
注意:伺服器端安裝Office儘量安裝低版本,可以相容其他使用者較低版本的Office。
1、設定相關許可權
i. 執行dcomcnfg
ii. 選中DCOM中的Word
iii. 右鍵屬性相關設定如圖示
2、其他問題及解決
64位系統偶爾可能會出現錯誤,有可能是利用到了一些其他的庫。具體沒查,會與IIS中的應用程式池設定相關,圖形如下: