Вставка текста после закладки в openxml

Я ищу способ вставить текст после закладки в документ Word с помощью openxml. Пока что мне удалось найти закладку, используя следующее:

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

Эта закладка в слове «документ» представляет собой выделение двух строк в документе. Мне нужно вставить текст сразу после выделения из двух строк. Я попытался вставить текст, используя следующее:

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

mainPart.Document.Save();

Однако это не дает желаемого результата. Кто-нибудь знает, как правильно вставить текст сразу после закладки в документ Word с помощью openxml?


person John Baum    schedule 19.03.2012    source источник


Ответы (2)


с использованием

bookMarkToWriteAfter.Parent.InsertAfterSelf(run);

вы пытаетесь работать с XML напрямую, что не всегда рекомендуется с OpenXML.

Попробуй это..

    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();
person Flowerking    schedule 19.03.2012
comment
У меня есть такое требование, что мне нужно сразу найти все закладки во всем документе. Это потому, что что-то общее делается для всех сразу, прежде чем я сделаю вставку текста. Так есть ли способ работать со всеми закладками сразу, а не разбивать их по абзацам? - person John Baum; 19.03.2012
comment
Вы можете получить список всех закладок и работать с ними (в зависимости от того, что вы пытаетесь с ними делать), но для вставки текста лучше вставлять с помощью элементов абзаца. - person Flowerking; 19.03.2012

Нельзя считать, что закладка начинается и заканчивается одним абзацем. Закладки могут начинаться и заканчиваться разными элементами и быть дочерними по отношению к:

bdo (§17.3.2.3); тело (§17.2.2); комментарий (§17.13.4.2); customXml (§17.5.1.6); customXml (§17.5.1.4); customXml (§17.5.1.5); customXml (§17.5.1.3); град (§22.1.2.26); дель (§17.13.5.14); ден (§22.1.2.28); dir (§17.3.2.8); docPartBody (§17.12.6); е (§22.1.2.32); сноска (§17.11.2); fldSimple (§17.16.19); fName (§22.1.2.37); сноска (§17.11.10); ftr (§17.10.3); hdr (§17.10.4); гиперссылка (§17.16.22); ins (§17.13.5.18); lim (§22.1.2.52); moveFrom (§17.13.5.22); moveTo (§17.13.5.25); число (§22.1.2.75); oMath (§22.1.2.77); р (§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); подпункт (§22.1.2.112); sup (§22.1.2.114); таблица (§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

Это означает, что вам нужно просмотреть все элементы BookmarkEnd в документе при проверке наличия необходимого элемента BookmarkEnd.

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();

Вы можете проверить, что Run можно добавить к родительскому элементу и добавить к другому предку или создать новый абзац.

(Мне бы хотелось добавить это в качестве комментария к ответу Flowerking, но я не могу комментировать, поэтому я изменил их код в этом ответе.)

person Adam    schedule 06.11.2016