在 OpenXML 的顏色畫刷填充,有特殊的填充是 GrpFill 屬性,對應 OpenXML SDK 定義的 DocumentFormat.OpenXml.Drawing.GroupFill 型別
本文屬于 OpenXML 系列博客,前后文請參閱 Office 使用 OpenXML SDK 決議檔案博客目錄
在顏色畫刷的定義,如形狀的填充色,在形狀放入到組合里面時,可以讓形狀的顏色繼承組合的顏色,根據 ECMA 376 的 20.1.8.35 章檔案,通過 grpFill (Group Fill)屬性可以讓形狀等元素的畫刷繼承組合元素的畫刷,如下面檔案內容,下面檔案忽略很多代碼,只是作為例子
<p:grpsp>
<p:grpsppr>
<a:solidfill>
<a:srgbclr val="565656">
</a:srgbclr></a:solidfill>
</p:grpsppr>
<p:sp>
<p:sppr>
<a:prstgeom prst="rect">
<a:grpfill>
</a:grpfill></a:prstgeom></p:sppr>
</p:sp>
<p:sp>
<p:sppr>
<a:prstgeom prst="rect">
<a:solidfill>
<a:srgbclr val="F6F656">
</a:srgbclr></a:solidfill>
</a:prstgeom></p:sppr>
</p:sp>
</p:grpsp>
可以看到在組合內有兩個矩形,其中第一個矩形的填充寫的是 <a:grpfill> 采用組合元素的填充,而組合元素的填充如下
<a:solidfill>
<a:srgbclr val="565656">
</a:srgbclr></a:solidfill>
我以為大家都能看出 RGB 的值,因此就截圖此時的檔案從 PowerPoint 打開的界面,不標注每個矩形的顏色

可以看到左邊的矩形采用了 565656 的顏色,而另一個矩形采用自己定義的 F6F656 顏色,也就是說第一個矩形的顏色是從組合讀取的
使用 OpenXML SDK 讀取的代碼如下
private static void ReadFill(Shape shape)
{
var shapeProperties = shape.ShapeProperties;
if (shapeProperties == null)
{
return;
}
var groupFill = shapeProperties.GetFirstChild<groupfill>();
if (groupFill != null)
{
// 如果是組合的顏色畫刷,那需要去獲取組合的
var groupShape = shape.Parent as GroupShape;
var solidFill = groupShape?.GroupShapeProperties?.GetFirstChild<solidfill>();
Debug.Assert(solidFill?.RgbColorModelHex?.Val != null, "solidFill.RgbColorModelHex.Val != null");
Console.WriteLine(solidFill.RgbColorModelHex.Val.Value);
}
else
{
var solidFill = shapeProperties.GetFirstChild<solidfill>();
Debug.Assert(solidFill?.RgbColorModelHex?.Val != null, "solidFill.RgbColorModelHex.Val != null");
Console.WriteLine(solidFill.RgbColorModelHex.Val.Value);
}
}
以上的測驗檔案和代碼放在 github 和 gitee 歡迎訪問
可以通過如下方式獲取本文的源代碼,先創建一個空檔案夾,接著使用命令列 cd 命令進入此空檔案夾,在命令列里面輸入以下代碼,即可獲取到本文的代碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin c42f54305663193343be6c7f7da318a63cd1ce94
以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
獲取代碼之后,進入 PptxDemo 檔案夾
那如果是放在組合的組合里面的元素呢?規則和 WPF 資源相同,越靠近元素的越優先,如下面檔案代碼,只有最上層的組合存在組合填充,在第二層組合里面沒有組合填充,此時的矩形將會使用最上層的組合的填充
<p:grpsp>
<p:grpsppr>
<a:solidfill>
<a:srgbclr val="565656">
</a:srgbclr></a:solidfill>
</p:grpsppr>
<p:grpsp>
<p:grpsppr>
<!-- 沒有填充 -->
</p:grpsppr>
<p:sp>
<p:sppr>
<a:prstgeom prst="rect">
<a:grpfill>
</a:grpfill></a:prstgeom></p:sppr>
</p:sp>
<p:sp>
<p:sppr>
<a:prstgeom prst="rect">
<a:solidfill>
<a:srgbclr val="F6F656">
</a:srgbclr></a:solidfill>
</a:prstgeom></p:sppr>
</p:sp>
</p:grpsp>
<p:sp>
<!-- 賣萌的 -->
</p:sp>
</p:grpsp>
從 PowerPoint 打開的界面如下

