excel - excel如何才能找出代码是否以 VBScript,. HTA, 或者VBA形式运行?

  显示原文与译文双语对照的内容
86 1

编辑:到目前为止,大多数响应都是检查可以能存在的对象,这是在( 它引发编译时错误,因这里错误无效,并且关闭选项显式不是选项。) 中的选项显式。 这里还有其他的循环/out-of-the-box方法来了解这里需要什么?

我试图编写一般的copy-and-paste代码,它将在独立的VBScript ( 。. vbs 文件) 中工作,在. hta 文件中,作为 VBA ( 例如在Excel文件中) 。 为这里,我需要一些方法来使代码本身知道它在哪个引擎中运行。

我到目前为止听到的最好的想法是测试某些对象是否存在,但在VBA中失败。 试图查找它运行的文件的名称并不是可以行的;这是根据三个脚本引擎运行的代码之一。 我希望有一些简单的东西,但不确定要用什么填充它:


Option Explicit



'--- Returns a string containing which script engine this is running in,


'--- either"VBScript","VBA", or"HTA".



Function ScriptEngine()



 If {what goes here?} Then ScriptEngine="VBS"


 If {what goes here?} Then ScriptEngine="VBA"


 If {what goes here?} Then ScriptEngine="HTA"


 End Function



如果这是正确的,你应该能够将该函数复制和粘贴到任何 VBA ,或者,文件中。 最好的方法是什么?

时间:

58 3

在VBA实现中需要 Option Explicit的限制使得这一点比它的它的要困难,否则就是( 这是一个没有它的liner 。) 。 讽刺的是,这也是解决问题的关键。 如果你没有将自己限制到单个函数中,可以通过执行以下操作来离开它:


Dim hta



Sub window_onload()


 hta = True


End Sub



Function HostType()


 On Error Resume Next


 If hta Then


 HostType ="HTA"


 Else


 Dim foo


 Set foo = foo


 If Err.Number = 13 Then


 HostType ="VBA"


 Else


 HostType ="VBS"


 End If


 End If


End Function



如果通过一个文件加载,window_onload 事件处理程序运行,将 hta 变量设置为 True 。 这是第一个测试第二个"测试"是由线路抛出的错误 Set foo = foo 这里类型不匹配,它解释为尝试将转换为 Empty,这不是兼容类型。 同一行代码在VBScript中抛出错误 424 ( 需要对象),因为它不是强类型语言。 这意味着skipped检查被跳过,它尝试实际执行分配( 失败了) 。 剩下的就是找出它是如何抛出并返回结果的。

测试代码

VBA


Option Explicit



Dim hta



Sub Test()


 Debug.Print HostType 'VBA


End Sub



Sub window_onload()


 hta = True


End Sub



Function HostType()


 On Error Resume Next


 If hta Then


 HostType ="HTA"


 Else


 Dim foo


 Set foo = foo


 If Err.Number = 13 Then


 HostType ="VBA"


 Else


 HostType ="VBS"


 End If


 End If


End Function



VBScript


WSCript.Echo HostType



Dim hta



Sub window_onload()


 hta = True


End Sub



Function HostType()


 On Error Resume Next


 If hta Then


 HostType ="HTA"


 Else


 Dim foo


 Set foo = foo


 If Err.Number = 13 Then


 HostType ="VBA"


 Else


 HostType ="VBS"


 End If


 End If


End Function




<HTML>


 <BODY>


 <script type="text/vbscript">


 Dim hta



 Sub Test()


 MsgBox HostType 


 End Sub



 Sub window_onload()


 hta = True


 End Sub



 Function HostType()


 On Error Resume Next


 If hta Then


 HostType ="HTA"


 Else


 Dim foo


 Set foo = foo


 If Err.Number = 13 Then


 HostType ="VBA"


 Else


 HostType ="VBS"


 End If


 End If


 End Function


 </script>


 <button onclick="vbscript:Test()">Click me</button> 


 </BODY>


</HTML>



编辑:

FWIW,如果不需要 Option Explicit,上面引用的一个接口就是:


Function HostString()


 HostString = Application & document & WScript


End Function



所有三个对象都有一个返回 String的默认属性。 在VBScript中,这将返回"Windows 脚本主机"。 在VBA中,它将返回主机的NAME ( 例如 。 。Excel"在Excel中) 。在卫生技术中,它将返回"[object]"。

原作者:
121 3

尝试检查上下文对象的存在,例如


Function ScriptEngine()


 dim tst


 on error resume next


 Err.Clear


 tst = WScript is Nothing


 if Err=0 then ScriptEngine="WScript" : exit function


 Err.Clear


' similar way check objects in other environments



End Function



129 0

我建议你向后逼近问题。 你应该拥有一个通用的任务接口,而不是询问"谁是这里的主持人"。 例如你将有一个模块- 让我们称之为 MyAPI:


Public Function MySleep(Milliseconds As Long)


End Function



然后,你可以为VBA实现一个,一个用于 VBS,另一个用于 HTA ( 尽管我质疑是否存在一个真正的差异) 。 你的主机不可知代码将需要包含该模块,所有该模块都应该允许。 例如在这里查看包含一个文件到VBS的文件。 它看起来像技术有类似的东西。 在VBA中,这只是另一个模块。

然后在不可知的主机代码中,可以调用 MySleep 而不是声明为 Sleep 或者 WScript.Sleep的api,并让包含的模块提供主机特定实现,而不需要禁用 Option Explicit,也不需要测试不存在的对象。

原作者:
125 1

任何未声明的变量都是 Variant/Empty,因此如果 something 未定义,VarType(something) 将为 vbEmpty ( 或者 0 ) 。

除非 VarType 标准库( 我不知道 TBH ) 之外不存在,否则无需对这里工作进行任何错误,即在VBA中测试:


Function GetHostType()


 If VarType(wscript) <> vbEmpty Then


 GetHostType ="VBS"


 Exit Function


 End If 


 If VarType(Application) <> vbEmpty Then


 GetHostType ="VBA"


 Exit Function


 End If 


 GetHostType ="HTA"


End Function



注意,如果 比如 Application 或者 WScript 被定义为,并且主机不是VBA或者 VBScript,那么这将产生意外结果。

或者,不管是否定义了 VarType,这将起作用:


Function GetHostType()


 On Error Resume Next



 If Not WScript Is Nothing Then


 If Err.Number = 0 Then


 GetHostType ="VBS"


 Exit Function


 End If


 End If


 Err.Clear ' clear error 424 if not VBS



 If Not Application Is Nothing Then


 If Err.Number = 0 Then


 GetHostType ="VBA"


 Exit Function


 End If


 End If


 Err.Clear ' clear error 424 if not VBA



 GetHostType ="HTA"


End Function



再次假设这些名称没有定义对象;机制依赖于 WScript/Application,因此在测试时抛出运行时错误 424"需要对象"。

请注意,不能为这里指定 Option Explicit 。 原因是,如果你执行 Dim WScriptDim Application,那么在运行时这些变量将重影你检查的全局标识符。

原作者:
...