2010-11-29 93 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 
     { 

     } 
    } 
相关问题