Getting value of a variable from string of variable name

QueenKirsty

Registered User.
Local time
Today, 01:15
Joined
Mar 13, 2009
Messages
31
Newbie to the forum here so sorry if this post is not totally clear!

I am trying to get the value of a variable by evaluating a string which matches the variable name.

As part of a State Machine I have a list of function names (delimited with %) that I want to run. The function string contains variable names. I want to use eval() to run the function but it cant convert the variable names in the string into their respective values from the sub that is calling eval().

To counter this I want to pull each variable out in turn, convert it to its value and then put it back in the string. The problem is I dont know how to match the string variable name with the variable value. I have put the whole code below to try and make it a little clearer. Any help would be gratefully appreciated! :o)

Public Sub doActions(Actions As String, TestInstID As Integer, StateID As Integer, STID As Integer)
'do actions from the state table - only variables are function params

'declare variables to be used
Dim comma As Boolean
Dim Act1, vars1, vars2, var3, Act2 As String
Dim FromStateID, ToStateID As Integer
Dim myArray As Variant

'if STID is not null then get details from stateTransition table
If STID > 0 Then
FromStateID = DLookup("FromStateID", "StateTransition", "STID = " & STID)
ToStateID = DLookup("ToStateID", "StateTransition", "STID = " & STID)
End If

'split the string of actions into individual actions in an array
myArray = Split(Actions, "%")
'for each action swap the variable names for their values and enact the action
For Each Act1 In myArray
'replace the variables with values
'get string of variables
Char1 = InStr(1, Act1, "(")
Char2 = InStr(1, Act1, ")")
len2 = Char2 - 1 - Char1
vars1 = MID(Act1, Char1 + 1, len2)
vars2 = ""
'loop through replace each variable name with its value
Do While vars1 <> ""
'get the variable name and check if there is a comma after it
'then reduce the variable name string being checked
If InStr(1, vars1, ",") > 0 Then
var3 = Left(vars1, InStr(1, vars1, ",") - 1)
comma = True
vars1 = MID(vars1, InStr(1, vars1, ",") + 1)
Else
var3 = vars1
comma = False
vars1 = ""
End If
'get the value of the variable and add it back into the list (with a comma after it where needed)

vars2 = vars2 + CStr(Eval(var3)) 'this is what won't work!!!!
If comma = True Then
vars2 = vars2 & ","
End If
Loop
'create the new action string with the new variable list
Act2 = Left(Act1, Char1 - 1) & "(" & vars2 & ")"

'run action
Eval Act2
Next Act1
End Sub
 
what is vars3 - if its a string then

clng(vars3) or cdbl(vars3)
 
vars2 = vars2 + CStr(Eval(var3)) 'this is what won't work!!!!

You don't say how it fails I wonder if as vars2 is a variant you should be using & not + for the concatenation.

I believe that only Act2 is defined as a string in the statement below, all of the others default to Variant.

Dim Act1, vars1, vars2, var3, Act2 As String



Brian
 
It's the eval(var3) that won't work! Sorry I didn't make that clear.

Eg.
The sub is called with doActions("doTest(TestInstID)" 1,4,0)

Act1 = "doTest(TestInstID)"
I need to replace the string "TestInstID" with the variable from the main function (i.e. 1) so that I end up with "doTest(1)" which I can then pass to
eval("doTest(1)")
if I try to do eval("doTest(TestInstID)") it doesn't recognise TestInstID as having the variable value from the main function.

hope that clarifies! :o
 
you need to get the string inside the eval looking like

dotest(1)

so its

evstrg = "dotest(" & testid & ")"

eval(evstrg)
 
unfortunately the string that is the variable name could be any variable from the main sub so I cant hard code it like that. Also, each function that is called could have different variables in different orders. I wanted something that would automatically match up the string variable name with one of the variables from the main sub that has the same name.
I considered using a case statement to match up the string with the variable name but depending on the main sub there could be a large number of variables (too many to make a case statement practical).
 
eval is pretty flexible

you just need to form a string that contains the name of the function you want to call, together with the functions arguments.

i can't realy see that anything can be too complex - its just a matter of deciding whether its the correct solution to yuor problem.

