Convert a Variable to a Literal

Cotswold

Active member
Local time
Today, 19:21
Joined
Dec 31, 2020
Messages
698
I Want to transfer the field contents to memory variables and to do that I presume I'll need to convert a Variable to a Literal.
In the olden days with Clipper87 I'd just prefix with an ampersand to do that but I've never noticed anything like it in other languages I've used. I've shown a section of code where the save will take place and am wondering of there is a way to save the value of mTemp1 to memory variables named as each Fieldname but prefixed with "m"

Code:
a simple form with just three fields Test0, Test2 and Test3

.....
.....
'setting Memory Variables
Dim mTest0, mTest2, mTest3 as String
Dim mTemp, mTemp1 as String
.....
....
'Now to step through the From Fields and store their content to mmory
For Each Ctrl in Screen.Active.Form.Controls
    If Ctrl.ControlType = acTextBox then
        mTemp = Ctrl.Name    ' Fieldname
        mTemp1 = Ctrl        ' Field content

at this point I know the Fieldname and its content. The next thing is to store
that value into the correct memory variable, in this case mTest0, or mTest2 or mTest3
depending upon the position in the For Each Ctrl/ Next loop.  Which is where I guess I
need to convert a Variable to a Literal.
(the position of fields in Controls may change as new ones are added, so only the
Fieldname will be constant)
....
....
Next Ctrl
.....
more code
 
Last edited:
Cannot build a variable name from string. Cannot go: "m" & Ctrl.Name = Ctrl

Can populate an array or collection or dictionary.
 
Cannot build a variable name from string. Cannot go: "m" & Ctrl.Name = Ctrl

Can populate an array or collection or dictionary.
Thanks for that June7, I came across that with If Ctrl.Name = "Test0" then ; which of course falls over and I couldn't find a way around.

Not sure a collection or Dictionary would do as fields may move up and down and there are other issues. I do have a couple of ways around it but it was my intention to automate the save and restore options, as I have with the other routines. Also wanted to try and squeeze this into 6 or so lines of code. I simplified the example but the actual application has many forms often with easily more than a dozen fields on most forms, and one with 27. I'd want to control them all from one Function.
 
Last edited:
Just an FYI,

This does not do what you think.
Dim mTest0, mTest2, mTest3 as String
Dim mTemp, mTemp1 as String


Only mTemp1 and mTest3 will be strings. The others -variants.
 
Control them to do what? Why do you want to populate variables? How will you use them?
 
If these variables were public/friend fields or properties in a class, it would be addressable with CallByName.
However, I like the suggestion with the dictionary better.
 
The problem with somehow instantiating a dynamic variable is that the language gets in the way.

When dealing with DIM statements (or PUBLIC or PRIVATE or other related declarations) is that the syntax of the DIM statement doesn't allow anything quoted. Variables need to be statically defined.

Where you CAN use concatenation would be if you could find a collection of named objects that have some similarities in the name, you could have an item selector like collection-object( "A" & Format( n, "000" ) ) - where if n = 123, you get object item A123. So far as I know, there is not a formal collection of variables, so you cannot pull variable A123 out of the hat here.
 
Control them to do what? Why do you want to populate variables? How will you use them?
If I understand the OP correctly, It's a very popular and easy way in PHP and other languages to make a variable from another one.
Specially when you read data from a table and want to show it in a page.
A variable is shown with $. If you add another $ before the variable, you create a new variable out of the contents of first one.

PHP:
$a = ‘b’;
$$a = ‘Hello World’;
echo $b; // Output: Hello World

You may think of using variable variables to dynamically generate variables from an array, by doing something similar to: -

PHP:
<?php
foreach ($array as $key => $value)
{
  $$key= $value;
}
?>

Me, with a PHP background, had a hard time to work in VBA without this feature.
 
Last edited:
On the other hand, @KitaYama - my background was in earlier procedural languages such as ALGOL, FORTRAN, PASCAL, PL/1, and other things of that type. Plus early versions of basic. FORTRAN was like BASIC without the OPTION EXPLICIT declaration, but had implicit typing. The others were more strongly typed with regard to declaration. Therefore, I had no trouble with VBA and OPTION EXPLICIT.

In fact, I rather like the strong type declaration requirement. With something like PASCAL or PL/1, if you got everything to compile correctly, you were over 50% certain that your code could run. (Of course, if you did something dumb, that was on you!)
 
In a Control sequence we have an efficient method of extracting or writing data with little code.
But as I have indicated there isn't any way of using the name of any individual field to save its value to a specific memory variable or other named form field that can be made generic. Which is illogical and a nonsense, as it defeats the object of the Control in some operations. If we could create Literals from Variables and visa versa that would solve it.

