VB6.0使用VBS中的Eval函数

时间:2022-09-17 11:46:59
原VBS代码
a=5
m="a"
msgbox eval(m)
存为a.vbs文件后 执行
VB6.0使用VBS中的Eval函数

然而用VB6.0使用下面代码没达到上面的效果

Private Sub Command1_Click()
Dim m As String
Dim a  As Long
a = 5
m = "a"
MsgBox Eval(m)
End Sub

Function Eval(ByVal Expressions As String) As Long
    Dim Mssc As Object
    Set Mssc = CreateObject("MSScriptControl.ScriptControl")
    Mssc.Language = "VBScript"
    Eval = Mssc.Eval(Expressions)
    Set Mssc = Nothing
End Function

VB6.0使用VBS中的Eval函数
请问下大家 怎么修改才能得到VBS中的效果
或者能直接用VB写个类似Eval效果的函数  能实现上面VB6.0中的结果和VBS中一样的

13 个解决方案

#1


本帖最后由 bcrun 于 2015-08-29 09:51:45 编辑
此帖算是涉及到比较常见的一类混合语言编程的问题,楼主显然是想当然的把vbs和vb里的eval当成可*替换,交叉执行什么的了。我觉得还是应该尽量保持不同语言代码块的独立性。 这里面的道理其实有点绕,短时间内我讲不清楚,还是直接给出改好的代码供模仿更现实些。


Private Sub Command1_Click()

MsgBox Eval("a = 5 : m = ""a""", "eval(m)")
End Sub

Function Eval(ByVal PreCode As String, ByVal Expressions As String) As Long
    Dim Mssc As Object
    Set Mssc = CreateObject("MSScriptControl.ScriptControl")
    Mssc.Language = "VBScript"
    Call Mssc.addcode(PreCode)
    Eval = Mssc.Eval(Expressions) '控件的Eval方法只能执行个表达式,因为实际上这个表达式还受前面执行的代码影响,所以需要先用addcode加进代码
    Set Mssc = Nothing
End Function


#2


谢谢 bcrun
但这样之后就失去了 我本来的用意了 
我的目的就是在VB6.0中  读取 字符串对应变量的值   
能用VB写一个Eval函数不呢  

#3


引用 2 楼 u013968698 的回复:
谢谢 bcrun
但这样之后就失去了 我本来的用意了 
我的目的就是在VB6.0中  读取 字符串对应变量的值   
能用VB写一个Eval函数不呢  


不现实的,你这样基本上是动态语言、脚本语言那类的特性了,显然,VB6甚至后来的VB.NET都不是这类东西。虽然.net中可以动态编译执行代码,但那实际上还是要编译成DLL什么的。说实话,你要做这功能,是想满足什么样的实际需求呢?

#4


该回复于2015-08-29 17:38:08被版主删除

#5


    Dim 小赵 As Long
    Dim 小钱 As Long
    Dim 小孙 As Long
    Dim 小周 As Long
    Dim 小郑 As Long
    Dim 小王 As Long
    Dim 小冯 As Long
    Dim 小陈 As Long
    Dim 小卫 As Long
    Dim 小蒋 As Long
    Dim 小沈 As Long
    Dim 小韩 As Long
    Dim 小杨 As Long
    '......
    '后面省略无数个 几千个以上
    '假如上面定义的是学号
    小赵 = 0
    小钱 = 1
    小孙 = 2
    小周 = 3
    小郑 = 4
    小王 = 5
    小冯 = 6
    小陈 = 7
    小卫 = 8
    小蒋 = 9
    小沈 = 10
    小韩 = 11
    小杨 = 12
    '......
    '当用户输入一个名字的时候  就立即返回它的学号
    '如果是数据很少完全可以用下面的
    '第一种 Select Case语句
    Dim Num As Long
    Select Case 名字
    Case 小赵
        Num = 0
    Case 小钱
        Num = 1
        '......
    End Select
    '第二种 if 语句
    If 名字 = "小赵" Then
        Num = 0
    ElseIf 名字 = "小钱" Then
        Num = 1
        '......
    End If
    '关键是数据量比较大 几千上万个  在循环结构里一直查询 速度相当的慢
    '用读取ini文件 采用键名、键值这种我觉得在循环读取中都比Select Case
    '和if语句快N倍,但如果是多线程读取的时候又会有其它麻烦了
    '所以才有了上面发帖的那种想法 直接给字符串,然后获得对应变量的值
    '在其它语言中实现都比较简单像VBS的Eval函数  不知道VB6.0能否实现

#6


或者保存到数据库中吧。“多线程读取的时候又会有其它麻烦了”,具体是什么麻烦呢?

#7


引用 6 楼 bcrun 的回复:
或者保存到数据库中吧。“多线程读取的时候又会有其它麻烦了”,具体是什么麻烦呢?

保存到数据库的话   的确是减少了VB6.0里面定义变量的代码量 但是没提高读取速度呀  数据库读取速度根据连if的速度都比不上
具体麻烦比如:   多线程同时读写同个文件会造成文件错乱.  
所以想找个好方法 我个人也想了很久觉得 读ini文件的速度快的多 但这种方案 同时几个进程或者线程读取它的时候就会出问题

#8


搜索了很多帖子 看到的都是很多其它语言的 说要用“反射”
http://www.2cto.com/kf/201312/262551.html
http://blog.csdn.net/you_and_me12/article/details/7218318
不知道VB6.0可以用上这种技术不呢 

#9


首先,要搞清楚,所谓“反射”里说的“变量”一般是指的类的“成员变量”,不是你前面说的普通变量。这个在VB6里有个类似的CallByName。
其次,既然是要在多线程中访问,应该也是不能如你这种直接定义成变量来处理的。
刚想起来,有个“内存映像文件”,好像可以满足你说的多进程高速访问的需求,不过我也没测试过。

#10


再次谢谢 bcrun 的耐心解答
    Dim TheName() As String, TheNum() As Integer
    TheName(0) = "小赵": TheNum(0) = 100
    TheName(1) = "小钱": TheNum(1) = 200
    TheName(2) = "小孙": TheNum(2) = 300
    TheName(3) = "小周": TheNum(3) = 400
    TheName(4) = "小郑": TheNum(4) = 500
    TheName(5) = "小王": TheNum(5) = 100
    TheName(6) = "小冯": TheNum(6) = 200
    TheName(7) = "小陈": TheNum(7) = 300
    TheName(8) = "小卫": TheNum(8) = 400
    TheName(9) = "小蒋": TheNum(9) = 500
    TheName(10) = "小沈": TheNum(10) = 100
    TheName(11) = "小韩": TheNum(11) = 200
    TheName(12) = "小杨": TheNum(12) = 300
    '......省略几千上万个
    '是否可以根据TheName的值 返回其数组索引
    '再用TheNum(索引) 得到其值
    '最大的问题就是返回数组索引的速度了,用if
    '和Select Case那个速度肯定是不能接受的
    '不知道有没有好的方法

#11


谢谢 bcrun 版主的帮忙 我这个问题解决了  
完美的解决方案: 将所有全局变量定义在类模块中
然后使用反射 就是VB6.0中的CallByName,现在的
我最担心的问题是类模块中的全局变量可以定义多少
个呢,如果类模块可以定义无限制个全局变量,那就
太好了!

#12


特别强调一句:我觉得包括VB6在内的所有编程语言,你都不要指望,为了适合程序功能,使用“无限制行数”的代码来实现功能,难道你要处理几百万人的数据还一一对应的写几百万行代码?

首先,要搞清楚,所谓“反射”里说的“变量”一般是指的类的“成员变量”,不是你前面说的普通变量。这个在VB6里有个类似的CallByName。
其次,既然是要在多线程中访问,应该也是不能如你这种直接定义成变量来处理的。
刚想起来,有个“内存映像文件”,好像可以满足你说的多进程高速访问的需求,不过我也没测试过。


Re:"如果类模块可以定义无限制个全局变量",肯定不会是无限多个,而应该是很少的量,比如说几千个,msdn library中好像有提到,当然你自己编程批量生成一下代码更好些。本想着你这需求中,可能最在的麻烦是多线程访问,不过你既然更希望讨论下这个数据结构方面的表达,那就暂只说说这个好了。另一种种也许可行的方案就是,用VB6内置的collection类来表示:

Option Explicit
Private mPeople As Collection
Private Sub DoLoadData()
    Set mPeople = New Collection
    With mPeople
        .Add 100, "小赵"
        .Add 200, "小钱"
        .Add 300, "小孙"
    
        
    
    End With
End Sub


Private Sub Command1_Click()
    DoLoadData
    Debug.Print mPeople("小赵")
    Debug.Print mPeople("小孙")
End Sub

#13


谢谢 bcrun 版主  
根据您的意见 使用 Collection 集合类  这样做确实非常好  代码也简洁了  
本人VB知识浅薄  不是您在楼上提出这个Collection类 我都没听说过     
感谢您的指点  让我受益匪浅  学习和使用VB的道路上有大家的帮忙 真是太好了
CSDN确实是个非常好的学习交流平台

#1


本帖最后由 bcrun 于 2015-08-29 09:51:45 编辑
此帖算是涉及到比较常见的一类混合语言编程的问题,楼主显然是想当然的把vbs和vb里的eval当成可*替换,交叉执行什么的了。我觉得还是应该尽量保持不同语言代码块的独立性。 这里面的道理其实有点绕,短时间内我讲不清楚,还是直接给出改好的代码供模仿更现实些。


Private Sub Command1_Click()

MsgBox Eval("a = 5 : m = ""a""", "eval(m)")
End Sub

Function Eval(ByVal PreCode As String, ByVal Expressions As String) As Long
    Dim Mssc As Object
    Set Mssc = CreateObject("MSScriptControl.ScriptControl")
    Mssc.Language = "VBScript"
    Call Mssc.addcode(PreCode)
    Eval = Mssc.Eval(Expressions) '控件的Eval方法只能执行个表达式,因为实际上这个表达式还受前面执行的代码影响,所以需要先用addcode加进代码
    Set Mssc = Nothing
End Function


#2


谢谢 bcrun
但这样之后就失去了 我本来的用意了 
我的目的就是在VB6.0中  读取 字符串对应变量的值   
能用VB写一个Eval函数不呢  

#3


引用 2 楼 u013968698 的回复:
谢谢 bcrun
但这样之后就失去了 我本来的用意了 
我的目的就是在VB6.0中  读取 字符串对应变量的值   
能用VB写一个Eval函数不呢  


不现实的,你这样基本上是动态语言、脚本语言那类的特性了,显然,VB6甚至后来的VB.NET都不是这类东西。虽然.net中可以动态编译执行代码,但那实际上还是要编译成DLL什么的。说实话,你要做这功能,是想满足什么样的实际需求呢?

#4


该回复于2015-08-29 17:38:08被版主删除

#5


    Dim 小赵 As Long
    Dim 小钱 As Long
    Dim 小孙 As Long
    Dim 小周 As Long
    Dim 小郑 As Long
    Dim 小王 As Long
    Dim 小冯 As Long
    Dim 小陈 As Long
    Dim 小卫 As Long
    Dim 小蒋 As Long
    Dim 小沈 As Long
    Dim 小韩 As Long
    Dim 小杨 As Long
    '......
    '后面省略无数个 几千个以上
    '假如上面定义的是学号
    小赵 = 0
    小钱 = 1
    小孙 = 2
    小周 = 3
    小郑 = 4
    小王 = 5
    小冯 = 6
    小陈 = 7
    小卫 = 8
    小蒋 = 9
    小沈 = 10
    小韩 = 11
    小杨 = 12
    '......
    '当用户输入一个名字的时候  就立即返回它的学号
    '如果是数据很少完全可以用下面的
    '第一种 Select Case语句
    Dim Num As Long
    Select Case 名字
    Case 小赵
        Num = 0
    Case 小钱
        Num = 1
        '......
    End Select
    '第二种 if 语句
    If 名字 = "小赵" Then
        Num = 0
    ElseIf 名字 = "小钱" Then
        Num = 1
        '......
    End If
    '关键是数据量比较大 几千上万个  在循环结构里一直查询 速度相当的慢
    '用读取ini文件 采用键名、键值这种我觉得在循环读取中都比Select Case
    '和if语句快N倍,但如果是多线程读取的时候又会有其它麻烦了
    '所以才有了上面发帖的那种想法 直接给字符串,然后获得对应变量的值
    '在其它语言中实现都比较简单像VBS的Eval函数  不知道VB6.0能否实现

#6


或者保存到数据库中吧。“多线程读取的时候又会有其它麻烦了”,具体是什么麻烦呢?

#7


引用 6 楼 bcrun 的回复:
或者保存到数据库中吧。“多线程读取的时候又会有其它麻烦了”,具体是什么麻烦呢?

保存到数据库的话   的确是减少了VB6.0里面定义变量的代码量 但是没提高读取速度呀  数据库读取速度根据连if的速度都比不上
具体麻烦比如:   多线程同时读写同个文件会造成文件错乱.  
所以想找个好方法 我个人也想了很久觉得 读ini文件的速度快的多 但这种方案 同时几个进程或者线程读取它的时候就会出问题

#8


搜索了很多帖子 看到的都是很多其它语言的 说要用“反射”
http://www.2cto.com/kf/201312/262551.html
http://blog.csdn.net/you_and_me12/article/details/7218318
不知道VB6.0可以用上这种技术不呢 

#9


首先,要搞清楚,所谓“反射”里说的“变量”一般是指的类的“成员变量”,不是你前面说的普通变量。这个在VB6里有个类似的CallByName。
其次,既然是要在多线程中访问,应该也是不能如你这种直接定义成变量来处理的。
刚想起来,有个“内存映像文件”,好像可以满足你说的多进程高速访问的需求,不过我也没测试过。

#10


再次谢谢 bcrun 的耐心解答
    Dim TheName() As String, TheNum() As Integer
    TheName(0) = "小赵": TheNum(0) = 100
    TheName(1) = "小钱": TheNum(1) = 200
    TheName(2) = "小孙": TheNum(2) = 300
    TheName(3) = "小周": TheNum(3) = 400
    TheName(4) = "小郑": TheNum(4) = 500
    TheName(5) = "小王": TheNum(5) = 100
    TheName(6) = "小冯": TheNum(6) = 200
    TheName(7) = "小陈": TheNum(7) = 300
    TheName(8) = "小卫": TheNum(8) = 400
    TheName(9) = "小蒋": TheNum(9) = 500
    TheName(10) = "小沈": TheNum(10) = 100
    TheName(11) = "小韩": TheNum(11) = 200
    TheName(12) = "小杨": TheNum(12) = 300
    '......省略几千上万个
    '是否可以根据TheName的值 返回其数组索引
    '再用TheNum(索引) 得到其值
    '最大的问题就是返回数组索引的速度了,用if
    '和Select Case那个速度肯定是不能接受的
    '不知道有没有好的方法

#11


谢谢 bcrun 版主的帮忙 我这个问题解决了  
完美的解决方案: 将所有全局变量定义在类模块中
然后使用反射 就是VB6.0中的CallByName,现在的
我最担心的问题是类模块中的全局变量可以定义多少
个呢,如果类模块可以定义无限制个全局变量,那就
太好了!

#12


特别强调一句:我觉得包括VB6在内的所有编程语言,你都不要指望,为了适合程序功能,使用“无限制行数”的代码来实现功能,难道你要处理几百万人的数据还一一对应的写几百万行代码?

首先,要搞清楚,所谓“反射”里说的“变量”一般是指的类的“成员变量”,不是你前面说的普通变量。这个在VB6里有个类似的CallByName。
其次,既然是要在多线程中访问,应该也是不能如你这种直接定义成变量来处理的。
刚想起来,有个“内存映像文件”,好像可以满足你说的多进程高速访问的需求,不过我也没测试过。


Re:"如果类模块可以定义无限制个全局变量",肯定不会是无限多个,而应该是很少的量,比如说几千个,msdn library中好像有提到,当然你自己编程批量生成一下代码更好些。本想着你这需求中,可能最在的麻烦是多线程访问,不过你既然更希望讨论下这个数据结构方面的表达,那就暂只说说这个好了。另一种种也许可行的方案就是,用VB6内置的collection类来表示:

Option Explicit
Private mPeople As Collection
Private Sub DoLoadData()
    Set mPeople = New Collection
    With mPeople
        .Add 100, "小赵"
        .Add 200, "小钱"
        .Add 300, "小孙"
    
        
    
    End With
End Sub


Private Sub Command1_Click()
    DoLoadData
    Debug.Print mPeople("小赵")
    Debug.Print mPeople("小孙")
End Sub

#13


谢谢 bcrun 版主  
根据您的意见 使用 Collection 集合类  这样做确实非常好  代码也简洁了  
本人VB知识浅薄  不是您在楼上提出这个Collection类 我都没听说过     
感谢您的指点  让我受益匪浅  学习和使用VB的道路上有大家的帮忙 真是太好了
CSDN确实是个非常好的学习交流平台