1

ブックマークの内容を置き換えるための実用的なコード例が見つかりません。コードは、空のブックマークを置き換える場合と、ブックマークを既存のコンテンツに置き換える場合の両方を処理できる必要があります。

例: Word 文書に次のテキストがある場合:

「次の期間の間に Bookmark1.. 次の期間の間に Bookmark2 が来る..」

最初のピリオドの間に「BM1」というテキストを挿入し、次のピリオドの間に「BM2」というテキストを挿入します。

最初の交換実行後、交換品は正しく挿入されます。

しかし、次の置換の実行後、Bookmark1 の後の行のすべてのテキストが削除され、Bookmark2 の置換が挿入されます。

これは私のC#コードです:

    var doc = WordprocessingDocument.Open(@"file.docx", true);

    public static Dictionary<string, wd.BookmarkStart> FindAllBookmarksInWordFile(WordprocessingDocument file)
    {
        var bookmarkMap = new Dictionary<String, wd.BookmarkStart>();


        foreach (var headerPart in file.MainDocumentPart.HeaderParts)
        {
            foreach (var bookmarkStart in headerPart.RootElement.Descendants<wd.BookmarkStart>())
            {
                if (!bookmarkStart.Name.ToString().StartsWith("_"))
                    bookmarkMap[bookmarkStart.Name] = bookmarkStart;
            }
        }

        foreach (var bookmarkStart in file.MainDocumentPart.RootElement.Descendants<wd.BookmarkStart>())
        {
            if (!bookmarkStart.Name.ToString().StartsWith("_"))
                bookmarkMap[bookmarkStart.Name] = bookmarkStart;
        }


        return bookmarkMap;
    }
    /*extension methods*/
    public static bool IsEndBookmark(this OpenXmlElement element, BookmarkStart startBookmark)
    {
        return IsEndBookmark(element as BookmarkEnd, startBookmark);
    }

    public static bool IsEndBookmark(this BookmarkEnd endBookmark, BookmarkStart startBookmark)
    {
        if (endBookmark == null)
            return false;

        return endBookmark.Id.Value == startBookmark.Id.Value;
    }
    /* end of extension methods */

    public static void SetText(BookmarkStart bookmark, string value)
    {
        RemoveAllTexts(bookmark);

        bookmark.Parent.InsertAfter(new Run(new Text(value)), bookmark);
    }

    private static void RemoveAllTexts(BookmarkStart bookmark)
    {
        if (bookmark.ColumnFirst != null) return;

        var nextSibling = bookmark.NextSibling();

        while (nextSibling != null)
        {
            if (nextSibling.IsEndBookmark(bookmark) || nextSibling.GetType() == typeof(BookmarkStart))
                break;

            foreach (var item in nextSibling.Descendants<Text>())
            {
                item.Remove();
            }
            nextSibling = nextSibling.NextSibling();
        }
    }

私は長い間、一般的な解決策を探してきました。どんな助けでも大歓迎です!-ビクター

4

2 に答える 2

1

多分これは最初にあなたを助けることができます:delete bookmarkContent 2番目:find bookMark => insert value

        public static void InsertTest1(WordprocessingDocument doc, string bookMark, string txt)
            {
                try
                {
                    RemoveBookMarkContent(doc, bookMark);

                    MainDocumentPart mainPart = doc.MainDocumentPart;

                    BookmarkStart bmStart = findBookMarkStart(doc, bookMark);
                    if (bmStart == null)
                    {
                        return;
                    }
                    Run run = new Run(new Text(txt));
                    bmStart.Parent.InsertAfter<Run>(run, bmStart);
                }
                catch (Exception c)
                {
                    //not Exception
                }
            }
    public static void RemoveBookMarkContent(WordprocessingDocument doc, string bmName)
            {
                BookmarkStart bmStart = findBookMarkStart(doc, bmName);
                BookmarkEnd bmEnd = findBookMarkEnd(doc, bmStart.Id);
                while (true)
                {
                    var run = bmStart.NextSibling();
                    if (run == null)
                    {
                        break;
                    }
                    if (run is BookmarkEnd && (BookmarkEnd)run == bmEnd)
                    {
                        break;
                    }

                    run.Remove();
                }
            }
private static BookmarkStart findBookMarkStart(WordprocessingDocument doc, string bmName)
        {
            foreach (var footer in doc.MainDocumentPart.FooterParts)
            {
                foreach (var inst in footer.Footer.Descendants<BookmarkStart>())
                {
                    if (inst.Name == bmName)
                    {
                        return inst;
                    }
                }
            }

            foreach (var header in doc.MainDocumentPart.HeaderParts)
            {
                foreach (var inst in header.Header.Descendants<BookmarkStart>())
                {
                    if (inst.Name == bmName)
                    {
                        return inst;
                    }
                }
            }
            foreach (var inst in doc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
            {
                if (inst is BookmarkStart)
                {
                    if (inst.Name == bmName)
                    {
                        return inst;
                    }
                }
            }

            return null;
        }
于 2019-06-18T04:08:33.227 に答える
0

このコードは機能しますが、ブックマークがフィールド/フォームテキスト (灰色のボックス) 内に配置されている場合は機能しません。

    private static void SetNewContents(wd.BookmarkStart bookmarkStart, string text)
    {
        if (bookmarkStart.ColumnFirst != null) return;

        var itemsToRemove = new List<OpenXmlElement>();

        var nextSibling = bookmarkStart.NextSibling();

        while (nextSibling != null)
        {

            if (IsEndBookmark(nextSibling, bookmarkStart))
                break;

            if (nextSibling is wd.Run)
                itemsToRemove.Add(nextSibling);

            nextSibling = nextSibling.NextSibling();
        }

        foreach (var item in itemsToRemove)
        {
            item.RemoveAllChildren();
            item.Remove();
        }

        bookmarkStart.Parent.InsertAfter(new wd.Run(new wd.Text(text)), bookmarkStart);
    }
于 2013-09-16T10:04:05.830 に答える