在使用 OpenXML SDK 解析 PPT 文檔的文本佔位符的時候,須要對 PPT 的格式有必定的瞭解,儘管整個 OpenXML SDK 包括文檔等都很詳細。可是有一些細節文檔上雖然有寫,可是沒有強調一下,就被我忽略了php
什麼是文本佔位符,其實這是在 PPT 添加的概念,在 PPT 裏面用戶能夠編輯模版文件,在這裏定義某個佔位符文本的樣式和座標等app
如何製做佔位符請看 PPT佔位符,竟然這麼好用! - 知乎ide
想要解析佔位符還須要先學會如何使用佔位符纔好理解佔位符是如何作的測試
在 OpenXML 裏面文本是形狀,也就是 DocumentFormat.OpenXml.Presentation.Shape
元素,可使用下面代碼獲取頁面的形狀.net
using (var presentationDocument = DocumentFormat.OpenXml.Packaging.PresentationDocument.Open("測試.pptx", false)) { var presentationPart = presentationDocument.PresentationPart; var presentation = presentationPart.Presentation; // 先獲取頁面 var slideIdList = presentation.SlideIdList; foreach (var slideId in slideIdList.ChildElements.OfType<SlideId>()) { // 獲取頁面內容 SlidePart slidePart = (SlidePart) presentationPart.GetPartById(slideId.RelationshipId); var slide = slidePart.Slide; foreach (var shape in slidePart.Slide .Descendants<DocumentFormat.OpenXml.Presentation.Shape>()) { } } }
在 PPT 裏面是使用 p:ph
判斷一個形狀是佔位符,下面是一個佔位符的形狀code
<p:sp> <p:nvsppr> <p:cnvpr id="2" name="標題 1"> </p:cnvpr> <p:cnvsppr> <a:splocks nogrp="1"> </a:splocks> </p:cnvsppr> <p:nvpr> <p:ph type="ctrTitle"> </p:ph> </p:nvpr> </p:nvsppr> <p:sppr> </p:sppr> <p:txbody> <a:bodypr> </a:bodypr> <a:p> <a:r> <a:rpr altlang="en-US" lang="zh-CN"> </a:rpr> <a:t> PPT 解析 </a:t> </a:r> <a:endpararpr altlang="en-US" lang="zh-CN"> </a:endpararpr> </a:p> </p:txbody> </p:sp>
在 slide.xml 裏面的元素,經過設置 nvsppr->nvpr->ph 設置這個元素使用佔位符,須要繼承模版的佔位符樣式和座標等值orm
從 Shape 裏面拿到佔位符可使用下面代碼xml
// <p:nvSpPr>佔位符的樣式 NonVisualShapeProperties nonVisualShapeProperties = shape?.NonVisualShapeProperties; // cNvSpPr var nonVisualShapeDrawingProperties = nonVisualShapeProperties?.NonVisualShapeDrawingProperties; // nvpr var applicationNonVisualDrawingProperties = nonVisualShapeProperties?.ApplicationNonVisualDrawingProperties; var placeholderShape = applicationNonVisualDrawingProperties?.PlaceholderShape;
能夠在 placeholderShape 裏面找到兩個主要的屬性,一個是 Index 一個是 Type 屬性,這兩個屬性是什麼意思?從屬性的註釋能夠看到寫的很複雜,大概的作法就是佔位符須要去找到模版裏面相同的 Index 或相同的 Type 的佔位符元素,獲取這個元素的樣式和座標等blog
若是有仔細閱讀上面文檔就能夠知道,若是用戶在模版裏面定義了佔位符,那麼僅僅表示頁面裏面的對應元素的默認樣式,而元素本文能夠覆蓋此樣式。也就是元素的最終樣式是先嚐試獲取元素本文的樣式,若是元素本文獲取不到樣式,那麼嘗試運行佔位符元素,若是能夠找到佔位符元素,那麼嘗試獲取佔位符元素的對應樣式繼承
那麼如何經過 placeholderShape 找到對應的放在模版裏面的佔位符元素?是否小夥伴還記得 Slide Layout 和 Slide Master 的概念,若是不知道的話,請複習一下 PPT 是如何製做的課程,這兩個概念有點繞,須要小夥伴學會製做 PPT 才比較好說
獲取 SlideLayout 和 SlideMaster 可使用下面代碼
var layout = slidePart.SlideLayoutPart.SlideLayout; var master = slidePart.SlideLayoutPart.SlideMasterPart.SlideMaster;
先從 layout 裏面嘗試找到有沒有對應的佔位符元素,若是沒有找到再從 master 裏面找
尋找方法是從 CommonSlideData 的 ShapeTree 尋找是否有對應的元素,那麼什麼是對應的元素,若是頁面元素設置了 Type 那麼要求 ShapeTree 的元素的佔位符屬性有徹底相同的 Type 屬性,若是頁面元素設置了 Index 那麼要求 ShapeTree 的有相同的 ShapeTree 屬性。若是頁面元素的 Type 是空,那麼就不對 ShapeTree 的屬性有要求,若是 Index 是空,那麼對 ShapeTree 的屬性也沒有要求
private static Shape GetPlaceholderShape(PlaceholderShape placeholder, ShapeTree tree) { return tree.Elements<Shape>().FirstOrDefault(shape => { var placeholderShape = shape?.NonVisualShapeProperties?.ApplicationNonVisualDrawingProperties ?.PlaceholderShape; return placeholderShape != null && Equals(placeholder, placeholderShape); }); } /// <summary> /// 比較<see cref="PlaceholderShape"/>的type和id是否相同 /// <para></para> /// 若是 1 的 Type 或 Index 是空,那麼跳過這個屬性的判斷 /// <para></para> /// 若是這個屬性不是空,那麼必定要求 2 存在這個屬性 /// </summary> /// 這個規則經過 文本佔位符沒有type和id的值,獲取第一個佔位符做爲座標 和 WPS 對比測試拿到 /// 測試課件:文本佔位符沒有type和id的值.pptx /// <param name="placeholder1"></param> /// <param name="placeholder2"></param> /// <returns></returns> private static bool Equals(PlaceholderShape placeholder1, PlaceholderShape placeholder2) { // 若是 placeholder1.Type 存在值,要求 2 必定存在值 if (placeholder1.Type != null && placeholder1.Type.Value != placeholder2.Type?.Value) { return false; } if (placeholder1.Index != null && placeholder1.Index.Value != placeholder2.Index?.Value) { return false; } return true; }
獲取的方法以下
layoutPlaceholder = GetPlaceholderShape(placeholder, layout?.CommonSlideData?.ShapeTree); masterPlaceholder = GetPlaceholderShape(placeholder, master?.CommonSlideData?.ShapeTree);
此時的樣式獲取順序就是先從元素獲取,若是元素獲取不到,就從 layoutPlaceholder 獲取,若是獲取不到從 masterPlaceholder 獲取
註釋裏面的 文本佔位符沒有type和id的值.pptx 我就不放出來了,有須要的小夥伴發郵件給我
更多的 OpenXML 相關博客,還請自行百度 OpenXML 林德熙
就能找到個人博客了
我搭建了本身的博客 https://blog.lindexi.com/ 歡迎你們訪問,裏面有不少新的博客。只有在我看到博客寫成熟以後纔會放在csdn或博客園,可是一旦發佈了就再也不更新
若是在博客看到有任何不懂的,歡迎交流,我搭建了 dotnet 職業技術學院 歡迎你們加入
若有不方便在博客評論的問題,能夠加我 QQ 2844808902 交流
本做品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、從新發布,但務必保留文章署名林德熙(包含連接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的做品務必以相同的許可發佈。若有任何疑問,請與我聯繫。