passing variable name rather than the variable
There is a simple way to refer to the variable name rather than then variable value, but I can't remember or locate how to do it. I forget the term, somthing like convert the name to a string?
such as:
apple=20
lemon=33
banana=45
send one of these names (call it "xfername")
xfername=xfername +4
msgbox (" increased to " & xfername)
Note that what I desire is that if apple were the "sent one", it would have an updated final value of 24. If banana were sent, it would have a value of 49.
Re: passing variable name rather than the variable
Create a function like this.
Code:
Public Function AddTo(ByVal InitValue as Integer, ByVal Increment as Integer) As Integer
AddTo = InitValue + Increment
End Function
Call it like this.
Code:
Apple = 20
Apple = AddTo(Apple, 4)
Re: passing variable name rather than the variable
I really need to have a variable or some function hold the name of the variable (apple, banana, etc) so that I can do some processing on it much later in the program. There is some decision logic early on to determine which variable is being updated later on.
Re: passing variable name rather than the variable
Create a TYPE of your own, for FRUIT
Code:
Type SystemInfo
CPU As Variant
Memory As Long
DiskDrives(25) As String ' Fixed-size array. if you need one for each
VideoColors As Integer
Cost As Currency
PurchaseDate As Variant
End Type
or create an array of them, and assign values
Code:
Dim AllSystems(1) As SystemInfo
AllSystems(0).CPU = "386SX"
AllSystems(0).DiskDrives(2) = "100M SCSI"
You can pass procedure arguments using a user-defined type.
Code:
Sub FillSystem (SomeSystem As SystemInfo)
SomeSystem.CPU = lstCPU.Text
SomeSystem.Memory = txtMemory.Text
SomeSystem.Cost = txtCost.Text
SomeSystem.PurchaseDate = Now
End Sub
Re: passing variable name rather than the variable
I think I understand what vbcandies wants. In fact everything was easy if we had pointers in VB. So we could store a pointer to a variable somewhere and know later which variable that was. However, you cannot pass the name of a variable to a function or sub, or store the name of a variable in a string.
Unfortunately we haven't pointers and we can't really simulate them.
What you can do is: you can implement an array (of fruit), wher fruit(0) is apples, fruit(1) is lemons, fruit(2) is bananas. Then you can store the index of the array element or pass it to a sub to make changes. If you assign constants you keep the overview in your program.
The actual value is stored in an array, but you use the index to access it.
Code:
Const FRT_apple = 0
Const FRT_lemon = 1
Const FRT_banana = 2
Private Fruit(2) As Integer
Private LastFruit as Integer
Private Sub ChangeFruit(FruitIndex as Integer, Increment as Integer)
Fruit(FruitIndex) = Fruit(FruitIndex) + Increment
End Sub
'now you can do:
ChangeFruit(FRT_apple, 10)
LastFruit = FRT_apple
...later then
ChangeFruit(LastFruit, -10)
Another idea is, to create a simple class Fruit which contains one property 'Count'.
The variables will be objects references which can be seen like pointers.
You'd need a class module named 'Fruit'
In the simplest way it contains only one line
Code:
Public Count As Integer 'or Long if you like
In your main program you have to declare and use your objects like that:
Code:
Private apple As New Fruit
Private lemon as New Fruit
Private banana as New Fruit
Private LastFruit as Fruit
Private Sub ChangeFruit(FruitVar as Fruit, Increment as Integer)
FruitVar.Count = FruitVar.count + Increment
End Sub
ChangeFruit(apple, -10)
Set LastFruit = apple
... later then
ChangeFruit(LastFruit, 20)
Re: passing variable name rather than the variable
If the names are known at design-time, you could use a Select Case statement:
Code:
Function GetVar(Name As String) As Long
Select Case Name
Case "Apple"
GetVar = Apple
Case "Lemon"
GetVar = Lemon
Case "Banana"
GetVar = Banana
End Select
End Function
So you could use it like:
Code:
Result = GetVar("Banana") + 4
However, you can get a pointer to VB variables using VarPtr(), or StrPtr() for strings. Though this doesn't sound quite like what you're looking for.
Re: passing variable name rather than the variable
I also considered VarPtr() in the first place, but then I found no means to pass it as a reference to a function or sub.
You could store a VarPtr() in a Long but I didn't find a means to pass it to a sub, so as the sub would accept it as a reference to a variable.
You would have to declare the parameter ByRef, but pass the VarPtr() variable ByVal
Code:
Dim apple as integer
Sub ChangeFruit(ByRef FruitVar as Integer, Increment as Integer)
FruitVar = FruitVar + Increment
End Sub
Dim LastFruit as Long
LastFruit = VarPtr(apple)
ChangeFruit ByVal LastFruit, -10
Would be nice, but does not work.
Sub
Re: passing variable name rather than the variable
Wiz bang--thanks, but your suggestion is sort of the reverse of what I want===I need to later on UPDATE the variable value (being banana, apple, etc) based on previously slecting which of the variables I want to update.
I suppose DGLIENNA/WOF's idea is the only way to go..."problem" is I've already using a bunch of different variable names here & there in the code, so now I have to gather them up into a multidimensional array or TYPE!!
Re: passing variable name rather than the variable
After considering all the possibilities I like the Object solution best.
It allows closest what you want: store a pointer to a variable for later use, no matter which one it was.
Arrays seem apropriate too, but all the changes seem more complicated than to write one simple one-line-class as I described.
Change the variable declarations, and where the variables are used, you add the Value property (or Count).
Code:
Dim apple as New Fruit
apple.Value = 10
Dim FruitPointer as Fruit
Set FruitPointer = apple
Looks rather straight forward.
1 Attachment(s)
Re: passing variable name rather than the variable
Quote:
Originally Posted by
WoF
I also considered VarPtr() in the first place, but then I found no means to pass it as a reference to a function or sub.
You could store a VarPtr() in a Long but I didn't find a means to pass it to a sub, so as the sub would accept it as a reference to a variable.
You would have to declare the parameter ByRef, but pass the VarPtr() variable ByVal
Code:
Dim apple as integer
Sub ChangeFruit(ByRef FruitVar as Integer, Increment as Integer)
FruitVar = FruitVar + Increment
End Sub
Dim LastFruit as Long
LastFruit = VarPtr(apple)
ChangeFruit ByVal LastFruit, -10
Would be nice, but does not work.
Sub
Actually, CopyMemory can do the trick.
Quote:
Originally Posted by
vbcandies
Wiz bang--thanks, but your suggestion is sort of the reverse of what I want===I need to later on UPDATE the variable value (being banana, apple, etc) based on previously slecting which of the variables I want to update.
I suppose DGLIENNA/WOF's idea is the only way to go..."problem" is I've already using a bunch of different variable names here & there in the code, so now I have to gather them up into a multidimensional array or TYPE!!
Well, I'm partial to UDT arrays. Incredibly useful, and they also make it sooo easy to store and retrieve data from a file. If I understand what it is you want to do, attached is an example of three ways to do it.
Re: passing variable name rather than the variable
WizBang:
WOW---that is quite an impressive demo...thanks for the great ideas...there seems to be so many obscure and hidden functions to work with...not sure how you run across all this...I guess. you call it: Experience..
I alway get great thoughts from everyone on this forum.
Re: passing variable name rather than the variable
Yes, good one, Wizbang. CopyMemory is always a way to workaround things VB6 does not have. But it requires you to know exactly what you are doing, because any wrong memory address would crash the program badly.
Re: passing variable name rather than the variable
or the OS, or the security system on the LAN...
Re: passing variable name rather than the variable
Yeah. That's why I'd rather use the object oriented approach. It is perfectly safe.
What else are Class modules good for if we can achieve everything with CopyMemory. ;)
Re: passing variable name rather than the variable
Fortunately, VarPtr() gives CopyMemory valid values every time. What's scary is when someone hard-codes values for such things.
Class modules are great for various things too, and can do even more when used in conjunction with CopyMemory ;)
Re: passing variable name rather than the variable
Yes, as I said, you have to know what you are doing with CopyMem.
Well, come to think of it, there is another neat solution which simply uses a good old well known VB object, without a new class or fancy tricks. Look at this:
Code:
Private Fruit As New Collection
Private LastFruit As String
Private Sub Form_Load()
Fruit.Add 10, "apple"
Fruit.Add 10, "banana"
Fruit.Add 10, "orange"
End Sub
Private Sub ChangeFruit(FruitName, Increment)
Fruit(FruitName) = Fruit(FruitName) + Increment
End Sub
'and you can do
LastFruit = "apple"
ChangeFruit LastFruit, 10
Items in a collection act exactly like named variable, if you use the key as an index to retrieve the value, the key being a name which is nothing more than a string.
Re: passing variable name rather than the variable
That's an interesting approach WoF. I doubt I would have thought of it, since I don't use collections. Though for the example I posted, I did consider a function which iterates through the UDT to find the correct element to update, which would be similar in some ways.
Re: passing variable name rather than the variable
Yes, right. I thought something like that, too.
But then I thought, my, what do we have the nice Collection for? It does the searching much faster.
This has nothing to do with the OPs request, but:
I like to use collections well. They are a real versatile tool, when you consider that you can collect not only numbers or strings, but also any kind of objects or controls, which you want to retrieve by a key or index.
I often use them to group controls, which have to be operated commonly and are not somehow in the same container or have nothing in common. You just add the groups of them to collections at form-load, and in the code you can do a for each pass over all controls in one collection, enabling, disabling or making them visible or whatnot.
Re: passing variable name rather than the variable
Thanks Wof--your ideas are always top-shelf.
As an additional twist, do you think it is possible to have an incoming string select a particular variable? Probably not, from what I've seen.
for example: IncomingString= "intDollars=100" would be processed and set intdollars to 100,
"bolOpenTheDoor= True" ,would do just what you see. Of course you can go through some lengthy case statement, listing every variable you might ever want to possibly change in your program.
case strVname= "intdollars"
intdollars=intdollars+strVvalue
case strVname= "bolOpenTheDoor"
BolOpenTheDoor=... etc
etc
But is it possible to have a generic processing, so you need not list all the variable in a lengthy case statment ahead of time. Something like the CallByName function to call routines.
Re: passing variable name rather than the variable
You nearly answered your own question, by referring to the CallByName statement. At least that's the first thing which comes to mind. What you might do, is create a class with Public Properties to access your variables. Then a string could determine which property would get called, hence which variable gets set. I suppose you would also need to parse the string based on the position of the "=", to pass what's after it as a separate argument.
However, if your intent is to allow the user to type in a string, and the program uses it as the ProcName parameter of CallByName, you'd need to account for non-compliant strings, including the variable types of the values being passed.
Re: passing variable name rather than the variable
The Collection solution I mentioned earlier should work as well.
Code:
Dim Fruit As New Collection
Private Sub Command1_Click()
Dim a$
a$ = InputBox("Your command>", "apple and banana")
ChangeFruit a$
End Sub
Private Sub Form_Load()
Fruit.Add 10, "apple"
Fruit.Add 10, "banana"
End Sub
Private Sub ChangeFruit(LiteralCommand As String)
Dim arg$()
arg = Split(LiteralCommand, "=")
Fruit.Remove arg(0)
Fruit.Add Val(arg(1)), arg(0)
Debug.Print arg(0), Fruit(arg(0))
End Sub
The only question remaining is:
Why can I not do Fruit(arg(0)) = Val(arg(1)) ???
It seems it can't be done. To change the value of a collected item you have to remove it and add it with the new value, like shown.
But no matter, this seems the most generic solution possible.
You can even "declare" new collected items if you do apropriate checks or on error resume.
If an item is not yet in the collection, it will simply be created.
orange=20 will create a new fruit named orange with an amount of 20.
Some more safety checks should be elaborated, analysing the user input, like stripping blanks, putting everything to lowercase and so on.
Re: passing variable name rather than the variable
Adding a little conclusion:
Instead of using the Collection I'd go and use the Dictionary.
It is more verstile than the Collection. It has a method to find out if a key already exists, provides a list of all keys AND allows to change a stored item's value in-line, that is without deleting and recreating it.
You have to add a reference to the Windows Scripting Runtime, though, to make use of this object.
And watch out. The syntax of adding an item is reverse to the collection:
Directory.Add KeyString, Value