天天看點

dotnet OpenXML 簡單聊聊 PPT 文本解析

在 Office 裡面的文本解析最全的範圍是 Word 文本,就是屬性數量本身就特别多。本文隻是簡單和大家聊聊 Office 裡面的 PPT 的文本的解析入門。盡管 PPT 的文本也是采用 DrawingDL 的文本屬性為主,不過會用到的屬性将比 Word 少很多。本文将和小夥伴介紹 PPT 的文本存放的方式

在 PPT 中的文本框也是形狀,隻是形狀裡面添加了特殊的設定。而沒有添加特殊設定的形狀也可以添加文本,在 PPT 的文本使用 <p:txBody> 包含,這就是本文主要和大家介紹的内容

閱讀本文,你将能大概了解如何開始入手 PPT 的文本解析,以及了解相應的工作量

在開始之前,我期望你是了解 PPT 的整個元素的存放格式的,請看 dotnet OpenXML 解析 PPT 頁面元素文檔格式

最簡單的文本元素,當然,我這裡的簡單說的是文本解析層的。此時的文本将不引用全局的和占位符等的樣式資訊,此時的文本将包含自己的所有資訊,此時的文本解析是最簡單的

簡單的文本在 <p:txBody> 裡面将會包含一個 <a:bodyPr> 的值,這個值對應在 OpenXML SDK 的 DocumentFormat.OpenXml.Drawing.BodyProperties 類。也就是在 <a:bodyPr> 有啥屬性和值都可以在 BodyProperties 這個類裡面找到,當然有些可選的值隻能通過 GetFirstChild 方法擷取了,這部分就不細說了

需要科普的,放在 DocumentFormat.OpenXml.Drawing 的内容意味着是 DrawingDL 的定義,也就是将是 Office 多個格式如 PPT 和 Word 等共同使用的定義,是以對 DrawingDL 的解析完成基本上對 Office 的多個格式的這部分解析也是算完成。關于 DrawingDL 等 Office 多個格式的關系,請小夥伴看 Office 文檔解析 文檔格式和協定

在 PPT 的 <p:txBody> 的 <a:bodyPr> 表示整個文本本身的屬性,包括文本是橫排還是豎排,文本是否自适寬度高度等資訊

在 PPT 的文本是富文本,可以對文本的文本段落進行設定,同時可以對文本的每個字元進行設定樣式。是以在 PPT 的文檔會給每一段添加段落屬性。給每一段裡面的某些樣式相同的字元添加文本屬性,為什麼不是給每個字元單獨一個屬性?原因是這樣做會讓文本屬性太多了。是以連續的文本如果有相同的樣式,那麼就可以使用相同的一個文本屬性

在 <p:txBody> 标準的文檔将會在 <a:bodyPr> 的下方添加 <a:p> 段落資訊,一個文本框會包含多個段落資訊,大概的格式如下

<p:txBody>
  <a:bodyPr>
  </a:bodyPr>

  <a:p></a:p>
  <a:p></a:p>
</p:txBody>      

在 <a:p> 包含一個段落資訊,在 OpenXML SDK 裡面使用 DocumentFormat.OpenXml.Drawing.Paragraph 類。在段落裡面,會包含很多 <a:r> 文本,以及段落屬性

段落屬性使用 <a:pPr> 表示,包含段落的行距等段落資訊,具體是哪些屬于段落資訊?打開 PPT 軟體,選擇一個文本,可以看到段落的設定,這些就是段落資訊。在 OpenXML SDK 裡面使用 DocumentFormat.OpenXml.Drawing.ParagraphProperties 類

dotnet OpenXML 簡單聊聊 PPT 文本解析

小夥伴可以看到在 PPT 軟體的段落設定旁邊有字型設定,這是對應放在 <a:r> 文本的内容,格式如下

