Edit Word bookmark changes the font

核能气质少年 提交于 2019-12-11 04:59:21

问题


I have a C# program that generates documents using OpenXml. It replaces bookmarks with values using the following method :

private void FillBookmark(BookmarkStart bookmark, string value)
{
    var text = new Text(value);
    bookmark.RemoveAllChildren();

    IEnumerable<OpenXmlElement> elementsAfter = bookmark.ElementsAfter();
    IEnumerable<OpenXmlElement> insideBookmark = elementsAfter.TakeWhile(element => !(element is BookmarkEnd));
    foreach (OpenXmlElement element in insideBookmark)
    {
        element.RemoveAllChildren();
    }
    OpenXmlElement previousSibling = bookmark.PreviousSibling();
    while (previousSibling is BookmarkStart || previousSibling is BookmarkEnd)
    {
        previousSibling = previousSibling.PreviousSibling();
    }
    var container = new Run(text);
    previousSibling.AppendChild(container);
}

In this particular word document, the font used is Raleway. There are several bookmarks and after the execution of this method, two bookmarks are using the Calibri font. I tried to rewrite theses bookmarks to be sure they are in Raleway but they continue to change to Calibri.

How is this possible ?


回答1:


First of all your code creates new element without previous RunProperties. So, you get something like next snippet:

<w:r>
    <w:t>valuexX</w:t>
</w:r>

instead of it:

<w:r w:rsidRPr="00DE66A4">
    <w:rPr>
        <w:rFonts w:ascii="Algerian" w:hAnsi="Algerian" />
            <w:lang w:val="en-US" />
    </w:rPr>
    <w:t>6</w:t>               
</w:r>  

You can copy any properties like this:

private void FillBookmark(BookmarkStart bookmark, string value)
{
  var text = new Text(value);
  bookmark.RemoveAllChildren();

  IEnumerable<OpenXmlElement> elementsAfter = bookmark.ElementsAfter();
  IEnumerable<OpenXmlElement> insideBookmark = elementsAfter.TakeWhile(element => !(element is BookmarkEnd));
  foreach (OpenXmlElement element in insideBookmark)
  {
    element.RemoveAllChildren();
  }
  OpenXmlElement previousSibling = bookmark.PreviousSibling();
  while (previousSibling is BookmarkStart || previousSibling is BookmarkEnd)
  {
    previousSibling = previousSibling.PreviousSibling();
  }

  //Get previous font.
  var runProperties = previousSibling.GetFirstChild<ParagraphMarkRunProperties>().GetFirstChild<RunFonts>();
  //var runProperties = previousSibling.GetFirstChild<RunProperties>(); - if its simple element.

  // Clone.
  var newProperty = (RunFonts)runProperties.Clone();

  // Create container with properties.
  var container = new Run(text)
  {
    RunProperties = new RunProperties() { RunFonts = newProperty }
  };

  previousSibling.AppendChild(container);
}



回答2:


Bookmarks are a bit weird. It would be natural to think that a bookmark is something that can contain fx a Run, like so (NB: This is not valid OpenXML, it's just to illustrate a point):

<w:bookmark>   
    <w:run>
        <w:text>Some text</w:text>
    </w:run>
</w:bookmark>

But that's not how they work. Instead they are defined using BookmarkStart and BookmarkEnd - using the attribute id to match corresponding start- and end-elements.

The BookmarkStart and BookmarkEnd can span all kind of stuff - they don't even have to be in the same paragraph (as illustrated by this example on MSDN).

A word-document with two bookmarks that appear to be adjacent can be nested in a weird way. Here is an example from a Word-document I just threw together: it has a paragraph with two bookmarks: b1 and b2. Notice that the bookmarkStart for b2 is 'inside' the bookmark b1.

<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:r>
        <w:t>Some text with a</w:t>
    </w:r>
    <w:bookmarkStart w:name="b1" w:id="1" />
    <w:r>
        <w:t>couple</w:t>
    </w:r>
    <w:bookmarkStart w:name="b2" w:id="2" />
    <w:bookmarkEnd w:id="1" />
    <w:r>
        <w:t xml:space="preserve"> of bookmarks.</w:t>
    </w:r>
    <w:bookmarkEnd w:id="2" />
</w:p>

It's hard to guess exactly what happens in your example, but my guess would be that the bookmarkStart and bookmarkEnd is not structured like you expect.

I find it usefull to use OpenXML Productivity Tool to help when debugging stuff like this.

(Also the BookmarkStart doesn't have children, so the call to bookmark.RemoveAllChildren is not needed).



来源:https://stackoverflow.com/questions/42515339/edit-word-bookmark-changes-the-font

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!