I am looking for a way to insert some text after a bookmark in a word doc using openxml. So far, i have been able to locate the bookmark using the following:
var bookmarks = mainPart.Document.Descendants<BookmarkStart>().ToList();
var bookMarkToWriteAfter = bookmarks.FirstOrDefault(bm => bm.Name == insertAfterBoomark.Name);
This bookmark in the word doc is a selection of two lines in the doc. I have to insert some text right after the two line selection. I have 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 produce the desired result. Does anyone know of the correct way to insert text right after a bookmark in a word doc using openxml?
Right click on your project on Solution Explorer, and you should see the Add Reference option. Once selected, click on the Browser tab and browser the folder C:\Program Files\Open XML SDK\V2. 0\lib and select DocumentFormat. OpenXml.
The content of the paragraph is contained in one or more runs (<w:r>). Runs are non-block content; they define regions of text that do not necessarily begin on a new line. Like paragraphs, they are comprised of formatting/property definitions, followed by content.
Bold fbld = new Bold();
The Open XML SDK provides tools for working with Office Word, Excel, and PowerPoint documents. It supports scenarios such as: - High-performance generation of word-processing documents, spreadsheets, and presentations. - Populating content in Word files from an XML data source.
using
bookMarkToWriteAfter.Parent.InsertAfterSelf(run);
you are trying to work with XML directly which is not always advisable with OpenXML.
Try This..
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();
You can not assume that a bookmark starts and ends in one paragraph. Bookmarks can start and end in different elements and be children of:
bdo (§17.3.2.3); body (§17.2.2); comment (§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); endnote (§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 you need to look at all the 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 may want to check that a Run can be added to the parent and add to a different ancestor or create a new Paragraph.
(I would have liked to have added this as a comment to Flowerking's answer but I can't comment so I have modified their code in this answer.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With