<p:txBody>
  <a:bodyPr></a:bodyPr>
  <a:p>
    <a:pPr fontAlgn="auto">
    </a:pPr>
    <a:r>
      <a:rPr b="1" dirty="0" lang="en-US" sz="2400">
        <a:latin typeface="+mn-ea"/>
      </a:rPr>
      <a:t>歡迎</a:t>
    </a:r>
    <a:r>
      <a:rPr altLang="en-US" b="1" dirty="0" lang="zh-CN" sz="2400">
        <a:latin typeface="+mn-ea"/>
      </a:rPr>
      <a:t>通路我部落格 https://blog.lindexi.com 裡面有大量 UWP WPF 部落格</a:t>
    </a:r>
  </a:p>
</p:txBody>      

在 <a:r> 裡面包含 <a:rPr> 文本屬性,也就是上面圖檔 PPT 軟體的 字型 的設定的内容,包含具體的字型字号等屬性。這裡的 <a:rPr> 在 OpenXML SDK 裡面使用 DocumentFormat.OpenXml.Drawing.RunProperties 類。上面僅是例子,關于屬性的作用和含義請忽略

同時在 <a:r> 裡面将包含 <a:t> 也就是 DocumentFormat.OpenXml.Drawing.Text 的值,從上面的格式可以看到,這就是純文字的字元串

是以最簡單的解析 PPT 的文本,其實就是需要先拿到整個本文的屬性,也就是 <a:bodyPr> 的值,然後分段解析每個 <a:p> 的值。在解析 <a:p> 的值包括解析段落的屬性 <a:rPr> 的值和段落裡面包含的文本 <a:r> 的值,而文本本身包含純文字 <a:t> 和文本屬性 <a:rPr> 的值

也就是 PPT 的文本排版其實就是拿出純文字,然後将純文字先按照文本的富文本屬性的不同分組,如不同的文本有不同的字号和顔色等。接着按照文本的段落,也就是換行符将文本分為多個段落,再添加每個段落的段落屬性,如行距等

最後的文本需要包含這些段落和文本框的屬性,如橫排豎排顯示等

從本文上面的描述,其實 PPT 用到的文本格式大部分都是 DrawingDL 的定義,也就是其實上面的規則不隻是适用于 PPT 一個格式,對 Excel 等也适合

那麼解析的工作量大的在哪裡?第一點是在收集這些屬性上面,在 PPT 裡面最簡單的文本才會将所有的屬性都添加上,而基本上的 PPT 文檔裡面是不會将所有的屬性添加的,那麼這些沒有添加的屬性使用的是預設屬性?其實不一定,因為在 PPT 中的屬性是有繼承的,從頁面繼承 SlideLayout 屬性,從 SlideLayout 繼承 SlideMaster 屬性。又有文本的樣式等級,如 Level1ParagraphProperties 和 Level2ParagraphProperties 等,收集對的屬性的工作量很大

等等,什麼是 SlideLayout 和 SlideMaster 呀,請看 dotnet OpenXML 的 Slide Master 和 Slide Layout 是什麼

第二點就是屬性的數量本身,在 OpenXML 裡面定義了大量的文本可以被設定的屬性,光是定義這些屬性就需要大量的代碼。而在定義之後還需要了解屬性的含義和作用,有些屬性本身會互相影響的,就更坑了。好在幾乎所有的屬性能做出來的效果,都能在 WPF 裡面實作,我還沒有遇到隻有 PPT 能實作的渲染效果而在 WPF 不能實作的。當然使用 WPF 的富本文控件是做不出效果的,需要自己寫一個文本庫

是以整個 PPT 的文本解析裡面的工作量都在屬性上面,也就是了解 PPT 的純文字在加上這些屬性之後會有啥的呈現就是解析文本的主要工作

我寫了很多 Office 解析相關的部落格,請看 Office 使用 OpenXML SDK 解析文檔部落格目錄

我搭建了自己的部落格 https://blog.lindexi.com/ 歡迎大家通路,裡面有很多新的部落格。