Insert text after bookmark in openxml

I am looking for a way to insert text after a bookmark into a word doc using openxml. So far, I could find the bookmark using the following:

var bookmarks = mainPart.Document.Descendants<BookmarkStart>().ToList(); var bookMarkToWriteAfter = bookmarks.FirstOrDefault(bm => bm.Name == insertAfterBoomark.Name); 

This tab in the word doc is a selection of two lines in the document. I need to insert text right after selecting two lines. I tried to insert text using the following:

 var run = new Run(); run.Append(new Text("Hello World")); bookMarkToWriteAfter .Parent.InsertAfterSelf(run); mainPart.Document.Save(); 

This, however, does not give the desired result. Does anyone know the correct way to insert text right after bookmarking into word doc using openxml?

+6
source share
2 answers

using

 bookMarkToWriteAfter.Parent.InsertAfterSelf(run); 

You are trying to work directly with XML, which is not always desirable with OpenXML.

Try it.

  Body body = mainPart.Document.GetFirstChild<Body>(); var paras = body.Elements<Paragraph>(); //Iterate through the paragraphs to find the bookmarks inside foreach (var para in paras) { var bookMarkStarts = para.Elements<BookmarkStart>(); var bookMarkEnds = para.Elements<BookmarkEnd>(); foreach (BookmarkStart bookMarkStart in bookMarkStarts) { if (bookMarkStart.Name == bookmarkName) { //Get the id of the bookmark start to find the bookmark end var id = bookMarkStart.Id.Value; var bookmarkEnd = bookMarkEnds.Where(i => i.Id.Value == id).First(); var runElement = new Run(new Text("Hello World!!!")); para.InsertAfter(runElement, bookmarkEnd); } } } mainPart.Document.Save(); 
+7
source

You cannot assume that a bookmark begins and ends in a single paragraph. Bookmarks can start and end with different elements and be children:

bdo (ยง17.3.2.3); authority (ยง17.2.2); commentary (ยง17.13.4.2); customXml (ยง17.5.1.6); customXml (ยง17.5.1.4); customXml (ยง17.5.1.5); customXml (ยง17.5.1.3); deg (ยง22.1.2.26); del (ยง17.13.5.14); den (ยง22.1.2.28); dir (ยง17.3.2.8); docPartBody (ยง17.12.6); e (ยง22.1.2.32); footnote (ยง17.11.2); fldSimple (ยง17.16.19); fName (ยง22.1.2.37); footnote (ยง17.11.10); ftr (ยง17.10.3); hdr (ยง17.10.4); hyperlink (ยง17.16.22); ins (ยง17.13.5.18); lim (ยง22.1.2.52); moveFrom (ยง17.13.5.22); moveTo (ยง17.13.5.25); num (ยง22.1.2.75); oMath (ยง22.1.2.77); p (ยง17.3.1.22); rt (ยง17.3.3.24); rubyBase (ยง17.3.3.27); sdtContent (ยง17.5.2.34); sdtContent (ยง17.5.2.33); sdtContent (ยง17.5.2.35); sdtContent (ยง17.5.2.36); smartTag (ยง17.5.1.9); sub (ยง22.1.2.112); sup (ยง22.1.2.114); tbl (ยง17.4.38); tc (ยง17.4.66); tr (ยง17.4.79)

https://msdn.microsoft.com/en-gb/library/documentformat.openxml.wordprocessing.bookmarkstart(v=office.15).aspx

This means that you need to view all BookmarkEnd elements in the document when checking for the required BookmarkEnd element.

 Body body = mainPart.Document.GetFirstChild<Body>(); var bookMarkStarts = body.Descendants<BookmarkStart>(); var bookMarkEnds = body.Descendants<BookmarkEnd>(); foreach (BookmarkStart bookMarkStart in bookMarkStarts) { if (bookMarkStart.Name == bookmarkName) { //Get the id of the bookmark start to find the bookmark end var id = bookMarkStart.Id.Value; var bookmarkEnd = bookMarkEnds.Where(i => i.Id.Value == id).First(); var runElement = new Run(new Text("Hello World!!!")); bookmarkEnd.Parent.InsertAfter(runElement, bookmarkEnd); } } mainPart.Document.Save(); 

You might want to check that Run can be added to the parent and add another ancestor or create a new paragraph.

(I would like to add this as a comment on Flowerking's answers, but I cannot comment, so I changed their code in this answer.)

+1
source

Source: https://habr.com/ru/post/911114/


All Articles