【问题标题】:How to create word docs programmatically from a template如何从模板以编程方式创建 word 文档
【发布时间】:2022-05-10 00:17:35
【问题描述】:

我正在尝试在 Microsoft Office Word 中创建大约 600 个报告。这些文档填充了来自数据库的数据和在本地驱动器上找到的图像。 我已经想通了,我可能会在 Visual Studio 2010 中创建一个 Word 模板项目,并对模板进行编程,这样当您输入单个值(id-number)时,它会自动填写整个文档。

我非常有信心这是可能的。唯一的问题是。如何遍历数据库中的所有条目,根据模板打开一个新文档并设置 id-value?

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"); 
}

该应用程序应该只运行一次,生成报告,而且它不必很快。它必须易于开发。

这里的问题是,在 Word 项目之外似乎无法访问 DocumentBase 对象。替代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-titled 对象中的文本填写文档。

【问题讨论】:

  • 问这个问题已经有一段时间了,从那时起事情发生了很大变化。我创建了一个名为“docxtemplater”的库,在github.com/open-xml-templating/docxtemplater 上可用,它使用Javascript 非常优雅地解决了这个问题

标签: c# ms-word office-interop


【解决方案1】:

不要使用办公自动化。 办公自动化在后台打开一个办公实例并对其执行操作。打开一个办公室实例 600 次似乎不是一件很有趣的事情。 (而且它永远不会在服务器端运行)

看看 Open XML。您可以在下面找到有关它的内容:

http://openxmldeveloper.org/

编辑:Openxmldeveloper 正在关闭。请在 http://www.ericwhite.com/ 找到上述所有来源。

【讨论】:

    【解决方案2】:

    也许您应该查看 Microsoft.Office.Tools.Word.Document?

    Document.SelectContentControlsByTitle

    【讨论】:

    • 最后我发现,这实际上是要走的路。但是有很多事情你必须注意。首先,您需要添加对名为 office 的组件的引用,并且您必须确保您的程序集是正确的版本,否则您将无法访问正确的方法和对象。
    【解决方案3】:

    如果您使用 Word 2007 或 2010 格式,您应该阅读有关 OpenXML 格式的信息

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

    【讨论】:

    • 这对于他想要实现的目标来说太过分了,Word 自动化/互操作在这种情况下更容易实现。
    • 矫枉过正?一点也不。 OpenXML SDK 易于使用,并且旨在做到这一点。进行文字自动化/互操作时,您是否不必在服务器上安装 Word?使用 OpenXML,您不需要。
    • 另外我想添加到 Moontear 评论中,OpenXML 格式只是 XML,它在他试图做的事情上是如此之快(生成 600 个文档)
    • 我知道我可能会使用 OpenXML,但对我来说,能够在所见即所得的编辑器中使用可绑定的 ContentControls 设计我的文档似乎要快得多。
    【解决方案4】:

    这里好像有2个问题:

    1. 如何启动特定 id 值的流程

    2. 如何填充文档。

    sunilp 已回答 Q2。数据绑定内容控件是为 Word 2007 及更高版本注入数据的最佳方式。

    OP 的重点似乎是第一季度。

    没有可让您将任意值传递给 Word 的命令行开关:http://support.microsoft.com/kb/210565

    所以在我看来,你有 4 个选择:

    1. 通过 OpenXML SDK 完成所有工作,从不打开 Word(正如其他海报所建议的那样)

    2. 使用 OpenXML SDk 创建一个最小的预先存在的文档(包含您的 ID 号),然后打开 Word

    3. 自动化 Word 将 id 号传递给文档,可能作为文档属性

    4. 使用 VSTO 或 Word 宏 (VBA) 在 Word 中创建 600 个文档

    我?我会在 Word 中创建一个包含数据绑定内容控件的 docx,然后保存。

    然后,in 会将我的数据作为自定义 xml 部分注入其中,然后保存。 (此步骤您可以使用 OpenXML SDK 完成,如果您需要 Word 更新您的某些下游流程的绑定,也可以在 Word 中完成)

    【讨论】:

    • 感谢您的回答,您能否详细说明最后一部分:“然后,将我的数据作为自定义 xml 部分注入其中,并保存。”这可能就是这样做的方法。
    • 您可以在 word 中创建内容控件并将它们与 xml 文件绑定在一起。该 xml 文件也将保存到您的 word 文档中。替换 xml 文件将更改文档的显示数据。我建议您查看 word content control toolkit 为您进行绑定。
    【解决方案5】:

    关于上面的答案,我同意 J. Vermeire 的观点,即 OpenXML 是要走的路。三年多来,我一直在使用基于 OpenXML 的工具包,它可以生成从模板和数据库数据合并的 .docx 文档。有一个示例如何使用它here。该示例展示了如何同时使用一个文档,要使用更多文档,只需添加一个循环并调用一个方法来生成文档。

    【讨论】:

    • 更新链接将不胜感激,看起来链接中的数据在您在这里发布 7 个月后被删除
    • 引用的文章已于 2015 年 7 月 10 日删除,其最新版本可在强大的 WebArchive 中以web.archive.org/web/20150607050033/https://www.codeproject.com/… 的形式获得。无论如何,它是关于 Docentric Toolkit,它是一个付费图书馆......
    【解决方案6】:

    我创建了开源库:docxtemplater,它允许从模板创建 word 文档。

    在您的模板中编写:

    Dear {firstname},
    

    你的代码很简单:

    import Docxtemplater from "docxtemplater";
    
    const doc = new Docxtemplater(document1);
    
    doc.render({firstname: "John"});
    

    【讨论】:

      【解决方案7】:

      添加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
              {
      
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-10
        相关资源
        最近更新 更多