如何从模板以编程方式创建word文档

时间:2010-11-29 13:34:21

标签: c# ms-word office-interop

我正在尝试在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标题对象中的文本填写文档。

6 个答案:

答案 0 :(得分:12)

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

看看Open XML。你可以在下面找到关于它的负载:

http://openxmldeveloper.org/

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

答案 1 :(得分:6)

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

Document.SelectContentControlsByTitle

答案 2 :(得分:5)

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

,则应阅读有关OpenXML格式的信息

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

答案 3 :(得分:3)

这里似乎有两个问题:

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

  2. 如何填充文档。

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

    OP的焦点看起来是Q1。

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

    所以我看到你有4个选择:

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

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

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

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

    5. 我吗?我将在Word中创建一个包含数据绑定内容控件的docx,并保存它。

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

答案 4 :(得分:0)

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

答案 5 :(得分: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
        {

        }
    }