1

I'm using DocumentFormat.OpenXml to replace merge fields in my template docx file.

Step 1, I write method to find merge field

            var instructionRegEx = new Regex(@"[\w]*\sMERGEFIELD\s+(?<name>[\w]+)", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);

            string GetFieldName(OpenXmlElement field)
            {
                string outerXml = field.OuterXml;
                if (!string.IsNullOrEmpty(outerXml))
                {
                    Match m = instructionRegEx.Match(outerXml);
                    if (m.Success)
                    {
                        return m.Groups["name"].ToString().Trim();
                    }
                }
                return string.Empty;
            }

            using (var docx = WordprocessingDocument.Open(filePath, true))
            {
                var fields = docx.MainDocumentPart.RootElement.Descendants<SimpleField>().Select(item => (OpenXmlElement)item)
                    .Concat(docx.MainDocumentPart.RootElement.Descendants<FieldCode>().Select(item => (OpenXmlElement)item))
                    .ToList();
                foreach (var field in fields)
                {
                    var name = GetFieldName(field);
                    if (string.IsNullOrEmpty(name)) continue;
                    switch (name)
                    {
                     ///
                    }
                }
            }

Step 2, I write method to replace html text

 public static void ReplaceHtml(this WordprocessingDocument document, OpenXmlElement el, string html, bool disableHtmlHeader = false, string color = "", string alignment = "", string lineHeight = "", bool removeStyle = true)
        {
            var formatImportPart = document.MainDocumentPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html);
            var idOfPart = document.MainDocumentPart.GetIdOfPart(formatImportPart);
            var convertedHtml = html.ConvertHtmlContent(disableHtmlHeader: disableHtmlHeader, aligment: alignment, color: color, lineHeight: lineHeight, removeStyle: removeStyle);
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(convertedHtml)))
            {
                formatImportPart.FeedData(ms);
            }
            var altChunk = new AltChunk
            {
                Id = idOfPart
            };
            var r = new Run();
            foreach (RunProperties placeholderrpr in el.Parent.Descendants<RunProperties>())
            {
                r.Append(new RunProperties(placeholderrpr.OuterXml));
            }
            r.Append(altChunk);
            ReplaceElement(el, r);
        }
private static void ReplaceElement(OpenXmlElement el, OpenXmlElement newEl)
        {
            if (el == null) return;
            if (el is SimpleField)
            {
                el.Parent.ReplaceChild(newEl, el);
            }
            else if (el is FieldCode)
            {
                var parent = el.Parent;
                var begin = parent.PreviousSibling();
                var separate = parent.NextSibling();
                var runText = separate.NextSibling();
                var end = runText.NextSibling();
                var another = end.NextSibling();
                var container = parent.Parent;                    
                container.InsertAfter(newEl, parent);
                container.RemoveChild(parent);
                container.RemoveChild(begin);
                container.RemoveChild(separate);
                container.RemoveChild(runText);
                container.RemoveChild(end);
            }
        }

Code work well when after RemoveChild, the paragraph that contains merge field become empty. But if it still contains some element, the docx file after replace merge fields will corrupt. I've open docx file by xml tool, and see results are as follows: enter image description here

enter image description here

So, my question is, how can I replace a merge field inside a paragraph that contains another fields. Sorry for my English not good

4
  • Why aren't you deleting the entire paragraph's Descendents, then? If you do that you wouldn't even need to distinguish between simple and complex field codes? Commented Jul 16, 2018 at 13:49
  • Because paragraph not only contains the merge field, it can contains another text fields, break page... Commented Jul 16, 2018 at 16:04
  • Well, I can't read the text in your images - you should post the relevant part as plain text, in that case. But it's quite possible that the HTML you're passing simply can't be incorporated into a paragraph with other content. But there's really nothing more one can say without seeing that raw HTML... Commented Jul 16, 2018 at 16:26
  • i.sstatic.net/Iitcy.png Just click to the images, you will see very clearly Commented Jul 17, 2018 at 2:50

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.