编辑Word书签更改字体

时间:2017-02-28 17:37:52

标签: c# ms-word openxml openxml-sdk

我有一个使用OpenXml生成文档的C#程序。它使用以下方法用值替换书签:

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

在这个特定的word文档中,使用的字体是Raleway。有几个书签,在执行此方法后,两个书签使用Calibri字体。我试图重写这些书签,以确保他们在Raleway,但他们继续改为Calibri。

这怎么可能?

2 个答案:

答案 0 :(得分:2)

首先,您的代码创建没有先前RunProperties的新元素。 所以,你会得到类似下一个片段的内容:

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

代替它:

<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>  

您可以复制以下任何属性:

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

答案 1 :(得分:1)

书签有点奇怪。很自然地认为书签可以包含fx Run,就像这样(注意:这不是有效的OpenXML,只是为了说明一点):

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

但这不是他们的工作方式。相反,它们是使用BookmarkStartBookmarkEnd定义的 - 使用属性id来匹配相应的起始元素和结束元素。

BookmarkStartBookmarkEnd可以涵盖所有类型的内容 - 它们甚至不必位于相同的段落中(如this example on MSDN所示)。

带有两个看似相邻的书签的文字文件可以以一种奇怪的方式嵌套。以下是我刚刚汇总的Word文档中的示例:它有一个带有两个书签的段落:b1b2。请注意,bookmarkStart的{​​{1}}位于书签b2内。

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> bookmarkStart的结构不像您期望的那样。

我觉得使用OpenXML Productivity Tool帮助调试这样的东西很有用。

bookmarkEnd也没有子女,因此不需要调用BookmarkStart