觀察上一段日記最后的代碼:
這里的樣式基本可以理解為行內CSS。那么既然有行內的樣式,就肯定有外部的樣式。那這部分就對應筆記1里說的style.xml文件。這個文件對應的是Document.MainDocumentPart.StyleDefinitionsPart這個部分,文檔是 https://docs.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.packaging.styledefinitionspart 。這部分里面有一個重要屬性 Styles 。這個屬性里存着的就是整個文檔里所有用到的樣式,包括顯示在界面上的,和不顯示在界面上的。Styles屬性里,所有內容都是Style的對象。在學習這個對象前,先要了解Word里有幾種樣式。在Word中,選擇編輯任何一個樣式,就可以看到:
這樣的界面,他們歸納一下,也就是文檔中提到的WordprocessingML的六大樣式:
-
段落樣式
-
字符樣式
-
鏈接樣式(段落 + 字符)[注釋:通過鏈接元素實現 (§17.7.4.6)。注釋結束]
-
表樣式
-
編號樣式
-
默認段落 + 字符屬性
其中,在本需求中會用到的就是“段落樣式”和“字符樣式”。所以,只需要學習這兩種樣式的實現方式即可。那么,再觀察Style對象。這個對象的初始化大致是長這樣的:
ParagraphStyle = new Style()
{
CustomStyle = true,
Type = StyleValues.Paragraph,
StyleName = new StyleName()
{
Val = Name
},
StyleId = paraId,
StyleParagraphProperties = new StyleParagraphProperties(),
StyleRunProperties = new StyleRunProperties()
};
其中,CustomStyle指的是用戶自定義樣式,直接設置為true就可以。Type是樣式的類型,一個枚舉,直接設置為Paragraph就可以。再接下來,StyleName就是顯示在窗口中“名稱”一欄的名字。StyleId則是內部用於識別樣式的編號,這個屬性和StyleName都不能重復。接着,StyleParagraphProperties指的是窗口里下拉欄中“段落”對應的內容,StyleRunProperties指的是窗口里設置文字字體字號這些內容。
在聲明樣式之后,需要將樣式先保存在Document.MainDocumentPart.StyleDefinitionsPart.Styles屬性里。之后,再應用這些樣式。應用時,需要使用到樣式的ID,所以要將Style轉換為樣式ID:
internal ParagraphStyleId ParagraphStyleId => new ParagraphStyleId()
{
Val = ParagraphStyle.StyleId
};
internal RunStyle RunStyleId => new RunStyle()
{
Val = ParagraphStyle.StyleId
};
這兩個屬性分別給誰用是非常明確的。那么,在WordParagraph里,書寫一個函數用於適用樣式:
protected override CompositeElementBase SetStyleSafe(WordStyles style)
{
Properties.ParagraphStyleId = style.ParagraphStyleId;
foreach (var item in Children)
{
(item as WordRun)?.SetStyle(style);
}
return this;
}
Run里面也需要一個這樣的函數,不過用的就是RunStyle,內容是一樣的就不重復了。
最后呢,修改一下AppendParagraph等方法,讓樣式更容易使用就行了。這一篇筆記結束的樣子是這樣的:
和上一章筆記結束時不太一樣的地方是,我發現這個原文居然有左側縮進2.23字符。於是我無奈新加了SetLeftChars和SetRightChars方法用來處理這些情況,非常尷尬。所以,做的時候讀需求非常重要。另外開發過程中,為了保證使用簡單,我把代碼重構了好幾次,倒也花了不少時間。最坑的是還不是這些,下篇筆記會講這里的調試。