zoukankan      html  css  js  c++  java
  • dotnet OpenXML 继承组合颜色的 GrpFill 属性

    在 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);
                }
            }
    

    以上的测试文件和代码放在 githubgitee 欢迎访问

    可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 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);
                }
            }
    

    上面代码在获取到当前形状的上一层组合,拿不到画刷时,将会继续尝试去找组合的组合

    以上代码和测试文件放在 githubgitee 欢迎访问

    可以继续在当前代码仓库里面输入以下命令获取

    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);
        }
    }
    

    以上代码和测试文件放在 githubgitee 欢迎访问

    可以继续在当前代码仓库里面输入以下命令获取

    git pull origin 20627e0deed86ea300a1c70a0066e7b15d98a9b9
    

    更多请看 Office 使用 OpenXML SDK 解析文档博客目录

    博客园博客只做备份,博客发布就不再更新,如果想看最新博客,请到 https://blog.lindexi.com/

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我[联系](mailto:lindexi_gd@163.com)。
  • 相关阅读:
    Pytorch学习(一)基础语法篇
    CSAPP深入理解计算机系统(第二版)第三章家庭作业答案
    理解DP(持续更新)
    LeetCode题解 | 215. 数组中的第K个最大元素
    快速排序
    浅谈设计模式(java)——从lol来看观察者模式
    <小虾米的android学习之旅1>Android框架
    程序员如何用技术变现?
    为了反击爬虫,前端工程师的脑洞可以有多大?
    如何成为一名爬虫工程师?(顺带提供工作机会)
  • 原文地址:https://www.cnblogs.com/lindexi/p/15131067.html
Copyright © 2011-2022 走看看