OpenXML / DocumentFormat.OpenXml将excel设置为Word中的MailMerge的DataSource(Letter系列)

时间:2015-02-06 13:47:15

标签: c# ms-word openxml newsletter mailmerge

我尝试将word文件中的excel文件设置为Address-List-Source(作为收件人),这样我就可以使用MailMerge创建一个单词字母系列(例如100个地址)。

我使用DocumentFormat.OpenXml编写了以下代码,但是当我打开DocX文件时,没有数据源。

我使用以下代码:

        using (WordprocessingDocument wordDocument = WordprocessingDocument.Open("Microsoft Word-Dokument (neu).docx", true))
        {
            var settingsPart = wordDocument.MainDocumentPart.GetPartsOfType<DocumentSettingsPart>().First();

            var mailMerge = new MailMerge();

            mailMerge.MainDocumentType = new MainDocumentType();
            mailMerge.MainDocumentType.SetAttribute(new DocumentFormat.OpenXml.OpenXmlAttribute("val", null, "formatLetters"));

            string excel = @"C:\test.xlsx";

            mailMerge.LinkToQuery = new LinkToQuery();

            mailMerge.DataType = new DataType();
            mailMerge.DataType.SetAttribute(new DocumentFormat.OpenXml.OpenXmlAttribute("val", null, "native"));

            mailMerge.ConnectString = new ConnectString();
            mailMerge.ConnectString.SetAttribute(new OpenXmlAttribute("val", null, "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";"));

            mailMerge.Query = new Query();
            mailMerge.Query.SetAttribute(new OpenXmlAttribute("val", null, "SELECT * FROM `Tabelle1$`"));



            mailMerge.ViewMergedData = new ViewMergedData();

            mailMerge.DataSourceObject = new DataSourceObject();
            mailMerge.DataSourceObject.UdlConnectionString = new UdlConnectionString();
            mailMerge.DataSourceObject.UdlConnectionString.SetAttribute(new OpenXmlAttribute("val", null, "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";"));

            mailMerge.DataSourceObject.DataSourceTableName = new DataSourceTableName();
            mailMerge.DataSourceObject.DataSourceTableName.SetAttribute(new OpenXmlAttribute("val", null, "Tabelle1$"));

            mailMerge.DataSourceObject.ColumnDelimiter = new ColumnDelimiter();
            mailMerge.DataSourceObject.ColumnDelimiter.SetAttribute(new OpenXmlAttribute("val", null, "9"));

            settingsPart.Settings.RemoveAllChildren<MailMerge>();
            settingsPart.Settings.InsertAt<MailMerge>(mailMerge, 0);

            foreach (var relationship in wordDocument.ExternalRelationships.Where(Rel => Rel.RelationshipType == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/mailMergeSource"))
            {
                wordDocument.DeleteExternalRelationship(relationship);
            }

            string DataPath = excel;
            var dsRelationship = wordDocument.MainDocumentPart.DocumentSettingsPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/mailMergeSource", new Uri(string.Format("file:///{0}", DataPath)));

            if (mailMerge.DataSourceReference == null)
            {
                mailMerge.DataSourceReference = new DataSourceReference();
            }

            mailMerge.DataSourceReference.Id = dsRelationship.Id;
            mailMerge.ViewMergedData.Val = true;
        }

之前是否有人解决了这个问题?

修改

我添加了关系逻辑,但现在有人说,它找不到C:\test.xlsx。但它存在于正确的位置和C:\

还缺少SQL语句:

enter image description here

编辑2

如果我创建这样的查询:

mailMerge.Query = new Query()
{
    Val = "SELECT * FROM `Tabelle1$`"
};

选择查询将正确嵌入docx。

但缺少Test.xlsx的错误仍然存​​在......

1 个答案:

答案 0 :(得分:1)

至少有两个问题:

  1. 属性未正确限定。在.docx中,它们显示为val =&#34;无论&#34;,但它们必须是w:val =&#34;无论&#34;。
  2. 你应该能够通过使用例如

    来解决这个问题
    string xmlnsw = @"http://schemas.openxmlformats.org/wordprocessingml/2006/main";
    

    然后更改所有的SetAttribute状态,例如

    mailMerge.MainDocumentType.SetAttribute(new DocumentFormat.OpenXml.OpenXmlAttribute("val", xmlnsw, "formatLetters"));
    

    (我猜有一种更好的方法来编写利用Open XML SDK中现有常量定义的代码。)

    1. 您还需要(重新)创建至少一个w:mailMerge XML中指定的关系。 (但您已经更改了代码以反映这一点。)
    2. 一些额外的评论......

      据我所知,您现有的代码只修改其中一个关系。由于Microsoft的文档表明Word永远不会使用&#34; &#34; src&#34; odso元素的属性,这可能是好的。但是,Word确实会创建并填充src元素,因此我不确定它是否会使用&#34;它。

      事实上,对于这种类型的数据源,我认为你可以删除整个odso元素和相关的关系。对于文本类型数据源,如果仅指定字段分隔符,则可能需要odso元素。

      您的代码似乎试图删除现有的关系。它没有在这里这样做,但我没有试图发现原因。我不认为这会导致问题,除非每次针对给定文件运行此代码时,未引用关系的数量都会增加。

      我的猜测是你也可以省略ConnectString属性或将其留空(这取决于.docx架构需要什么)。在最新版本的Word中,您通常只需指定文件名和Word查询即可成功建立连接。如果指定ConnectString实际上导致Word使用ConnectString(而不是生成自己的),则可能会出现问题,例如,您使用Word 2003(使用Jet提供程序而不是ACE提供程序)打开它。有趣的是,Word本身创建并存储了一个COnnectString,其中包含引擎类型编号(在这种情况下为37),而不是扩展属性中的名称(&#34; Excel 12.0 Xml&#34;)。