- VBA是MS Office的标准脚本语言。普通的pptx结尾的PowerPoint文件无法保存VBA脚本,只有以pptm结尾的文件可以。
- MS Office自带VBA的开发工具,在Ribbon中开启Develop Tab才能看到VBA开发工具的启动按钮。对于属于Visual Studio的,VBA的开发工具应该可以很快上手。
技巧一,使用Debugger查看物件属性
VBA开发工具中竟然没有办法像浏览器的开发工具那样,可以有检视工具,用来对Office文档中的物件进行检视。一个变通的办法是使用Debug工具。
首先输入以下代码
Sub ShowIt()
Set ActiveShape = ActiveWindow.Selection.ShapeRange(1)
End Sub
然后在Set ActiveShape = ActiveWindow.Selection.ShapeRange(1)
打断点,接着执行这个脚本,就可以在VBA开发工具里面查看ActiveShape的属性了。
Determine The Current ActiveShape In PowerPoint With VBA
任务一,处理PowerPoint事件
PowerPoint的事件都集中在Application对象。挂载事件处理函数需要特殊的设置,参考Use Events with the Application Object。
' in Module1
Public WithEvents App As Application
Private Sub App_SlideSelectionChanged(ByVal SldRange As SlideRange)
If SldRange.Count > 0 Then
Debug.Print SldRange(1).Name
End If
End Sub
' in Class1
Dim X As New Class1
Sub InitializeApp()
Set X.App = Application
End Sub
上面处理的是SlideSelectionChanged事件。
任务二,为选中的一个Section下的Slides添加目录页
Public Function AddTocSlideForSelectedSlides() As slide
Dim index As Long
Set oCustomLayout = ActivePresentation.Designs(1).SlideMaster.CustomLayouts(23)
index = ActiveWindow.Selection.SlideRange(1).SlideIndex
Set oNewSlide = ActivePresentation.Slides.AddSlide(index + 1, oCustomLayout)
ActivePresentation.Slides(index).MoveTo (index + 1)
Set AddTocSlideForSelectedSlides = oNewSlide
End Function
Public Function GetSectionName() As String
sectionIndex = ActiveWindow.Selection.SlideRange(1).sectionIndex
GetSectionName = ActivePresentation.SectionProperties.Name(sectionIndex)
End Function
Sub AddTocWithHyperlinksForSelectedSlides()
Dim oSlide As slide
Set oTocSlide = AddTocSlideForSelectedSlides()
oTocSlide.Shapes.Title.TextFrame.TextRange = GetSectionName()
oTocSlide.Shapes(2).TextFrame2.Column.Number = 2
Set bodyContent = oTocSlide.Shapes.Placeholders(2).TextFrame
For Each oSlide In ActiveWindow.Selection.SlideRange
If oSlide.Shapes.HasTitle Then
Set oTitle = oSlide.Shapes.Title.TextFrame.TextRange
titleText = RTrim(oTitle.Text)
If Right(titleText, 1) = Chr(11) Then titleText = Left(titleText, Len(titleText) - 1)
bodyContent.TextRange.InsertAfter (titleText & Chr(11) & "(link)" & Chr(13))
linkStart = InStrRev(bodyContent.TextRange.Text, "(link)")
With bodyContent.TextRange.Characters(linkStart, Len("(link)")).ActionSettings(ppMouseClick).Hyperlink
.SubAddress = oSlide.SlideID & "," & oSlide.SlideIndex & "," & titleText
End With
End If
Next
End Sub
上面的代码参考了 Powerpoint - creating a hyperlink table of contents using vba。
任务三,创建一个PowerPoint Add-in
参考Quick Access Toolbar - MS PowerPoint 2013,在PowerPoint里面,可以直接在Ribbon上添加Custom Macro,可是这个Custom Macro会锁定在某个文件。比如MyFile.PPTM!MySubroutine
这个例子中,这个Custom Macro对应的是MyFile.PPTM中的MySubroutine。要使用这个Custom Macro,必须保持MyFile.PPTM处于打开状态。
Creating PowerPoint Add-Ins from VBA defined Macros,可以把一个PPTM文件保存成一个PPAM文件,默认情况下保存的路径是%appdata%\Microsoft\AddIns
底下。但是如何加载这个Add-in,需要参考Add or load a PowerPoint add-in。
但是默认情况下,但是PPAM中的宏无法直接加载,除非通过Edit a .ppam file for customizing an add-in记述的办法修改注册表:
HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\PowerPoint\Options
(That'd be for PPT 2010; substitute 16.0 in place of 14.0 for PPT 2016/365 and PPT 2019, 15.0 for PPT 2013, 12.0 for PPT 2007 and so on ... there's no 13.0)
Add a new DWORD value: DebugAddins = 1
一个变通的办法是通过CustomUI来为PPAM中的VBA添加一个UI交互控件。假设有下面的VBA代码:
Sub Hello()
MsgBox "Hello"
End Sub
可以把下面的XML片段注入PPAM的母版,也就是PPTM:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="CustomTab" label="Custom Tab">
<group id="DefaultGroup" label="Default">
<button id="helloButton" label="Hello" imageMso="HappyFace" size="large" onAction="Hello" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
其他参考
PowerPoint的文件格式pptx和pptm是基于OpenXML格式的,其规范可以参照文档[MS-PPTX] -v20201117PowerPoint (.pptx) Extensions to the Office Open XML File FormatCopyright © 2020 Microsoft CorporationRelease: November 17, 2020[MS-PPTX]: PowerPoint (.pptx) Extensions to the Office Open XML File Format。
不是所有的OpenXML的特性都可以通过VBA操作。随着Office的在线化,VBA可能会式微,但应该不会消失。微软已经推出了使用JavaScript来开发Office的Add-in。但是这样的Add-in需要服务端的支持。而且相关的API也不够完备。
通过Python+Pywin32操作
- Automating MS Office w/ Python Programming via Win32 COM Library
- Automating Windows Applications Using COM
- Python for Win32 Extensions Help
- How to use Win32 API with Python?
通过IronPython操作
- Table of Contents - IronPython in Action
- WPF and MVVM in IronPython
- tobi-tobsen/IronPythonCharCounterExcel.py
- How to to send an email via Outlook using IronPython in TIBCO Spotfire®
- IronPython script which retrieves selected cells from an opened excel sheet and figures out the number of occurences for each of the letters used · GitHub
- How to Work With Office Applications in Iron Python - YouTube
通过.NET Interactive
.Net Interactive还在开发中,但是前景喜人。作成之后应该可以使用C#作为脚本语言来操作OFFICE的COM模型。
- dotnet/interactive
- What’s new in C# 9.0
- C# 9: towards First Class Support for Scripting
- Hitchhiker’s Guide to the C# scripting
- .NET Interactive Preview 3: VS Code Insiders and .NET Polyglot Notebooks
- .NET Interactive is here! | .NET Notebooks Preview 2
VBA相关参考
- How to return a result from a VBA function
- Where does VBA Debug.Print log to?
- How to Remove Line Break in String
If Right(titleText, 1) = Chr(11) Then titleText = Left(titleText, Len(titleText) - 1)
- vba hyperlinks and shape creation
- VBA: Select all slides of defined sections
- Are you able to use other languages instead of VB for Excel macros?
- PPT.WorkWithSections in MS PowerPoint 2010 to Insert, Move, Get Section Counts in VB.NET
- Table of contents for PPT
(本篇完)