2010-11-29 91 views
14

我想在Microsoft Office Word中創建約600個報表。這些文檔將填充來自數據庫的數據以及本地驅動器上的映像。 我已經想通了,我可以在Visual Studio 2010中創建一個Word模板項目,並對模板進行編程,以便當您輸入單個值(id-number)時,它會自動填充整個文檔。如何通過模板以編程方式創建Word文檔

我相當確信這是可能的。唯一的問題是。如何遍歷數據庫中的所有條目,根據模板打開一個新文檔並設置id值?

for(int i = 0; i < idnumbers.Count(); i++) 
{ 
    Word.Application app = new Word.Application(); 
    Word.Document doc = app.Documents.Add(@"C:\..\WordGenerator\bin\Debug\WordTemplate.dotx"); 
    //input the id-number below: HOW?? 

    doc.SaveAs(FileName: @"c:\temp\test.docx"); 
} 

該應用程序應該只運行一次,生成的報告,它不必很快。它必須容易開發。

這裏的問題是,似乎DocumentBase對象不能在Word項目外訪問。替代Microsoft.Office.Interop.Word.Document沒有像SelectContentControlsByTitle這樣的功能,它允許我查找和設置我的ContentControls。這正是我需要做的。

這就是我的代碼現在看起來像現在插入文本到我的字段中: Word.Application app = new Word.Application();

 Word.Document doc = app.Documents.Add(@"C:\..\test.dotx"); 

     foreach (Word.ContentControl cc in doc.SelectContentControlsByTitle("MyCCTitle")) 
     { 
      cc.Range.Text += "1234"; 
     } 

     doc.SaveAs(FileName: @"c:\temp\test.docx"); 

然後在BeforeSave在我的模板中的事件處理程序填寫基於在MyCCTitle題爲對象中的文本文檔。

回答

4

,如果你使用的是Word 2007或2010格式

http://msdn.microsoft.com/en-us/library/bb264572(office.12).aspx

+0

這將是添加引用矯枉過正什麼,他正在努力實現,字自動化/互操作是很容易爲這種情況做。 – BrokenGlass 2010-11-29 13:44:05

+0

矯枉過正?一點也不。 OpenXML SDK易於使用,並且意味着完成此操作。在進行文字自動化/互操作時,您是否必須在服務器上安裝Word?使用OpenXML你不需要。 – 2010-11-29 13:58:27

+0

再加上我想添加到Moontear的評論,OpenXML格式只是XML它如此之快,他正在試圖做什麼(生成600文檔) – Shuwaiee 2010-11-29 14:40:29

9

不要使用辦公自動化,你應該閱讀有關OpenXML格式。 辦公自動化在後臺打開辦公室實例並對其執行操作。打開辦公室實例600次似乎不是一件非常有趣的事情。 (並且它永遠不會運行serverside)

看看Open XML。你可以找到關於它的下面負載:

http://openxmldeveloper.org/

2

似乎有2個問題在這裏:

  1. 你如何揭開序幕的過程特定ID值

  2. 你如何填充文檔。

sunilp已經回答了Q2。數據綁定內容控件是爲Word 2007及更高版本注入數據的最佳方式。

OP的重點看起來是Q1。

沒有命令行開關,可以讓你通過一個任意值到Word:通過OpenXML的SDK

  1. 做的所有工作:http://support.microsoft.com/kb/210565

    所以當我看到它,你有4個選擇,從來沒有在所有使用的OpenXML SDK打開Word(如其他海報建議)

  2. 創建一個最小的預先存在的文件(包括你的身份證號碼),然後打開Word

  3. Word自動ID號傳遞給文件,或許作爲文檔屬性

  4. 做的工作,以創建使用VSTO或Word宏(VBA)

我在Word中的600份文件?我將在Word中創建一個包含數據綁定內容控件的docx,並保存它。

然後,將注入我的數據作爲一個自定義的XML部分,並保存它。 (這一步你可以使用OpenXML SDK,或者在Word中,如果你需要讓Word更新你的某個下游進程的綁定)

0

在考慮到上述答案我J. Vermeire同意OpenXML的是要走的路。我已經使用基於OpenXML的工具包已有三年多了,它生成了從模板和數據庫數據中合併的.docx文檔。有一個示例如何使用它here。這個例子展示瞭如何在當時使用一個文檔來處理更多的文檔,只需添加一個循環並調用文檔生成的方法即可。

0

Document.OpenXml.dllWindowsBase.dll

using System.IO.Packaging; 

using DocumentFormat.OpenXml.Packaging; 

using System.DirectoryServices; 

protected void btnOK_Click(object sender, EventArgs e) 
    { 

     try 
     { 
      Package package; 
      string strTemplateName = ddl_Templates.SelectedValue.ToString(); //Select Dotx template 
      string strClaimNo = "3284112"; 
      string strDatePart = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString(); 
      //Word template file 
      string templateName = Server.MapPath("~\\LetterTemplates\\" + strTemplateName + ".dotx"); 
      PackagePart documentPart = null; 
      //New file name to be generated from 
      string docFileName = Server.MapPath("~\\LetterTemplates\\" + strClaimNo + "_" + strTemplateName + "_" + strDatePart + ".docx"); 

      File.Copy(templateName,docFileName, true); 
      string fileName = docFileName; 
      package = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite); 
      DataSet DS = GetDataSet(strClaimNo, ""); // to get the data from backend to fill in for merge fields 
      try 
      { 
       if (DS != null) 
       { 
        if (DS.Tables.Count > 0) 
        { 
         if (DS.Tables[0].Rows.Count > 0) 
         { 
          foreach (System.IO.Packaging.PackageRelationship documentRelationship 
           in package.GetRelationshipsByType(documentRelationshipType)) 
          { 
           NameTable nt = new NameTable(); 
           nsManager = new XmlNamespaceManager(nt); 
           nsManager.AddNamespace("w", 
            "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); 

           Uri documentUri = PackUriHelper.ResolvePartUri(
            new Uri("/", UriKind.Relative), documentRelationship.TargetUri); 
           documentPart = package.GetPart(documentUri); 

           //Get document xml 
           XmlDocument xdoc = new XmlDocument(); 
           xdoc.Load(documentPart.GetStream(FileMode.Open, FileAccess.Read)); 
           int intMergeFirldCount = xdoc.SelectNodes("//w:t", nsManager).Count; 

           XmlNodeList nodeList = xdoc.SelectNodes("//w:t", nsManager); 
           foreach (XmlNode node in nodeList) 
           { 
            try 
            { 
             xdoc.InnerXml = xdoc.InnerXml.Replace(node.InnerText, DS.Tables[0].Rows[0][node.InnerText.Replace("«", "").Replace("»", "").Trim()].ToString()); 
            }catch(Exception x) { } 
           } 

           StreamWriter streamPart = new StreamWriter(documentPart.GetStream(FileMode.Open, FileAccess.Write)); 
           xdoc.Save(streamPart); 
           streamPart.Close(); 
           package.Flush(); 
           package.Close(); 
          } 
          using (WordprocessingDocument template = WordprocessingDocument.Open(docFileName, true)) 
          { 
           template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document); 
           template.MainDocumentPart.Document.Save(); 
          } 

          byte[] bytes = System.IO.File.ReadAllBytes(docFileName); 
          System.IO.File.Delete(docFileName); 
          System.Web.HttpResponse response = System.Web.HttpContext.Current.Response; 
          response.ClearContent(); 
          response.Clear(); 
          response.ContentType = "application/vnd.msword.document.12"; //"application/msword"; 
          Response.ContentEncoding = System.Text.Encoding.UTF8; 
          response.AddHeader("Content-Disposition", "attachment; filename=" + strClaimNo + "_" + strTemplateName + "_" + strDatePart + ".docx;"); 
          response.BinaryWrite(bytes); 
          response.Flush(); 
          response.Close(); 
         } 
         else 
         { 
          throw (new Exception("No Records Found.")); 
         } 
        } 
        else 
        { 
         throw (new Exception("No Records Found.")); 
        } 
       } 
       else 
       { 
        throw (new Exception("No Records Found.")); 
       } 


      } 
      catch (Exception ex) 
      { 
       package.Flush(); 
       package.Close(); 
       // Softronic to add code for exception handling 
      } 
     } 
     catch (Exception ex) 
     { 

      // add code for exception handling 
     } 
     finally 
     { 

     } 
    } 
相關問題