Как изменить содержимое элемента управления содержимым в Word 2007 с помощью OpenXML SDK 2.0?

собирается сойти с ума от этой проблемы. Я уверен, что это так просто, я просто пропустил, но я не могу за жизнь мне выяснить, как изменить содержание контроля содержание в Word 2007 с помощью инструкции OpenXML SDK версии 2.0 на языке C#.

Я создал документ Word с элементом управления содержимым обычного текста. Тег для этого элемента управления - "FirstName". В коде я хотел бы открыть документ Word, найти этот элемент управления содержимым и изменить содержимое, не теряя форматирование.

решение, которое я наконец-то получил, включало поиск элемента управления содержимым, вставку запуска после него, а затем удаление элемента управления содержимым как такового:

using (WordprocessingDocument wordProcessingDocument = WordprocessingDocument.Open(filePath, true)) {
MainDocumentPart mainDocumentPart = wordProcessingDocument.MainDocumentPart;
SdtRun sdtRun = mainDocumentPart.Document.Descendants<SdtRun>()
 .Where(run => run.SdtProperties.GetFirstChild<Tag>().Val == "FirstName").Single();

if (sdtRun != null) {
 sdtRun.Parent.InsertAfter(new Run(new Text("John")), sdtRun);
 sdtRun.Remove();
}

это изменяет текст, но я теряю все форматирование. Кто-нибудь знает как я могу это сделать?

5 ответов


Я нашел лучший способ сделать это, используя http://wiki.threewill.com/display/enterprise/SharePoint+and+Open+XML#SharePointandOpenXML-UsingWord2007ContentControls в качестве ссылки. Ваши результаты могут отличаться, но я думаю, что это поможет вам хорошо начать:

using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(filePath, true)) {
    var sdtRuns = mainDocumentPart.Document.Descendants<SdtRun>()
        .Where(run => run.SdtProperties.GetFirstChild<Tag>().Val.Value == contentControlTagValue);

    foreach (SdtRun sdtRun in sdtRuns) {
        sdtRun.Descendants<Text>().First().Text = replacementText;
    }

    wordprocessingDocument.MainDocumentPart.Document.Save();
}

Я думаю, что выше будет работать только для элементов управления текстовым контентом. К сожалению, он не избавляется от элемента управления содержимым в итоговом документе. Если я получу эту работу, я опубликую он.

http://msdn.microsoft.com/en-us/library/cc197932.aspx также является хорошей ссылкой, Если вы хотите найти элемент управления содержимым rich text. В этом разделе рассказывается о добавлении строк в таблицу,помещенную в элемент управления содержимым rich text.


ваш первый подход к удалению sdtRun и добавлению нового, очевидно, удалит форматирование, потому что вы добавляете только Run, но не RunStyle. Чтобы сохранить форматирование, вы должны создать элементы run, такие как

new Run( new RunProperties(new RunStyle(){ Val = "MyStyle" }),
                            new Text("Replacement Text"));

ваш второй подход, чтобы заменить все Decendants<Text> будет работать для управления содержимым обычного текста только потому, что элемент управления содержимым обогащенного текста не имеет элемента SdtRun. Rich Text Content Control-это SdtBlock с элементами SdtContent. Богатый текстовый контент управление может иметь несколько абзацев, несколько запусков и несколько текстов. Итак, ваш код,sdtRun.Descendants<Text>().First().Text = replacementText, будет иметь недостатки для управления содержимым богатого текста. Нет кода одной строки, чтобы заменить весь текст элемента управления богатым содержимым и сохранить все форматирование.

Я не понял, что вы подразумеваете под "Он не избавляется от контроля содержания в итоговом документе"? Я думал, что ваше требование здесь-изменить текст (контент) только путем сохранения контроля содержимого и форматирование.


один отличный способ решить, как достичь желаемого результата, - использовать инструмент отражатель документов, который поставляется с Open XML SDK 2.0....

например, можно:

  1. в диалоговом окне Свойства для каждого элемента управления содержимым в документ, установите флажок "удалить элемент управления содержимым при редактировании содержимого".
  2. заполните их и сохраните как новый документ.
  3. используйте рефлектор для того чтобы сравнить оригинал и сохраненное версия.
  4. Нажмите кнопку Показать / Скрыть код, и он покажет вам код, необходимый для превращения оригинала в заполненную версию.

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

это несколько хрупкий способ сделать это, потому что Wordprocessing ML может быть сложным; его легко испортить. Для простых текстовых элементов управления I просто используйте этот метод:

private void FillSimpleTextCC(SdtRun simpleTextCC, string replacementText)
    {
        // remove the showing place holder element      
        SdtProperties ccProperties = simpleTextCC.SdtProperties;
        ccProperties.RemoveAllChildren<ShowingPlaceholder>();

        // fetch content block Run element            
        SdtContentRun contentRun = simpleTextCC.SdtContentRun;
        var ccRun = contentRun.GetFirstChild<Run>();

        // if there was no placeholder text in the content control, then the SdtContentRun
        // block will be empty -> ccRun will be null, so create a new instance
        if (ccRun == null)
        {
            ccRun = new Run(
                new RunProperties() { RunStyle = null },
                new Text());
            contentRun.Append(ccRun);
        }

        // remove revision identifier & replace text
        ccRun.RsidRunProperties = null;
        ccRun.GetFirstChild<Text>().Text = replacementText;

        // set the run style to that stored in the SdtProperties block, if there was
        // one. Otherwise the existing style will be used.            
        var props = ccProperties.GetFirstChild<RunProperties>();
        if (props != null)
        if (props != null)
        {
            RunStyle runStyle = props.RunStyle;
            if (runStyle != null)
            {
                // set the run style to the same as content block property style.
                var runProps = ccRun.RunProperties;
                runProps.RunStyle = new RunStyle() { Val = runStyle.Val };
                runProps.RunFonts = null;
            }
        }
    }

надеюсь, что это каким-то образом поможет. : D


Мне тоже пришлось найти и заменить текст в колонтитулах. Вы можете найти их, используя следующий код:

using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(file.PhysicalFile.FullName, true)) {
    foreach (FooterPart footerPart in wordprocessingDocument.MainDocumentPart.FooterParts) {
        var footerPartSdtRuns = footerPart.Footer.Descendants<SdtRun>()
            .Where(run => run.SdtProperties.GetFirstChild<Tag>().Val.Value == contentControlTag);

        foreach (SdtRun sdtRun in footerPartSdtRuns) {
           sdtRun.Descendants<Text>().First().Text = replacementTerm;
        }
    }

    wordprocessingDocument.MainDocumentPart.Document.Save();
}

другое решение было бы

        SdtRun rOld = p.Elements<SdtRun>().First();

        string OldNodeXML = rOld.OuterXml;
        string NewNodeXML = OldNodeXML.Replace("SearchString", "ReplacementString");

        SdtRun rNew = new SdtRun(NewNodeXML);


        p.ReplaceChild<SdtRun>(rNew, rOld);