简体   繁体   English

OpenXML / DocumentFormat.OpenXml用文字将Excel设置为MailMerge的数据源(字母系列)

[英]OpenXML/DocumentFormat.OpenXml set excel as DataSource for MailMerge in word (Letter series)

I try to set an excel file as Address-List-Source in word (as recipient), so that i can use MailMerge to create a word letter series (for example for 100 addresses). 我尝试将Excel文件设置为Word中的Address-List-Source(作为收件人),以便我可以使用MailMerge创建单词字母系列(例如,用于100个地址)。

I wrote the following code using DocumentFormat.OpenXml , but when i open my DocX file, there is no data source. 我使用DocumentFormat.OpenXml编写了以下代码,但是当我打开DocX文件时,没有数据源。

I use the following code: 我使用以下代码:

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

Does any one solved this problem before? 有人解决过这个问题吗?

EDIT 编辑

I added the relationship logic, but now word say, that it could not found C:\\test.xlsx . 我添加了关系逻辑,但现在可以说找不到C:\\test.xlsx But it exists at the correct place und C:\\ . 但是它存在于C:\\的正确位置。

There is also the SQL-Statement missing: 还缺少SQL语句:

在此处输入图片说明

EDIT 2 编辑2

if i create the query like this: 如果我创建这样的查询:

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

The select-query will be embedded correctly in the docx. 选择查询将正确嵌入到docx中。

But the error with the missing Test.xlsx still exists... 但是缺少Test.xlsx的错误仍然存​​在...

There are at least two problems: 至少有两个问题:

  1. The attributes are not correctly qualified. 该属性未正确限定。 In the .docx, they appear as val="whatever", but they need to be w:val="whatever". 在.docx中,它们显示为val =“ whatever”,但必须为w:val =“ whatever”。

You should be able to fix that by using eg 您应该能够通过使用例如

string xmlnsw = @"http://schemas.openxmlformats.org/wordprocessingml/2006/main";

then changing all the SetAttribute statments so that you have, eg 然后更改所有SetAttribute陈述,以便您拥有例如

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

(I would guess there is a better way to code that that draws on existing constant definitions in the Open XML SDK). (我想有一种更好的编码方法可以利用Open XML SDK中的现有常量定义)。

  1. You also need to (re-)create at least one of the Relationships specified in the w:mailMerge XML. 您还需要(重新)创建w:mailMerge XML中指定的至少一种关系。 (But you have already changed your code to reflect that). (但是您已经更改了代码以反映这一点)。

Some additional comments... 一些其他评论...

As far as I can tell, your existing code only modifies one of the relationships. 据我所知,您现有的代码仅修改了一种关系。 Since Microsoft's documentation suggests that Word never "uses" the "src" attribute of the odso element, that is probably OK. 由于Microsoft的文档建议Word永远不要“使用” odso元素的“ src”属性,因此可能是可以的。 Word does, however, create and populate the src element, so I am not certain that it never "uses" it. 但是,Word确实会创建并填充src元素,因此我不确定它永远不会“使用”它。

In fact, for this type of data source, I think you could probably remove the entire odso element and the associated relationship anyway. 实际上,对于这种类型的数据源,我认为您可能仍然可以删除整个odso元素及其关联的关系。 For a text type data source you might need the odso element if only to specify the field delimiter character. 对于文本类型数据源,如果仅用于指定字段定界符,则可能需要odso元素。

Your code seems to be trying to remove the existing relationships. 您的代码似乎正在尝试删除现有关系。 It did not do so here, but I have not tried to discover why. 它在这里没有这样做,但是我没有尝试发现原因。 I do not think that will cause a problem except that the number of unreferenced relationships will increase every time you run this code against a given file. 我认为这不会引起任何问题,除了每次对给定文件运行此代码时,未引用关系的数量都会增加。

My guess is that you could also either omit the ConnectString attribute or leave it empty (it depends on what the .docx schemas require). 我的猜测是,您也可以省略ConnectString属性或将其保留为空(取决于.docx模式的要求)。 In recent versions of Word you only usually need to specify the file name and the query for Word to make a successful connection. 在最新版本的Word中,通常只需要指定文件名和对Word的查询即可建立成功的连接。 If specifying the ConnectString actually causes Word to use the ConnectString (rather than generate its own), there could be a problem if, for example, you were opening with Word 2003 (which used the Jet provider rather than the ACE provider). 如果指定ConnectString实际上导致Word使用ConnectString(而不是生成它自己的),例如,如果您使用Word 2003(使用Jet提供程序而不是ACE提供程序)打开,则可能会出现问题。 It is interesting that Word itself creates and stores a COnnectString with an Engine Type number (37 in this case, I think) rather than a name ("Excel 12.0 Xml") in the Extended Properties. 有趣的是,Word本身会在扩展属性中创建并存储带有引擎类型编号(在本例中为37)而不是名称(“ Excel 12.0 Xml”)的COnnectString。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM