本文告诉大家如何读取 PPT 文件里面,放在主动画序列 MainSequence 的进入和退出和强调的动画,和在 OpenXML 里面的存放方式

如以下的课件内容,给一个元素添加了进入强调退出的动画,动画之间没有相关影响,通过点击触发动画,如下图

大概的动画内容如下

  <p:timing>
<p:tnLst>
<p:par>
<p:cTn id="1" dur="indefinite" restart="never" nodeType="tmRoot">
<p:childTnLst>
<p:seq concurrent="1" nextAc="seek">
<p:cTn id="2" dur="indefinite" nodeType="mainSeq">
<p:childTnLst>
<p:par>
<p:cTn id="3" fill="hold">
<p:stCondLst>
<p:cond delay="indefinite" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="4" fill="hold">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="5" presetID="1" presetClass="entr" presetSubtype="0" fill="hold" grpId="0" nodeType="clickEffect">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<!-- 忽略代码-->
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
<p:par>
<p:cTn id="7" fill="hold">
<p:stCondLst>
<p:cond delay="indefinite" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="8" fill="hold">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="9" presetID="25" presetClass="emph" presetSubtype="0" fill="hold" grpId="2" nodeType="clickEffect">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<!-- 忽略代码-->
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
<p:par>
<p:cTn id="14" fill="hold">
<p:stCondLst>
<p:cond delay="indefinite" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="15" fill="hold">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="16" presetID="10" presetClass="exit" presetSubtype="0" fill="hold" grpId="1" nodeType="clickEffect">
<!-- 忽略代码-->
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
<!-- 忽略代码-->
</p:seq>
</p:childTnLst>
</p:cTn>
</p:par>
</p:tnLst>
<!-- 忽略代码-->
</p:timing>

根据 cTn 也就是 OpenXML sdk 定义的 CommonTimeNode 类型的 PresetClass 属性可以了解到,动画 id 是 5 的是进入动画,动画 id 是 9 的是强调动画,动画 id 是 10 的是退出动画

可以看到在 PPT 里面,多个不同的动画,这些动画没有关联,也就是没有在上一个播放完成后,而是通过点击触发的,放在主序列的动画的内容大概如下

  <p:timing>
<p:tnLst>
<p:par>
<p:cTn id="1" dur="indefinite" restart="never" nodeType="tmRoot">
<p:childTnLst>
<p:seq concurrent="1" nextAc="seek">
<p:cTn id="2" dur="indefinite" nodeType="mainSeq">
<p:childTnLst>
<p:par>
<!-- 进入动画-->
</p:par>
<p:par>
<!-- 强调动画-->
</p:par>
<p:par>
<!-- 退出动画-->
</p:par>
</p:childTnLst>
</p:cTn>
<!-- 忽略代码-->
</p:seq>
</p:childTnLst>
</p:cTn>
</p:par>
</p:tnLst>
<!-- 忽略代码-->
</p:timing>

如上面的内容,大概可以理解存放的方式了,只是在 PPT 里面,有多个 ParallelTimeNode 和 CommonTimeNode 的嵌套。从 mainSeq 也就是 MainSequence 主动画序列以下,获取到的实际的进入动画,是经过了如下路径才能获取

cTn (mainSeq) -> childTnLst -> par -> cTn (id="3") -> childTnLst -> par -> cTn (id="4") -> childTnLst -> par -> cTn (id="5" presetClass="entr")