eg why cannot you do what you describe here?
I want to use eval() to run the function but it cant convert the variable names in the string into their respective values from the sub that is calling eval().
 
eg why cannot you do what you describe here?

The eval function will run the function if I swap out the variable names with the actual values they are intended to represent. e.g. eval("doTest(1)")
BUT if I put in eval("doTest(TestInstID)") it fails.

eval cannot recognise TestInstID as the name of a variable that exists in the main sub (i.e. it doesn't know to substitute TestInstID for the value 1 from the main sub). My problem lies in getting the program to match the string "TestInstID" to the the variable TestInstID. And it needs to do this automatically rather than (for example)
select case var3
case "TestInstID"
vars2 = TestInstID
Case "StatusID"
vars2 = StatusID
 
Similar to what Gemma already said, but what about

eval("doTest(" & vars2 & ")")

Or

eval(varTest & "(" & vars2 & ")")
 
sorry, I dont seem to be explaining my problem very well! :(

The problem is building the vars2 list. I essentially have a large set of functions, each with different variables:
e.g. doTest1(a,b)
doMakeTea(c,b,a)
doOpenPot(b,c)

with FuctionNames = "doTest(a,b)%doMakeTea(c,b,a)"
a = 1
b = 2
c = 3
the sub might look like:
doAction(FuncNames,a,b,c)
do while FuncNames <>""
[1. get first function]​
act1 = "doTest(a,b)"​
[2. run function]​
eval("doTest(a,b)")​
'this doesnt work!!! the eval cant recognise that a & b are the variable values 1 & 2
FuncNames = FuncNames - act1​
loop

To solve this I am trying to do the following between steps 1 & 2:
a. get the variables from the function ("a,b")
b. match each of those values in turn to variables from the main sub (i.e. "a" = the value of a, "b" = the value of b)
c. reconstruct the function string with these values in place of the variable names (doTest(1,2))

I cannot use the "doTest(" & a & "," & b & ")" method because I don't know what variables will be used in the function or in what order they will be used.

It was suggested to me that eval("a") would return the value of the variable a but that does not seem to work.

I hope this clarifies my problem somewhat!

Thanks for sticking with me :)
 
I believe I understand your request, it comes up in forums from time to time, but VBA doesn't support runtime evaluation of variables by name.

Eval is only capable of evaluating expressions.
The expression service can evaluate function calls, select objects, built in functions and UI object properties.
Variables within procedures are well beneath the perview of the service though - and hence that of Eval. (Eval doesn't exactly follow the expression service in behaviour/functionality - but essentially they support the same).
Similarly Run and CallByName (the other methods for runtime execution of named items) can't access anything as granular as variables.

Your only option is to begin creating your own set of referencable values to act as distinct variables.
The simplest example of this is an array (i.e. instead of individual variables you'd use the elements of an array to allow dynamic referencing of the value you want to retrieve).
That would most readily be achieved by switching from a variable name to an ordinal index as a reference method.
This can, of course, be extended into a multi-dimensional array whereby you also assign and store a text reference to the value you want to retrieve (effectively naming it) and retrieve the matching value as required.

You can then always go on to creating a class (or just a single simple function) to perform this insertion or retrieval for you.
So for example where you now declare and then use a variable named var2 you would assign a new element in your array or class storage (which itself might be an array, collection or even a table) named var 2.
e.g.
MyObject("var2") = "SomeValue"
and subsequently
SomeObject.Value = MyObject("var2")

Not difficult in concept I'm sure you'll agree - but a hack compared to what you were wanting.
FWIW I've not found VBA's limitation in this area to be a problem. (As long as workarounds exist).
 
Thanks LPurvis!!! That answers my question. A multi-dimensional array sounds like the answer. I will now go and learn how to use them! :)
 
OK.
Just bear in mind that the example implementation I suggested wouldn't be with an array alone.
That would have to be by index
MyArray(1) = "SomeValue"
and subsequently
SomeObject.Value = MyArray(1)

If you want more descriptive elements you'll need to wrap the call in a function (i.e. in my example MyObject would be an object which returns a custom class type.)

Any questions or examples just shout.

Cheers.
 

Users who are viewing this thread

Back
Top Bottom