OpenXML вставляет текст в управление контентом Word 2007 - PullRequest
3 голосов
/ 28 сентября 2010

Я изучаю OpenXML. Я искал несколько часов, пытаясь найти способ выполнить простую задачу: вставить текст в элемент управления контентом в c #.

У меня есть шаблон документа с двумя элементами управления «Имя» и «Возраст». Я могу найти их достаточно хорошо, но я просто не могу добавить в них текст. Я перепробовал несколько вещей, но все безрезультатно.

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

Вся помощь очень ценится.

Приветствия

Тим.

РЕДАКТИРОВАТЬ -

Спасибо за ответ. Следуя вашим советам, я попытался использовать инструмент повышения производительности, чтобы найти дочерние элементы для обновления. Не могли бы вы сказать мне, если вы видите, почему этот код просто ничего не записывает в документ?

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

Ответы [ 4 ]

6 голосов
/ 29 сентября 2010

Вам нужно привести свой SdtElement к тому, чем он является, чтобы получить его дочерний контент.

Например, если это SdtBlock:

    ((SdtBlock)sdt).SdtContentBlock

Затем вы можете добавить к этому вещи (например, добавить детей).

Из 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
1 голос
/ 09 апреля 2013

Любой, кто хочет, чтобы код в формате 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

по какой-то причине последняя часть кажется sdtBlock вместо sdtRun, следовательно ElseIf ..!

1 голос
/ 29 сентября 2010

После многих часов боли я решил ее.

Проблема заключалась в двух вещах: 1) мне был нужен mainPart.Document.Save ();команда там.2) Я добавил customXmlPart с инструментарием управления контентом.Поэтому я предполагаю, что эта часть customxml переопределяла текст, который я добавлял вместе с кодом, потому что, когда я вернулся в инструментарий управления контентом и удалил часть xml, он работал.решение!

0 голосов
/ 09 апреля 2013

Кстати, добавление следующей строки кода перед foreach автоматически очистит любой существующий пользовательский xml:

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