简体   繁体   English

OpenXML将文本插入到内容控件Word 2007中

[英]OpenXML insert text into content control Word 2007

I am learning OpenXML. 我正在学习OpenXML。 I have been looking for hours trying to find how to do a simple task: insert text into a content control in c#. 我一直在寻找几个小时试图找到如何做一个简单的任务:在c#中的内容控件中插入文本。

I have a template document with two controls "Name" and "Age." 我有一个模板文档,其中包含两个控件“Name”和“Age”。 I can find them well enough, but I just cannot add text in them. 我可以很好地找到它们,但我无法在其中添加文本。 I've tried a number of things, all to no avail. 我尝试过很多东西,都无济于事。

        byte[] templateBytes = System.IO.File.ReadAllBytes(fileName);
        using (MemoryStream templateStream = new MemoryStream())
        {
            templateStream.Write(templateBytes, 0, (int)templateBytes.Length);

            using (WordprocessingDocument outDoc = WordprocessingDocument.Open(templateStream, true))
            {
                MainDocumentPart mainPart = outDoc.MainDocumentPart;

                foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>().ToList())
                {
                    SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();

                    if (alias != null)
                    {
                        string sdtTitle = alias.Val.Value;

                        switch (sdtTitle)
                        {
                            case "Name":
                                // ¿Qué?
                                break;
                            case "Age":
                                // ¿Qué?
                                break;
                        }
                    }
                }

                outDoc.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
            }

            using (FileStream fileStream = new FileStream(savePath, System.IO.FileMode.CreateNew))
            {
                templateStream.WriteTo(fileStream);
            }
        }

All help greatly appreciated. 所有帮助非常感谢。

Cheers, 干杯,

Tim. 蒂姆。

EDIT -- 编辑 -

Thanks for the response. 谢谢你的回复。 Taking your advice, I've attempted to cast and drilled down with the productivity tool to find the child elements to update. 根据您的建议,我尝试使用生产力工具进行投射和挖掘,以找到要更新的子元素。 Could you tell me if you can see why this code is simply not writing anything to the document? 你能不能告诉我你是否可以看到为什么这段代码根本没有写任何文件?

        foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>().ToList())
                {
                    SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();

                    if (alias != null)
                    {
                        SdtRun xRun = (SdtRun)sdt;
                        SdtContentRun xContentRun = xRun.Descendants<SdtContentRun>().FirstOrDefault();
                        Run xRun = xContentRun.Descendants<Run>().FirstOrDefault();
                        Text xText = xRun.Descendants<Text>().FirstOrDefault();

                        string sdtTitle = alias.Val.Value;

                        switch (sdtTitle)
                        {
                            case "Name":
                                xText.Text = "Whatever";                  
                                break;
                            case "Age":                    
                                xText.Text = "69";
                                break;
                        }
                    }     
                }

You need to cast your SdtElement to whatever it is, in order to get at its content child. 您需要将SdtElement转换为它的任何内容,以便获取其内容子项。

For example, if its an SdtBlock: 例如,如果它是一个SdtBlock:

    ((SdtBlock)sdt).SdtContentBlock

Then you can add stuff (eg add children) to that. 然后你可以添加东西(例如添加孩子)。

From MSDN , the inheritance hierarchy: 从MSDN ,继承层次结构:

 DocumentFormat.OpenXml.Wordprocessing.SdtElement
     DocumentFormat.OpenXml.Wordprocessing.SdtBlock
     DocumentFormat.OpenXml.Wordprocessing.SdtCell
     DocumentFormat.OpenXml.Wordprocessing.SdtRow
     DocumentFormat.OpenXml.Wordprocessing.SdtRun
     DocumentFormat.OpenXml.Wordprocessing.SdtRunRuby

Anyone wanting the code in VB format to do a straight find/replace of a key/value dictionary array... 任何想要VB格式的代码直接查找/替换键/值字典数组的人...

            Using document As WordprocessingDocument = WordprocessingDocument.Open(cls_sNewFilename, True)
                Dim mainPart As MainDocumentPart = document.MainDocumentPart
                Dim body As Body = mainPart.Document.Body

                'if custom xml content exists, delete it first
                mainPart.DeleteParts(Of CustomXmlPart)(mainPart.CustomXmlParts)

                For Each sdt As SdtElement In body.Descendants(Of SdtElement)().ToList()
                    Dim [alias] As SdtAlias = sdt.Descendants(Of SdtAlias)().FirstOrDefault()

                    If [alias] IsNot Nothing Then

                        If sdt.ToString() = "DocumentFormat.OpenXml.Wordprocessing.SdtRun" Then
                            Dim xStdRun As SdtRun = DirectCast(sdt, SdtRun)
                            Dim xStdContentRun As SdtContentRun = xStdRun.Descendants(Of SdtContentRun)().FirstOrDefault()
                            Dim xRun As Run = xStdContentRun.Descendants(Of Run)().FirstOrDefault()
                            Dim xText As Text = xRun.Descendants(Of Text)().FirstOrDefault()
                            Dim sdtTitle As String = [alias].Val.Value

                            xText.Text = dictReplacements.Item(sdtTitle)

                        ElseIf sdt.ToString() = "DocumentFormat.OpenXml.Wordprocessing.SdtBlock" Then
                            Dim xStdBlock As SdtBlock = DirectCast(sdt, SdtBlock)
                            Dim xStdContentBlock As SdtContentBlock = xStdBlock.Descendants(Of SdtContentBlock)().FirstOrDefault()
                            Dim xRun As Run = xStdContentBlock.Descendants(Of Run)().FirstOrDefault()
                            Dim xText As Text = xStdContentBlock.Descendants(Of Text)().FirstOrDefault()
                            Dim sdtTitle As String = [alias].Val.Value

                            xText.Text = dictReplacements.Item(sdtTitle)
                        End If
                    End If
                Next

                mainPart.Document.Save()
                document.Close()
            End Using

for some reason the last part seems to be sdtBlock instead of sdtRun hence the ElseIf..! 由于某种原因,最后一部分似乎是sdtBlock而不是sdtRun因此ElseIf ..!

After many hours of pain, I solved it. 经过几个小时的痛苦,我解决了它。

Two things were the problem: 1) I needed a mainPart.Document.Save(); 问题有两个:1)我需要一个mainPart.Document.Save(); command in there. 命令在那里。 2) I had added a customXmlPart with the Content Control Toolkit. 2)我添加了一个带有Content Control Toolkit的customXmlPart。 So I assume that this customxml part was overriding the text I was adding with the code, because when I went back into the content control toolkit and deleted the xml part, it worked. 所以我假设这个customxml部分覆盖了我在代码中添加的文本,因为当我回到内容控制工具包并删除xml部分时,它起作用了。

Thanks again plutext for putting me onto the solution! 再次感谢plutext让我加入解决方案!

顺便说一句,在foreach之前添加以下代码行将自动清除任何现有的自定义xml:

mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts);

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

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