It does appear that the sequence in Controls is the order in which fields are added to a form, which cannot be amended. From my brief tests, changing the Tab order, or adding a new field, even at different at different positions does not appear to affect the processing order in the For Each Control/Next routine. It is of course possible to exclude fields using Tags but that is by the by.
I have solved the If Ctrl.Name = "Text0" then issue as noted in #3 but it still means that up to now my loop routine for this part of the process is strictly form specific. I'll go with that for now which is still an improvement in automating.

I now think that I can create a completely generic Function() that could operate over all forms in an application. I have one now working covering some of the requirements but needs more work and testing before I'm happy with it. So that is a work in progress at this stage but I will get it to work. (and without a dictionary)
Many thanks to everyone for your responses.
 
OK, by way of further explanation, because I understand your problem/intent a little better...

In a language that is PURELY interpretive, such as scripting languages, everything is dynamic including variable creation. In scripting languages, a DIM statement (or its equivalent) would be treated as executable. Scripting variables exist in a symbol table that can be amended at will during the code's run-time. When you use a variable in that context, your code "looks up" the variable name to find a value. If you use a variable it can't find, it will create the variable in the symbol table and assign a default value initially.

A compiled language, something that involves a compilation and re-linking of contributing components, cannot do that so well. VBA is using a model where things have to be pre-defined as to where they go because that is the nature of run-time re-linking - such as what Access does if you tweak code and then try to test the app. It HAS to recompile and relink whatever you tweaked. Your whole problem comes down to the mechanism of address resolution of a variable, which in compiler paradigms is NOT done at run-time.

Therefore, @Cotswold - VBA doesn't have arbitrary variable creation at run-time. You have found that you can scan controls because they are all OBJECTS that, while they last, can be dynamically referenced through the class-resident objects. Of course, as soon as the variable referencing the controls vanishes, so do the controls. And that works because you CAN look up a control by its name via the Controls collections for each form and report. You CAN look up a dictionary value by its name. You can't do that for a variable because they are not stored in a symbol table. They are stored statically because of the multi-step nature of compilation.

Can it be done differently? Oh, sure. But does VBA do it? Nope!
 
Which is illogical and a nonsense, as it defeats the object of the Control in some operations. If we could create Literals from Variables and visa versa that would solve it.
I'm having trouble envisioning why, in an Access application, you would be creating variables on the fly. Are you trying to write utility code to build objects? Because in a standard business application, the universe of variables is known at compile time whether you use option Explicit or not.
 
I'm having trouble envisioning why, in an Access application, you would be creating variables on the fly. Are you trying to write utility code to build objects? Because in a standard business application, the universe of variables is known at compile time whether you use option Explicit or not.
I did, I thought, in #1 create a simple explanation and analysis of what I needed to do. One thing I don't want to do is to create a var on the fly.
I want to save any specific value I need obtained using the For Each Cntrl / Next into a specific and existing, already declared variable.

As I explained in #11, I've got it to work just fine now. But thank you anyway for your interest.
 
You didn't describe a business need where you needed to capture all controls from all forms in tab order ("visual" order is subjective when the control sizes are not the same. Access will "see" the tall object first) You just said you wanted to do it. OK. I'm sure there is a point but as long as you are happy with your solution, I am too.
 
No worries Pat. I'll not be doing any more posts anyway.
 
I have solved the issue of Variables to Literals for what I needed to do. I now have a totally generic Function to set any Form for Editing.
It will set Buttons Enabled on/off, also Locking/Unlocking fields and changing the Field Backcolors depending whether in editing or readonly mode. It is totally generic and will do all of that on any form that it is pointed at. Operating regardless of the number of Buttons, it will also handle any number of Fields and any FieldType/Object on any Form automatically. All in a few lines of code.

Clearly it will provide a huge time saving benefit when developing any application and provides easily maintained standardisation over applications and their forms. Completing the collection of my other developer functions that is now effectively an automatic program code generator and includes a Form-Resizer for any Access program from any developed size.

All, or any part of this set operates on any new or existing application with equal ease and little effort. I should have done this years ago but too busy working then! Initially I was minded, to share these under an MIT License.

However, it is clear to me now that sharing it will only attract unnecessary criticism of the whole Function, or a part of it. So that is not going to happen.
 
Last edited:
[OT]
Initially I was minded, to share these under an MIT License.

However, it is clear to me now that sharing it will only attract unnecessary criticism of the whole Function, or a part of it. So that is not going to happen.
This is exactly the advantage of open source: if you like the code as it is, you can use it 1:1, if you don't like some parts of the code, you can create a fork and redesign the code.
If then several developers live the idea behind open source and continue to improve the variant that suits them, an ever better product will emerge, because pretty much any available code will have potential for improvement ;)
 

Users who are viewing this thread

Back
Top Bottom