2017-02-28 109 views
1

我有一個使用OpenXml生成文檔的C#程序。它使用以下方法用值替換書籤:編輯Word書籤更改字體

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

首先,您的代碼會創建沒有以前的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

書籤是有點怪。它會自然地認爲,一個書籤的東西,可以包含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。請注意,b2bookmarkStart位於書籤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> 

很難猜測在你的例子究竟發生了什麼,但我的猜測是,在bookmarkStartbookmarkEnd像你期望不規整。

我覺得使用OpenXML生產力工具來幫助調試這樣的東西是有用的。

(此外BookmarkStart沒有子女,所以不需要致電bookmark.RemoveAllChildren)。