public static GenerationResult SearchAndReplace(string document) { var unfilledTokens = new UnfilfilledTokens(); using (var templateStream = new MemoryStream()) { File.Open(document, FileMode.Open).CopyTo(templateStream); templateStream.Position = 0; using (var wordDoc = WordprocessingDocument.Open(templateStream, isEditable: true)) { var mainDocument = wordDoc.MainDocumentPart; //// https://stackoverflow.com/questions/31750228/replacing-text-of-content-controls-in-openxml#answer-31755783 var elements = mainDocument.Document.Body.Descendants <SdtElement>() .Concat(mainDocument.HeaderParts.SelectMany(x => x.Header.Descendants <SdtElement>())) .Concat(mainDocument.FooterParts.SelectMany(x => x.Footer.Descendants <SdtElement>())) .ToList(); //ReplaceTokensByName(elements, unfilledTokens); ReplaceTokensByTag(elements, unfilledTokens); wordDoc.SaveAs("./output.docx"); } } return(new GenerationResult { UnfilledTokens = unfilledTokens }); }
public static void ReplaceTokensByName(IEnumerable <SdtElement> fields, UnfilfilledTokens unfilledTokens) { foreach (var sdtElement in fields) { var alias = sdtElement.Descendants <SdtAlias>().FirstOrDefault(); if (alias == null) { continue; } var tokenName = alias.Val.Value; if (!Mappings.TryGetValue(tokenName, out Func <string> mappedValue)) { unfilledTokens.Add(tokenName); continue; } ReplaceElementValue(sdtElement, mappedValue()); } }
// https://msdn.microsoft.com/en-us/library/office/gg605189(v=office.14).aspx public static void ReplaceTokensByTag(IEnumerable <SdtElement> fields, UnfilfilledTokens unfilledTokens) { var tokens = fields .Select(x => new { Element = x, Tag = x.SdtProperties.GetFirstChild <Tag>() }) .Where(x => x.Tag != null) .Select(x => new { x.Element, Name = x.Tag.Val.Value }) .GroupBy(x => x.Name) .Select(g => new { Name = g.Key, Elements = g.Select(x => x.Element) }) .ToList(); foreach (var token in tokens) { Console.WriteLine(" Replacing token {0} x{1}", token.Name, token.Elements.Count()); if (token.Name == "table1") { // https://msdn.microsoft.com/en-us/library/cc197932(office.12).aspx var sdtElement = token.Elements.First(); var theTable = sdtElement.Descendants <Table>().Single(); var theRow = theTable.Elements <TableRow>().Last(); foreach (var data in new[] { new[] { "1", "2", "3" }, new[] { "10", "20", "30" } }) { var rowCopy = (TableRow)theRow.CloneNode(true); var cells = rowCopy.Descendants <TableCell>(); for (var i = 0; i < data.Length; i++) { cells.ElementAt(i).Append(new Paragraph(new Run(new Text(data[i])))); } //rowCopy.Descendants<TableCell>().ElementAt(0).Append(new Paragraph // (new Run(new Text(data.Contact.ToString())))); //rowCopy.Descendants<TableCell>().ElementAt(1).Append(new Paragraph // (new Run(new Text(data.NameOfProduct.ToString())))); //rowCopy.Descendants<TableCell>().ElementAt(2).Append(new Paragraph // (new Run(new Text(data.Amount.ToString())))); theTable.AppendChild(rowCopy); } theTable.RemoveChild(theRow); RemoveContentControl(sdtElement); continue; } if (token.Name == "repeat1") { // https://msdn.microsoft.com/en-us/library/cc197932(office.12).aspx var sdtElement = token.Elements.First(); var repeat = sdtElement.Descendants <SdtRepeatedSection>().First(); //var theTable = sdtElement.Descendants<Table>().Single(); //var theRow = theTable.Elements<TableRow>().Last(); foreach (var data in new[] { new[] { "1", "2", "3" }, new[] { "10", "20", "30" } }) { var clone = repeat.CloneNode(true); clone.InsertAfterSelf(repeat); //repeat.InsertBefore() //ReplaceTokensByTag(sdtElement.Descendants<SdtElement>(), unfilledTokens); } //theTable.RemoveChild(theRow); RemoveContentControl(sdtElement); continue; } if (!Mappings.TryGetValue(token.Name, out Func <string> mappedValue)) { unfilledTokens.Add(token.Name, token.Elements.Count()); continue; } ReplaceElementValue(token.Elements, mappedValue()); } }