编辑Word书签更改字体
Edit Word bookmark changes the font
我有一个使用 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。
这怎么可能?
首先,您的代码创建了没有先前 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);
}
书签有点奇怪。人们很自然地认为书签是可以包含 fx a Run
的东西,就像这样(注意:这不是有效的 OpenXML,它只是为了说明一点):
<w:bookmark>
<w:run>
<w:text>Some text</w:text>
</w:run>
</w:bookmark>
但这不是他们的工作方式。相反,它们是使用 BookmarkStart
和 BookmarkEnd
定义的 - 使用属性 id
来匹配相应的开始 - 和 end-elements.
BookmarkStart
和 BookmarkEnd
可以涵盖所有类型的内容 - 它们甚至不必位于同一段落中(如 this example on MSDN 所示)。
一个 word-document 有两个看起来相邻的书签可以以一种奇怪的方式嵌套。这是我刚刚拼凑的 Word-document 中的一个示例:它有一个带有两个书签的段落:b1
和 b2
。请注意 b2
的 bookmarkStart
是 'inside' 书签 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
和 bookmarkEnd
的结构与您预期的不同。
我发现在调试此类内容时使用 OpenXML Productivity Tool 很有用。
(而且 BookmarkStart
没有 children,所以不需要调用 bookmark.RemoveAllChildren
。
我有一个使用 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。
这怎么可能?
首先,您的代码创建了没有先前 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);
}
书签有点奇怪。人们很自然地认为书签是可以包含 fx a Run
的东西,就像这样(注意:这不是有效的 OpenXML,它只是为了说明一点):
<w:bookmark>
<w:run>
<w:text>Some text</w:text>
</w:run>
</w:bookmark>
但这不是他们的工作方式。相反,它们是使用 BookmarkStart
和 BookmarkEnd
定义的 - 使用属性 id
来匹配相应的开始 - 和 end-elements.
BookmarkStart
和 BookmarkEnd
可以涵盖所有类型的内容 - 它们甚至不必位于同一段落中(如 this example on MSDN 所示)。
一个 word-document 有两个看起来相邻的书签可以以一种奇怪的方式嵌套。这是我刚刚拼凑的 Word-document 中的一个示例:它有一个带有两个书签的段落:b1
和 b2
。请注意 b2
的 bookmarkStart
是 'inside' 书签 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
和 bookmarkEnd
的结构与您预期的不同。
我发现在调试此类内容时使用 OpenXML Productivity Tool 很有用。
(而且 BookmarkStart
没有 children,所以不需要调用 bookmark.RemoveAllChildren
。