OpenXml SDK學習筆記(3):設置樣式


看日志的時間間隔基本就知道我的開發時間了,就樣式這一點做了我近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函數,就完成啦!對比一下需求,這個標題是完!全!一!樣!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM