Я рекомендую использовать Content Controls. Использование их для разметки областей вашего документа, где вы хотите выполнить подстановку, безусловно, самый простой способ сделать это.
Что касается дублирования документа (и сохранения всего содержимого документа, стилей и всего), то это относительно просто:
string documentURL = "full URL to your document";
byte[] docAsArray = File.ReadAllBytes(documentURL);
using (MemoryStream stream = new MemoryStream)
{
stream.Write(docAsArray, 0, docAsArray.Length); // THIS performs doc copy
using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
{
// perform content control substitution here, making sure to call .Save()
// on any documents Part's changed.
}
File.WriteAllBytes("full URL of your new doc to save, including .docx", stream.ToArray());
}
На самом деле найти элементы управления контентом - это очень просто, используя LINQ. В следующем примере отображаются все элементы управления содержимым простого текста (которые имеют тип SdtRun):
using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
{
var mainDocument = doc.MainDocumentPart.Document;
var contentControls = from sdt in mainDocument.Descendants<SdtRun>() select sdt;
foreach (var cc in contentControls)
{
// drill down through the containment hierarchy to get to
// the contained <Text> object
cc.SdtContentRun.GetFirstChild<Run>().GetFirstChild<Text>().Text = "my replacement string";
}
}
Элементы <Run>
и <Text>
могут еще не существовать, но создать их просто, как:
cc.SdtContentRun.Append(new Run(new Text("my replacement string")));
Надеюсь, это кому-нибудь поможет. : D