看日志的時間間隔基本就知道我的開發時間了,就樣式這一點做了我近1個半小時。所謂設置樣式,針對到Word里,大致有這樣的內容:
你把平時用不到的內容一去,那么必須要做的功能就列出來了:
字體:設置字體,設置字號,粗體,斜體,下划線
段落:設置對齊方式,設置首行縮進,設置段前,設置段后
這里我特意分了兩行。可以看到第一行,是在Word的是“字體”的設置。第二行則是在“段落”這個窗口里設置。針對到代碼里,很容易可以發現,其實第一個就是針對Run,第二個就是針對Paragraph來的。所以,在WordprocessingML里,也有專門用來修飾這兩個的標簽,也就是RunProperties和ParagraphProperties。他們應當是各自母標簽的第一個子標簽。並且在一個段落和連續文本內,不應該出現兩次。
所以,可以根據這樣的代碼初始化一個ParagraphProperties
1 public override void InitializeElement() 2 { 3 Properties = Run.GetFirstChild<RunProperties>(); 4 if (Properties == null) 5 { 6 Properties = new RunProperties(); 7 Run.PrependChild(Properties); 8 } 9 }
這里必須先找元素再加入,否則如果出現了兩個就不太好了。另外,由於大部分組件都有對應的Properties對象,所以這個初始化元素函數就加到CompositeElementBase這個類里,以防之后遺漏。之后就是一個無聊的工作了,按照規定把所有代碼都敲完就完整了。在這里,有幾個注意點:
1. 處理字號的時候,字號的點數和保存的值的關系是:value = size * 2。並且,這個數是要小於1600的。當然具體的值是1600多一些,記的不是很清楚了,取1600絕對沒有問題。所以,字號就是這樣的:
public override CompositeElementBase SetFontSize(int sizePoint) { if (sizePoint < 0 || sizePoint > 800) { throw new InvalidOperationException("字體大小必須大於0,並且小於800"); } DefaultRunProperties.FontSize = new DocumentFormat.OpenXml.Wordprocessing.FontSize() { Val = (sizePoint * 2).ToString() }; return SetPropertiesToChildren(); }
2. 一些常用的字號可以用枚舉,那由於枚舉對應的值只能是int。而常用字號里有幾個是有 0.5 的。所以,直接存雙倍數就可以。
public enum FontSize : int
{
ch初號 = 84,
xc小初 = 72,
yh一號 = 52,
xy小一 = 48,
eh二號 = 44,
xe小二 = 36,
sh三號 = 32,
xs小三 = 30,
sh四號 = 28,
xs小四 = 24,
hh五號 = 21,
xh小五 = 18,
lh六號 = 15,
xl小六 = 13,
qh七號 = 11,
bh八號 = 10
}
這里,寫中文是為了方便識別。前面帶兩個拼音是為了打字方便。
3. 字體分為中文字體和西文字體,這兩個可以分開設置。Ascii就是西文字體,EastAsia就是中文字體。
public override CompositeElementBase SetFontFamily(string zwFamily, string asciiFamily)
{
DefaultRunProperties.RunFonts = new RunFonts()
{
Ascii = asciiFamily,
EastAsia = zwFamily
};
return SetPropertiesToChildren();
}
4. 下划線是通過一個枚舉設置的:UnderlineValues。這個枚舉可以查看文檔:https://docs.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.wordprocessing.underlinevalues 。但是在編碼的時候,為了可以讓最終使用者完全不認識 DocumentFormat.OpenXml.Wordprocessing 這個命名空間,所以,要通過代碼對其進行封裝。那自己寫一個枚舉,然后轉換一下就行了。注意,這里絕對不推薦圖省事直接用“UnderlineValues”,如果直接用了這個東西,那就封了個寂寞。
5. 水平對齊方式不是TextAlignment,這個是垂直對齊。水平對齊的那個屬性叫“Justification”對應枚舉的MSDN文檔是:https://docs.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.wordprocessing.justificationvalues 。不過,我Html做的比較多,所以函數還是用SetAlign了。同樣的,這個枚舉也要封裝。
6. 在Word里,縮進其實有四種:左縮進,右縮進,首行縮進和懸掛縮進。對應的MSDN文檔:https://docs.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.wordprocessing.indentation 。我常用的只有首行縮進兩字符,所以我只留了這個函數:
public override CompositeElementBase SetFirstLineIndent(float chars = 2) { if (chars < 0) { throw new InvalidOperationException("參數chars必須大於 0"); } Properties.Indentation = new Indentation() { FirstLineChars = (int)(chars * 100) }; return this; }
在這里,“FirstLineChars”這個屬性的值是字符數乘以100的整數。
7. 段前,段后間距以及行距的 MSDN文檔是:https://docs.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.wordprocessing.spacingbetweenlines 。在這個對象里可以設置上述三種值。間距的單位“磅”在文檔里寫的是“twentieths”,也就是20分之一。即如果寫了10磅。那這個值就是 200,乘以20的關系。而行距一般使用倍數。幾倍行距則是 240的多少倍,比如單倍行距,則Line設置為240,兩倍行距就是480這樣。如果要設置成“最小值”或者“固定值”則需要配合LineRule這個屬性。這是一個枚舉,也非常簡單相信一看就懂。同樣的,如果代碼要用,那就建議封裝一下。
public override CompositeElementBase SetLineHeight(double times)
{
var sbl = Properties.SpacingBetweenLines;
if (sbl == null)
{
sbl = new SpacingBetweenLines();
Properties.SpacingBetweenLines = sbl;
}
sbl.Line = (times * 240).ToString();
return this;
}
public override CompositeElementBase SetLineBefore(int pt)
{
var sbl = Properties.SpacingBetweenLines;
if (sbl == null)
{
sbl = new SpacingBetweenLines();
Properties.SpacingBetweenLines = sbl;
}
sbl.Before = (pt * 20).ToString();
return this;
}
public override CompositeElementBase SetLineAfter(int pt)
{
var sbl = Properties.SpacingBetweenLines;
if (sbl == null)
{
sbl = new SpacingBetweenLines();
Properties.SpacingBetweenLines = sbl;
}
sbl.After = (pt * 20).ToString();
return this;
}
最后,改一下Main函數,就完成啦!對比一下需求,這個標題是完!全!一!樣!