【发布时间】:2013-10-02 10:28:11
【问题描述】:
我想编写一个适用于三个主要 Office 应用程序(Excel、PowerPoint、Word)的 VBA 代码模块。
由于每个应用程序中的对象模型不同,如果我在 Excel VBE 中编写特定于 PowerPoint 的代码,项目将无法编译。首先要走的路似乎是使用条件编译器常量。但这仍然会导致 VBE 吐出错误,具体取决于 VBE 当前托管在哪个 MSO 应用程序中。
在下面的简化示例中,我想将图片添加到工作表、幻灯片或文档中,具体取决于运行 VBA 代码的应用程序。如果我尝试在 Excel 中编译它,PowerPoint 代码将无法编译(即使它在条件编译器 If...Then 语句中!),反之亦然。如何在不添加对其他 MSO 应用程序的引用的情况下解决此问题(因为这会在分发到不同的 MSO 版本时导致兼容性问题)?
编译器继续查看应该被条件编译器常量有效“注释掉”的代码的方式是非常奇怪/烦人的行为!
' Set the compiler constant depending on which MSO app is hosting the VBE
' before saving as the respective .ppam/.xlam/.dotm add-in
#Const APP = "EXL"
Option Explicit
Dim curSlide As Integer
Dim curSheet As Integer
Public Sub InsertPicture()
Dim oShp as Shape
#If APP = "PPT" Then
' Do PowerPoint stuff
' The next 2 lines will throw "Invalid qualifier" and
' "Variable not defined" errors respectively when compiling in Excel.
curSlide = ActiveWindow.View.Slide.SlideIndex
Set oShp = ActivePresentation.Slides(curSlide).Shapes.AddPicture & _
(filename, msoFalse, msoTrue, 0, 0)
#ElseIf APP = "EXL" Then
' Do Excel stuff
curSheet = ActiveWindow.ActiveSheet
Set oShp = ActiveSheet.AddPicture(filename, msoFalse, msoTrue, 0, 0)
#ElseIf APP = "WRD" Then
' Do Word stuff
#End If
End Sub
由于我无法回答自己的问题:
扩展您的 KazJaw 想法,我认为这样的事情可能会起作用,用 GetObject 替换 CreateObject 函数(因为该实例已经存在,因为该过程是从加载项中调用的):
' CONDITIONAL COMPILER CONSTANTS
' Set this value before saving to .ppam, .xlam or .dotm
#Const APP = "EXL" ' Allowed Values : PPT, EXL or WRD
Sub One_Sub_For_Word_Excel_PP(filename As String, Optional SlideIndex as Integer)
#If APP = "PPT" Then
Dim appPPP As Object
Set appPPT = GetObject(, "PowerPoint.Application")
appPPT.ActivePresentation.Slides(SlideIndex).Shapes.AddPicture & _
(filename,msoFalse,msoTrue,0,0)
#ElseIf APP = "EXL" Then
Dim appEXL As Object
Set appEXL = GetObject(, "Excel.Application")
appEXL.ActiveSheet.AddPicture(filename, msoFalse, msoTrue, 0, 0)
#ElseIf APP = "WRD" Then
Dim appWRD As Object
Set appWRD = GetObject(, "Word.Application")
appWRD.ActiveDocument.AddPicture(filename, msoFalse, msoTrue, 0, 0)
#End If
End Sub
【问题讨论】:
-
说实话,我无法想象我想使用您正在尝试准备的解决方案的情况。有一种选择,但效率非常非常低。您对这样的解决方案感兴趣吗?
-
这种情况反映了 MSO 中的许多功能在所有应用程序中都是通用的。我正在写的内容完全相同,因为我希望在 3 个主要 MSO 应用程序中提供相同的功能,所以是的,我对解决方案感兴趣,但是当你说“非常、非常低效”时,你是什么意思?对于程序员还是用户还是机器?
-
两个附加选项:编写COM add-in,或在
Auto_Open事件上,以编程方式确保启用对三个库中的每一个的引用,这样它应该可以编译。 (我用一个在 PPT 或 XLS 中运行的应用程序完成了后者) -
有没有办法根据当前应用动态设置应用名称(而不是设置APP常量)? (注意:我从未编写过 COM 插件。)
标签: vba excel ms-word ms-office powerpoint