可以使用以下代码读取

        static void Main(string[] args)
{
using var presentationDocument =
DocumentFormat.OpenXml.Packaging.PresentationDocument.Open("Test.pptx", false);
var presentationPart = presentationDocument.PresentationPart;
var slidePart = presentationPart!.SlideParts.First();
var slide = slidePart.Slide;
var timing = slide.Timing;
// 第一级里面默认只有一项
var commonTimeNode = timing?.TimeNodeList?.ParallelTimeNode?.CommonTimeNode; if (commonTimeNode?.NodeType?.Value == TimeNodeValues.TmingRoot)
{
// 这是符合约定
// nodeType="tmRoot"
} if (commonTimeNode?.ChildTimeNodeList == null) return;
// 理论上只有一项,而且一定是 SequenceTimeNode 类型
var sequenceTimeNode = commonTimeNode.ChildTimeNodeList.GetFirstChild<SequenceTimeNode>(); var mainSequenceTimeNode = sequenceTimeNode.CommonTimeNode;
if (mainSequenceTimeNode?.NodeType?.Value == TimeNodeValues.MainSequence)
{
// [TimeLine 对象 (PowerPoint) | Microsoft Docs](https://docs.microsoft.com/zh-cn/office/vba/api/PowerPoint.TimeLine )
// MainSequence 主动画序列
var mainParallelTimeNode = mainSequenceTimeNode.ChildTimeNodeList; foreach (var openXmlElement in mainParallelTimeNode)
{
// 并行关系的
if (openXmlElement is ParallelTimeNode parallelTimeNode)
{
var timeNode = parallelTimeNode.CommonTimeNode.ChildTimeNodeList
.GetFirstChild<ParallelTimeNode>().CommonTimeNode.ChildTimeNodeList
.GetFirstChild<ParallelTimeNode>().CommonTimeNode; switch (timeNode.PresetClass.Value)
{
case TimeNodePresetClassValues.Entrance:
// 进入动画
break;
case TimeNodePresetClassValues.Exit:
// 退出动画
break;
case TimeNodePresetClassValues.Emphasis:
// 强调动画
break;
case TimeNodePresetClassValues.Path:
// 路由动画
break;
case TimeNodePresetClassValues.Verb:
break;
case TimeNodePresetClassValues.MediaCall:
// 播放动画
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
} // 文档规定,必须存在一个AttributeNameList列表,一定存在AttributeName元素,如果有多个只取第一个元素。
// 见"[MS-OI 29500].PDF 第2.1.1137章节(g选项)"
}

本文上面代码放在 githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2c06ddf74e45c31ad7842dd06dc09bcc67b6142e

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 PptxDemo 文件夹

以上的测试使用的 PPT 课件也放在此文件夹

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

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

dotnet OpenXML 读取 PPT 主序列进入退出强调动画的更多相关文章

  1. dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息

    在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式.本文来介绍如何读取 PPT 内嵌 ole 格式的 xls+ 表格的方法 在 ...

  2. dotnet OpenXML 转换 PathFillModeValues 为颜色特效

    在 OpenXml 预设形状,有一些形状设置了 PathFillModeValues 枚举,此枚举提供了亮暗的蒙层特效.具体的特效是让形状选择一个画刷,在画刷上加上特效.如立体几何 Cube 形状,在 ...

  3. java使用poi读取ppt文件和poi读取excel、word示例

    java使用poi读取ppt文件和poi读取excel.word示例 http://www.jb51.net/article/48092.htm

  4. DotNet加密方式解析--散列加密

    没时间扯淡类,赶紧上车吧. 在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念, ...

  5. OpenXml读取word内容(二)

    注意事项 上一篇已经说明,这次就不一一说了,直接来正文: word内容 相关代码 方法1 static void Main(string[] args) { string wordPathStr = ...

  6. OpenXml读取word内容(一)

    OpenXml读取word内容注意事项 1.使用OpenXml读取word内容,word后缀必须是".docx":如果word后缀是".doc"需要转成&quo ...

  7. OpenXml读取word内容注意事项

    OpenXml读取word内容注意事项 1.使用OpenXml读取word内容,word后缀必须是".docx":如果word后缀是".doc"需要转成&quo ...

  8. php 读取excel 时间列

    用PHP做一个导入excel功能,发现读取excel时间列的时候总是数据不对,去网上查找了这个函数,转换了一下就好了,真尼玛迷茫了,什么情况,先记录一下,以后再研究吧. 函数如下: function ...

  9. 使用openxml读取xml数据

    xml的数据格式如下: <?xml version="1.0"?> <Language Name="Chinese"> <Loca ...

  10. Java读取Excel指定列的数据详细教程和注意事项

    本文使用jxl.jar工具类库实现读取Excel中指定列的数据. jxl.jar是通过java操作excel表格的工具类库,是由java语言开发而成的.这套API是纯Java的,并不依赖Windows ...

随机推荐

  1. Mysql访问问题,远程连接提示:Host 'xxx' is not allowed to connect to this MySQL server。是mysql未开启mysql远程访问权限导致

    1.MySql服务器共享问题 对于在车间工作者,如果远程Mysql,我们这里假定网线连接 GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.1.3' IDE ...

  2. 记录--有关uni-app如何实现路由拦截的知识分享

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 随着业务的需求,项目需要支持H5.各类小程序以及IOS和Android,这就需要涉及到跨端技术,不然每一端都开发一套,人力成本和维护 ...

  3. (1,3,4,2,5)小和问题【Java】

    01[1,3,4,2,5]求小和 从右往左看:左边比右边小的加和到一起! 1 左边没有数 0 3 1 4 1+3 2 1 5 1+3+4+2 从左往右看:有几个数右边比左边大 1 4个数: 3 4 2 ...

  4. 【已解决】Hadoop_01 Linux修改hosts文件

    设置主机名 [root@localhost ~]# hostnamectl set-hostname s1[root@localhost ~]# reboot 修改hosts文件 [root@mast ...

  5. vue3中router配置中的children怎么用

    在Vue 3中,当你使用Vue Router创建路由配置时, children属性允许你为某个路由定义嵌套路由.这意味着你可以在父路由下设置子路由,从而构建出具有层级结构的URL路径. 这里是一个基本 ...

  6. 小师妹学JavaIO之:文件写入那些事

    目录 简介 字符输出和字节输出 格式化输出 输出其他对象 在特定的位置写入 给文件加锁 总结 简介 小师妹又对F师兄提了一大堆奇奇怪怪的需求,要格式化输出,要特定的编码输出,要自己定位输出,什么?还要 ...

  7. OpenHarmony社区运营报告(2023年2月)

      本月快讯 • 2023年2月25日,以"技术构筑万物智联"为主题的第一届开放原子开源基金会OpenAtom OpenHarmony(以下简称"OpenHarmony& ...

  8. SQL LIKE 运算符:用法、示例和通配符解释

    SQL中的LIKE运算符用于在WHERE子句中搜索列中的指定模式.通常与LIKE运算符一起使用的有两个通配符: 百分号 % 代表零个.一个或多个字符. 下划线 _ 代表一个单个字符. 以下是LIKE运 ...

  9. Matplotlib绘图设置---坐标轴上下限/标题设置

    坐标轴上下限设置 plt.plot(x, np.sin(x)) #设置坐标轴上下限 plt.xlim(-1, 11) plt.ylim(-1.5, 1.5) plt.plot(x, np.sin(x) ...

  10. climits 与 符号常量

    climits  在老式中是 limits.h 一.引入 #include <climits> 或者 #include <limits.h> 二.符号常量 符号常量 表示 CH ...