本文告诉大家如何读取 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. TP6框架--EasyAdmin学习笔记:Excel表单导入数据库

    这是我写的学习EasyAdmin的第四章,这一章我给大家分享下Excel表单导入数据库的全流程需要怎么处理并提供案例 首先给大家看下这个功能的原理,下面是PHP连接打印机的代码 public func ...

  2. 记录--新的HTML标签 :<search>

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 本文介绍了一种新的HTML元素搜索方法,并提供了一个实用的工具来帮助开发者快速找到所需的元素.这对于那些需要处理大量HTML元素的开发者来 ...

  3. 记录-VueJs中如何使用Teleport组件

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 在DOM结构相对比较复杂,层级嵌套比较深的组件内,需要根据相对应的模块业务处理一些逻辑,该逻辑属于当前组件 但是从整个页面应用的视图上看, ...

  4. GIT版本控制学习博客

    GIT版本控制学习博客 环境部署 下载git版本控制即可. 用户配置 (1)设置用户及地址 git config --global user.name "Username" git ...

  5. vivado的非嵌入ILA的使用

    vivado非嵌入ILA的使用 1.实验原理 前面在vivado中联合vitis设计时接触过ila,那个时候采用的方法是直接调用IP核在原理图中连接.这个方法简单直接,可以将自己所需的测量信号转移到I ...

  6. KingbaseES 数据库连接

    一.数据准备: create table student( id int , s_name varchar(20), t_id int ); create table teacher( id int ...

  7. 【已解决】xml映射找不到类名java.lang.ClassNotFoundException

    XMLUtil文件里的Class.forName 参数要写相对于项目根目录的绝对路径,除了类名要加上对应的包路径!

  8. Kylin Desktop V10部署达梦数据库(DM8)

    1.环境 处理器:飞腾D2000/8 E8C 内存:16GB 系统:银河麒麟桌面版操作系统(国防版)V10 达梦数据库:dm8_20231226_FTarm2000_kylin10_sp1_64 2. ...

  9. #线段树#LOJ 6029「雅礼集训 2017 Day1」市场

    题目 在长度为\(n(n\leq 10^5)\)的数列中, 需要满足区间加,区间下取整的操作 以及能够查询区间和以及区间最小值 除数\(d\)满足\(2\leq d\leq 10^9\) 加数\(c\ ...

  10. Socket.D v2.4.9 发布

    Socket.D 是什么东东? 是基于"事件"和"语义消息""流"的网络应用协议.在微服务.移动应用.物联网等场景,可替代 http.web ...