修改一下邏輯,如下
private static void ReadFill(Shape shape)
{
// 更多讀取畫刷顏色請看 [dotnet OpenXML 獲取顏色方法](https://blog.lindexi.com/post/Office-%E4%BD%BF%E7%94%A8-OpenXML-SDK-%E8%A7%A3%E6%9E%90%E6%96%87%E6%A1%A3%E5%8D%9A%E5%AE%A2%E7%9B%AE%E5%BD%95.html )
var shapeProperties = shape.ShapeProperties;
if (shapeProperties == null)
{
return;
}
var groupFill = shapeProperties.GetFirstChild<groupfill>();
if (groupFill != null)
{
// 如果是組合的顏色畫刷,那需要去獲取組合的
var groupShape = shape.Parent as GroupShape;
var solidFill = groupShape?.GroupShapeProperties?.GetFirstChild<solidfill>();
if (solidFill is null)
{
// 繼續獲取組合的組合
while (groupShape!=null)
{
groupShape = groupShape.Parent as GroupShape;
solidFill = groupShape?.GroupShapeProperties?.GetFirstChild<solidfill>();
if (solidFill != null)
{
break;
}
}
}
Debug.Assert(solidFill?.RgbColorModelHex?.Val != null, "solidFill.RgbColorModelHex.Val != null");
Console.WriteLine(solidFill.RgbColorModelHex.Val.Value);
}
else
{
var solidFill = shapeProperties.GetFirstChild<solidfill>();
Debug.Assert(solidFill?.RgbColorModelHex?.Val != null, "solidFill.RgbColorModelHex.Val != null");
Console.WriteLine(solidFill.RgbColorModelHex.Val.Value);
}
}
上面代碼在獲取到當前形狀的上一層組合,拿不到畫刷時,將會繼續嘗試去找組合的組合
以上代碼和測驗檔案放在 github 和 gitee 歡迎訪問
可以繼續在當前代碼倉庫里面輸入以下命令獲取
git pull origin f15fb418610fc95ac807289a4ea19343489daa2d
那如果元素沒有放入到組合呢?也就是某個形狀設定填充色采用繼承組合的畫刷,但是此形狀沒有在組合內,在 PowerPoint 的行為是此元素將丟失填充色,相當于沒有填充
如以下的檔案內容,有一個形狀使用了 grpFill 但是沒有放在組合里面
<p:csld>
<p:sptree>
<p:sp>
<p:nvsppr>
<p:cnvpr id="2" name="Rectangle 1">
</p:cnvpr></p:nvsppr>
<p:sppr>
<a:prstgeom prst="rect">
<a:grpfill>
</a:grpfill></a:prstgeom></p:sppr>
</p:sp>
</p:sptree>
</p:csld>
從 PPT 里打開可以看到此形狀是不可見的

咱使用代碼讀取的方法如下
static void ReadFill(Shape shape)
{
// 更多讀取畫刷顏色請看 [dotnet OpenXML 獲取顏色方法](https://blog.lindexi.com/post/Office-%E4%BD%BF%E7%94%A8-OpenXML-SDK-%E8%A7%A3%E6%9E%90%E6%96%87%E6%A1%A3%E5%8D%9A%E5%AE%A2%E7%9B%AE%E5%BD%95.html )
var shapeProperties = shape.ShapeProperties;
if (shapeProperties == null)
{
return;
}
var groupFill = shapeProperties.GetFirstChild<groupfill>();
if (groupFill != null)
{
// 如果是組合的顏色畫刷,那需要去獲取組合的
var groupShape = shape.Parent as GroupShape;
var solidFill = groupShape?.GroupShapeProperties?.GetFirstChild<solidfill>();
if (solidFill is null)
{
// 繼續獲取組合的組合
while (groupShape != null)
{
groupShape = groupShape.Parent as GroupShape;
solidFill = groupShape?.GroupShapeProperties?.GetFirstChild<solidfill>();
if (solidFill != null)
{
break;
}
}
}
if (solidFill is null)
{
Console.WriteLine($"沒有顏色");
}
else
{
Debug.Assert(solidFill.RgbColorModelHex?.Val != null, "solidFill.RgbColorModelHex.Val != null");
Console.WriteLine(solidFill.RgbColorModelHex.Val.Value);
}
}
else
{
var solidFill = shapeProperties.GetFirstChild<solidfill>();
Debug.Assert(solidFill?.RgbColorModelHex?.Val != null, "solidFill.RgbColorModelHex.Val != null");
Console.WriteLine(solidFill.RgbColorModelHex.Val.Value);
}
}
以上代碼和測驗檔案放在 github 和 gitee 歡迎訪問
可以繼續在當前代碼倉庫里面輸入以下命令獲取
git pull origin 20627e0deed86ea300a1c70a0066e7b15d98a9b9
更多請看 Office 使用 OpenXML SDK 決議檔案博客目錄
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/293286.html
標籤:.NET技术
