dotnet OpenXML 修复 Office 文档里面的百分比内容包含百分号

我在解析一个 PPT 文档的时候,发现了这个 PPT 文档的背景色的透明度百分比的字符串里面包含了百分号,而不是一个 OpenXml 里面的百分比单位

这份 PPT 文档的背景内容如下

    <p:bg>
      <p:bgPr>
        <a:solidFill>
          <a:srgbClr val="383747">
            <a:alpha val="100.00%" />
          </a:srgbClr>
        </a:solidFill>
      </p:bgPr>
    </p:bg>

可以看到背景的 a:alpha 的 Val 值是一个包含了百分号的字符串。这个和 OpenXML 的单位定义的百分比不相同,从 Office Open XML 的测量单位 可以了解到默认使用的是千分之一的百分比,也就是默认的字符串是一个整数的数值,其中数值的一千就代表百分之一的值,如我在 dotnetCampus.OpenXMLUnitConverter OpenXML 单位转换开源库 里面写的代码一样

如上面文档内容,如果使用 OpenXML SDK 的背景获取方式,如下面代码,将会提示出错

            using (var presentationDocument = DocumentFormat.OpenXml.Packaging.PresentationDocument.Open("1.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;

                    var background = slide.CommonSlideData.Background;
                    var backgroundProperties = background.BackgroundProperties;
                    var solidFill = backgroundProperties.GetFirstChild<SolidFill>();
                    var solidFillRgbColorModelHex = solidFill.RgbColorModelHex;
                    var alpha = solidFillRgbColorModelHex.GetFirstChild<Alpha>();
                    try
                    {
                        int alphaVal = alpha.Val;
                    }
                    catch (Exception e)
                    {
                        // Input string was not in a correct format.
                        Console.WriteLine(e);
                    }
                }
            }

以上的全部代码放在 github 欢迎下载测试,这里面就包含了这个测试的 PPT 文档

在 OpenXML SDK 里面将 alpha 的 Val 认为是一个 Int32Value 值,因此在转换的时候就会失败。这个问题我报给了官方,请看 OpenXML SDK will throw exception when a percentage with % char · Issue #875 · OfficeDev/Open-XML-SDK

咱的一个修复方法是获取的是 alpha 的 InnerText 然后进行转换

var alphaText = alpha.InnerText;
var percentage = new Percentage(alphaText);

        public Percentage(string percentageText)
        {
            if (int.TryParse(percentageText, out var intValue))
            {
                IntValue = intValue;
                return;
            }
            else
            {
                // 如果是带了百分比的
                if (percentageText.Length > 1 && percentageText.EndsWith("%"))
                {
                    var newPercentageText = percentageText.Substring(0, percentageText.Length - 1);
                    if (double.TryParse(newPercentageText, out var doubleValue))
                    {
                        IntValue = (int)Math.Round(doubleValue * 1000);

                        return;
                    }
                }
            }

            throw new ArgumentException(
                $"Can not convert PercentageText={percentageText} to {nameof(OpenXmlUnitConverter.Percentage)} value.");
        }

而根据 ECMA 376 文档的定义,这里的 Alpha 值内容如下

<xsd:group name="EG_ColorTransform">
  <xsd:choice>
  	<!-- 忽略代码 -->
  	<xsd:element name="alpha" type="CT_PositiveFixedPercentage" minOccurs="1" maxOccurs="1"/>
  </xsd:choice>
</xsd:group>

而 CT_PositiveFixedPercentage 的定义如下

<xsd:complexType name="CT_PositiveFixedPercentage">
  <xsd:attribute name="val" type="ST_PositiveFixedPercentage" use="required"/>
</xsd:complexType>

ST_PositiveFixedPercentage 的定义如下

<xsd:simpleType name="ST_PositiveFixedPercentage">
  <xsd:union memberTypes="s:ST_PositiveFixedPercentage"/>
</xsd:simpleType>

这里的要求的数据格式如下

<xsd:simpleType name="ST_PositiveFixedPercentage">
    <xsd:restriction base="ST_Percentage">
        <xsd:pattern value="((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%"/>
    </xsd:restriction>
</xsd:simpleType>

也就是说其实不算是 Int 数值

本文的属性是依靠 dotnet OpenXML 解压缩文档为文件夹工具 工具协助测试的,这个工具是开源免费的工具,欢迎小伙伴使用

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

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

lindexi_gd CSDN认证博客专家 C# WPF UWP 微软最具价值专家
我是微软Windows应用开发方向的最具价值专家,欢迎访问我博客blog.lindexi.com里面有大量WPF和UWP博客
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页