使用Open XML SDK替换Word文件中的书签文本

Mr.*_*Boy 19 c# ms-word openxml openxml-sdk

我认为2.0是更好的... ...他们有一些不错的"如何..." 的例子,但书签似乎并不为明显充当说表...一个书签被定义2个 XML元素BookmarkStart&书签结束.我们有一些带有书签的模板作为书签,我们只想用其他文本替换书签......没有奇怪的格式化,但如何选择/替换书签文字?

Mr.*_*Boy 16

这是我用你们的灵感后的方法:

  IDictionary<String, BookmarkStart> bookmarkMap = 
      new Dictionary<String, BookmarkStart>();

  foreach (BookmarkStart bookmarkStart in file.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
  {
      bookmarkMap[bookmarkStart.Name] = bookmarkStart;
  }

  foreach (BookmarkStart bookmarkStart in bookmarkMap.Values)
  {
      Run bookmarkText = bookmarkStart.NextSibling<Run>();
      if (bookmarkText != null)
      {
          bookmarkText.GetFirstChild<Text>().Text = "blah";
      }
  }
Run Code Online (Sandbox Code Playgroud)

  • 您在这里遵循一个非常简单的模式,该模式并不适用于所有情况。在许多情况下,书签替换变得更加复杂,这不适用于该算法。 (2认同)

小智 7

用单个内容(可能是多个文本块)替换书签.

public static void InsertIntoBookmark(BookmarkStart bookmarkStart, string text)
{
    OpenXmlElement elem = bookmarkStart.NextSibling();

    while (elem != null && !(elem is BookmarkEnd))
    {
        OpenXmlElement nextElem = elem.NextSibling();
        elem.Remove();
        elem = nextElem;
    }

    bookmarkStart.Parent.InsertAfter<Run>(new Run(new Text(text)), bookmarkStart);
}
Run Code Online (Sandbox Code Playgroud)

首先,删除开始和结束之间的现有内容.然后在开始之后(结束之前)直接添加新的运行.

但是,不确定书签在打开时是在另一个部分中关闭还是在不同的表格单元格中等等.

对我来说现在已经足够了.

  • 请注意,我已经翻译了这个答案(使用Google提供的帮助).请检查其准确性.将来,请用英文发布. (7认同)

小智 5

很多小时后,我写了这个方法:

    Public static void ReplaceBookmarkParagraphs(WordprocessingDocument doc, string bookmark, string text)
    {
        //Find all Paragraph with 'BookmarkStart' 
        var t = (from el in doc.MainDocumentPart.RootElement.Descendants<BookmarkStart>()
                 where (el.Name == bookmark) &&
                 (el.NextSibling<Run>() != null)
                 select el).First();
        //Take ID value
        var val = t.Id.Value;
        //Find the next sibling 'text'
        OpenXmlElement next = t.NextSibling<Run>();
        //Set text value
        next.GetFirstChild<Text>().Text = text;

        //Delete all bookmarkEnd node, until the same ID
        deleteElement(next.GetFirstChild<Text>().Parent, next.GetFirstChild<Text>().NextSibling(), val, true);
    }
Run Code Online (Sandbox Code Playgroud)

在那之后,我打电话给:

Public static bool deleteElement(OpenXmlElement parentElement, OpenXmlElement elem, string id, bool seekParent)
{
    bool found = false;

    //Loop until I find BookmarkEnd or null element
    while (!found && elem != null && (!(elem is BookmarkEnd) || (((BookmarkEnd)elem).Id.Value != id)))
    {
        if (elem.ChildElements != null && elem.ChildElements.Count > 0)
        {
            found = deleteElement(elem, elem.FirstChild, id, false);
        }

        if (!found)
        {
            OpenXmlElement nextElem = elem.NextSibling();
            elem.Remove();
            elem = nextElem;
        }
    }

    if (!found)
    {
        if (elem == null)
        {
            if (!(parentElement is Body) && seekParent)
            {
                //Try to find bookmarkEnd in Sibling nodes
                found = deleteElement(parentElement.Parent, parentElement.NextSibling(), id, true);
            }
        }
        else
        {
            if (elem is BookmarkEnd && ((BookmarkEnd)elem).Id.Value == id)
            {
                found = true;
            }
        }
    }

    return found;
}
Run Code Online (Sandbox Code Playgroud)

如果您没有空的书签,此代码运行良好。我希望它可以帮助某人。