Как изменить содержимое элемента управления содержимым в 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....
например, можно:
- в диалоговом окне Свойства для каждого элемента управления содержимым в документ, установите флажок "удалить элемент управления содержимым при редактировании содержимого".
- заполните их и сохраните как новый документ.
- используйте рефлектор для того чтобы сравнить оригинал и сохраненное версия.
- Нажмите кнопку Показать / Скрыть код, и он покажет вам код, необходимый для превращения оригинала в заполненную версию.
это не идеально, но это удивительно полезно. Вы также можете просто посмотреть непосредственно на разметку любого документа и увидеть изменения, вызванные заполнением элементов управления.
это несколько хрупкий способ сделать это, потому что 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);