vba - 如何在 PowerPoint 应用程序中获得字母之间的延迟?
问题描述
我想在 PowerPoint 中将动画导出为 mp4 并获取所有动画的时间线。
如果效果有,我如何获得字母之间的延迟EffectInformation.TextUnitEffect as msoAnimTextUnitEffectByCharacter
?
我读过的大多数 PowerPoint 文档,但没有关于“%delay between letters”的消息。
effectinformation
文档中没有消息作为字母之间的延迟(https://docs.microsoft.com/en-us/office/vba/api/powerpoint.effectinformation.textuniteffect)
CONST ppLayoutBlank = 12 ''ppt new black slide
CONST ppSaveAsMP4 = 39 ''ppSaveFormat for mp4
CONST ForAppending = 8 ''log file write for appending
const ppViewSlideMaster = 2 ''viewtype
const ppViewHandoutMaster = 4
const ppViewTitleMaster = 8
const ppViewMasterThumbnails = 12
const msoAnimTextUnitEffectByCharacter = 1
Dim filePath
dim logFilePath
dim logFile
dim fullPath
logFilePath = ".\convert.log" '''''''logfile
filePath = SelectFile()
if len(filePath)<1 then
wscript.quit
end if
MsgBox filePath + ";"
Set ObjFSO = CreateObject("Scripting.FileSystemObject")
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
''create log file
if ObjFSO.fileExists(logFilePath) then
set logFile = ObjFSO.OpenTextFile(logFilePath, ForAppending)
else
set logFile = ObjFSO.CreateTextFile(logFilePath)
end if
''do job
pptAnimate(filePath)
''quit or not
''objPPT.Quit()
Function SelectFile()
dim selectPath,selectPathLen
Set wShell=CreateObject("WScript.Shell")
Set oExec=wShell.Exec("mshta.exe ""about:<input type=file id=FILE><script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);</script>""")
selectPath = oExec.StdOut.ReadAll
selectPathLen = len(selectPath)
SelectFile = left(selectPath, selectPathLen-2)'''''remove \r\n, vbcr、vblf
End Function
Sub pptAnimate(pptPath)
if not (regMatch(pptPath, "\.(ppt|pptx)$")) then
exit sub
end if
Set pptInput = objPPT.Presentations.Open(pptPath)
logFile.WriteLine("slide count:" + cstr(pptInput.Slides.Count))
For i = 1 To pptInput.Slides.Count
if pptInput.Slides(i).TimeLine.MainSequence.Count > 0 then
Dim tmpPath
tmpPath = "F:\\word\\" + cstr(i) + ".pptx"
ObjFSO.CreateTextFile(tmpPath)
Set pptOutput = objPPT.Presentations.Open(tmpPath)
Set newSlide = pptOutput.Slides.Add(1, ppLayoutBlank)
pptOutput.PageSetup.slideWidth = pptInput.PageSetup.slideWidth
pptOutput.pageSetup.slideHeight = pptInput.pagesetup.slideheight
pptInput.Slides(i).Copy
pptOutput.Slides.Paste (pptOutput.Slides.Count)
logFile.WriteLine("page:" + cstr(i) + " sequence count:" + cstr(pptInput.Slides(i).TimeLine.MainSequence.Count))
For Each effect in pptInput.Slides(i).TimeLine.MainSequence
logFile.WriteLine("{delay time:" + cstr(effect.Timing.TriggerDelayTime) _
+ ", duration time:" + cstr(effect.Timing.Duration) _
+ ", Decelerate :" + cstr(effect.Timing.Decelerate) _
+ ", triggerType:" + getTriggerType(effect.Timing.TriggerType) _
+ ", Accelerate:" + cstr(effect.Timing.Accelerate) _
+ ", Decelerate:" + cstr(effect.Timing.Decelerate) _
+ ", Speed:" + cstr(effect.Timing.Speed) _
+ "}")
if msoAnimTextUnitEffectByCharacter = effect.EffectInformation.TextUnitEffect then
''I don't know how to get dealy between letters, have no way to set the effect to by graph
''effect.EffectInformation.TextUnitEffect = 0 '''readonly
end if
For Each behaviour in effect.Behaviors
logFile.WriteLine("behaviour {delay time :" + cstr(behaviour.Timing.TriggerDelayTime) + ", duration time :" + cstr(behaviour.Timing.Duration) + "}")
Next
Next
m = pptOutput.Slides.Count
pptOutput.Slides(m).Delete
''fullPath = "F:\\word\\"+cstr(i)+".mp4"
''pptOutput.SaveAs fullPath,ppSaveAsMP4
'''wait until the mp4 file exist,
'''msgbox fullPath
pptOutput.Save
pptOutput.Close
end if
Next
pptInput.Close
End Sub
Function regMatch(strng,Pattern)
Dim regEx
Set regEx = New RegExp
regEx.Pattern = Pattern
regEx.IgnoreCase = True
regEx.Global = True
regMatch = regEx.test(strng)
Set regEx = Nothing
End Function
'https://docs.microsoft.com/zh-cn/office/vba/api/powerpoint.msoanimtriggertype
Function getTriggerType(triggerType)
getTriggerType = ""
Select Case triggerType
Case 3
getTriggerType = "msoAnimTriggerAfterPrevious"
Case -1
getTriggerType = "msoAnimTriggerMixed"
Case 0
getTriggerType = "msoAnimTriggerNone"
Case 1
getTriggerType = "msoAnimTriggerOnPageClick"
Case 4
getTriggerType = "msoAnimTriggerOnShapeClick"
Case 2
getTriggerType = "msoAnimTriggerWithPrevious"
End Select
End Function
Function Format_Time(s_Time, n_Flag)
Dim y, m, d, h, mi, s
Format_Time = ""
If IsDate(s_Time) = False Then Exit Function
y = cstr(year(s_Time))
m = cstr(month(s_Time))
If len(m) = 1 Then m = "0" & m
d = cstr(day(s_Time))
If len(d) = 1 Then d = "0" & d
h = cstr(hour(s_Time))
If len(h) = 1 Then h = "0" & h
mi = cstr(minute(s_Time))
If len(mi) = 1 Then mi = "0" & mi
s = cstr(second(s_Time))
If len(s) = 1 Then s = "0" & s
Select Case n_Flag
Case 1
' yyyy-mm-dd hh:mm:ss
Format_Time = y & "-" & m & "-" & d & " "& h &":" & mi &":" & s
Case 2
' yyyy-mm-dd
Format_Time = y & "-" & m & "-" & d
Case 3
' hh:mm:ss
Format_Time = h & ":" & mi & ":" & s
Case 4
' yyyymmdd
Format_Time = y & m & d
End Select
End Function
解决方案
“字母之间的秒延迟”的值不直接暴露在对象模型中。
虽然仍然可以在 VBA 中提取值,但过程相当复杂。在高层次上,您需要:
- 使用 Presentation.SaveCopyAs 以“pptx”格式保存副本,但带有“zip”扩展名,例如 temp.zip
- 使用后期绑定创建
Shell.Application
对象 - 使用外壳对象复制
temp.zip\ppt\slides\slideN.xml
到文件夹(N
=幻灯片编号) - 读取 XML 文件并检查动画元素。您正在寻找的确切值(“字母之间的秒数延迟”)应该在像这样的元素中
<p:tmAbs val="50"/>
- 时间以毫秒为单位。因此
50
,示例中的 PowerPoint UI 中的时间为 0.05 秒。
因为同一张幻灯片上可能有很多动画,您可能需要在 XML 中找到正确的动画序列。这绝对不是一个简单的过程,在 VBA 中尤其具有挑战性。如果可能的话,我建议您使用 C# 或 VB.NET 构建一个小型实用程序 exe 文件来解析 XML 并直接从 PPTX 文件中读取必要的信息并从 VBA 调用程序。我们出于不同的目的做了类似的事情,而且效果很好。
前三个步骤可用于提取几乎所有无法通过对象模型获得的内容。对于 Word,您不必这样做,因为它公开了属性 WordOpenXML。不幸的是,Excel 或 PowerPoint 中不存在此类属性。
推荐阅读
- reactjs - 如何在没有 React Router 的情况下处理条件路由或组件导航
- java - 无法在 JBOSS 上启动 spring 批处理应用程序
- python - 如何删除文本中单词末尾可能出现的数字
- java - 如何在 Thymeleaf 中显示从“选择”到“文本字段”的选定项目?
- php - 为什么 current() 在 PHP 7 中不能与 foreach() 一起使用?
- android-studio - 如何在调试时检查表达式主体结果
- azure - 客户 ID 和租户 ID 有什么区别?
- regex - 根据文件名中的通配符检查文件是否存在
- orm - 从版本 11 升级到 ColdFusion 2018 后的 ORM 问题
- python - Python Pandas:基于另一个 Col 的列值的条件更新('int' 对象不可下标)错误