Link to home
Start Free TrialLog in
Avatar of askolits
askolits

asked on

Is there way to execute a string in VBA

I want to do something very easy.
I just want to place some code in a string and execute it.
Tried Eval, but no luck.

Example:

Dim strVal As String
strVal = "Forms!frm_000_010_REFERENCE_MAIN.txtpending.visible=true"
Eval (strVal)
Avatar of Nitin Sontakke
Nitin Sontakke
Flag of India image

This isn't quite evaluating an expression, isn't it? This is property assignment or executing a code, which on underlying level might be two different things.

For example, eval of "5 * 2", could be evaluated to but an assignment won't. Here is a quick script and it's output.

dim x, y, z
x = 5
y = 2
z = 0
MsgBox(x * y)		'10
MsgBox(Eval("x * y"))	'10
Eval("z = x * y")	
MsgBox(z)		'0
z = x * y
MsgBox(z)		'10

Open in new window


If you could tell what exactly you want to achieve, may be, we can think of the solution.
In order to make a Form 'Visible' ... you  need to do this:

Dim frm As Form
Set frm = Form_frm_000_010_REFERENCE_MAIN
frm!txtpending.Visible = True

For this case, be SURE you have the Form's 'Has Module' property set to Yes.


Or ...
DoCmd.OpenForm "frm_000_010_REFERENCE_MAIN"
Forms!frm_000_010_REFERENCE_MAIN.txtpending.visible=true

Not sure you can get that into an Eval() statement
Avatar of crystal (strive4peace) - Microsoft MVP, Access
crystal (strive4peace) - Microsoft MVP, Access

hi,

as mentioned by Nitin and Joe, Eval is simply to evaluate an expression. The result is a string or numeric value.  You cannot have an assignment to a variable there

Application.Eval Method (Access)
https://msdn.microsoft.com/en-us/vba/access-vba/articles/application-eval-method-access

What is your reason for wanting to do this with Eval? Do you have a list of controls to make visible or not?

have a day that matters,
crystal
What's your use-case?
Avatar of askolits

ASKER

Thanks for all your input. I have many ways I could use to set the value, I was just trying to optimize my code.
 
I was adding a bunch of values to an array and then iterating through the array.
Using those array values, determining if I need to display a control. All that part is easy.
What makes it tough is the control to display may be in the main form, a sub form of that main form, or a control in a sub form of that subform.

So if I could store the '.visible' action in an array value then execute it, it makes my code cleaner.

It's kind of hard to explain this in any more detail. But, l have a many options. Just trying to optimize my code.

Thanks all.

John
"Dynamic" meta code like this is not necessarily optimized code.

Using those array values, determining if I need to display a control. All that part is easy.
The correct approach is having a method which does this. E.g.

Public ApplyControlRules(AForm As Access.Form, ARules As Object)

  Dim Control As Access.Control

  For Each Control in AForm.Controls
    If [Control.Name IN ARules] Then
	  If TypeOf Control Is Access.ComboBox Then        
	    'Set specific control typ rules.
      End If

	  If TypeOf Control Is Access.CommandButton Then        
	    'Set specific control typ rules.
      End If

	  If TypeOf Control Is Access.TextBox Then        
	    'Set specific control typ rules.
      End If
	  
	  'Set general control type rules.
    End If
  Next Control
  
End Sub

Open in new window


where AValues is your array. The concrete implementation depends on your kind of array. Where I need to say, using a record set and storing these rules in a table makes more sense.
@ste5an Yes, but I need to do subforms as as well, and subforms within the subforms.  You would need to then call this function within itself to iterate through the main form, it's subforms and any of those subforms.  

Not sure why I would want to iterate through all the control when I already know which one I want to change. I have done this type of iteration before and found that forms with many controls take time to do and slows down the code.

I already have a solution, so I'm good. Thanks.
Well, when it works for you..

Not sure why I would want to iterate through all the control when I already know which one I want to change
The problem is that I don't know, why you know that. The reason here is important for the correct approach. Coding is sometimes less obvious than expected.

Caveat: Is just it's not an easy task and you may get "working" code. But working code is not necessarily good code. It maybe even incorrect.
@Ste5an "The problem is that I don't know, why you know that."  
Because, I've done it. I had a form with about 100+ controls and tried iterating through them changing some properties.
You may question why I had that many controls, and it was a long time ago.

Just so you know, I've been developing Access apps since 1.0. So, certainly not a novice.
Not that I couldn't always learn more about optimizing code. Feel free to check out my product which is 100% Access, including the touch screen. It'll give you some idea of what I'm working on.

Check-4-It
SOLUTION
Avatar of Gustav Brock
Gustav Brock
Flag of Denmark image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Gustav Oh.. that's real close. Cool idea. But I need the object to be a variable.

Something like:
Dim varObject
varObject = "Forms!frm_000_010_REFERENCE_MAIN!txtpending"
CallByName varObject , "Visible", VbLet, True
Or try the following:
public setControlProperty(ByRef frm As Access.form, ByVal ctrlName as String, ByVal propertyName As String, ByVal value As Variant)
    If(ExistInCollection(frm.Controls, ctrlName)) Then
        Dim ctrl As Access.Control
        Set ctrl = frm.Controls(ctrlName)
        If(ExistInCollection(ctrl.Properties, propertyName)) Then
            ctrl.Properties(propertyName) = value
        End If
        Set ctrl = Nothing
    End If
End Sub

Open in new window

Along with these 3 helpers functions:
Public Function existInCollection(ByVal key As String, ByRef col As Collection) As Boolean
    existInCollection = existInCollectionByVal(key, col) Or existInCollectionByRef(key, col)
End Function

Private Function existInCollectionByVal(ByVal key As String, ByRef col As Collection) As Boolean
On Error GoTo Error
    Dim item As Variant
    item = col(key)
    existInCollectionByVal = True
Exit Function
Error:
    existInCollectionByVal = False
End Function

Private Function existInCollectionByRef(ByVal key As String, ByRef col As Collection) As Boolean
On Error GoTo Error
    Dim item As Variant
    Set item = col(key)
    existInCollectionByRef = True
Exit Function
Error:
    existInCollectionByRef = False
End Function

Open in new window

Or like this:

    Dim Form            As Form
    
    Dim FormName        As String
    Dim ControlName     As String
    Dim PropertyName    As String
    Dim Value           As Variant
    
    FormName = "frm_000_010_REFERENCE_MAIN"
    ControlName = "txtpending"
    PropertyName = "Visible"
    Value = False
    
    Set Form = Forms(FormName)

    CallByName Form(ControlName), PropertyName, VbLet, Value

Open in new window

@Gustav  -  I though that did it, but I couldn't use the Set Form to point to the lower subforms.

This works
               Dim Form as form
               Dim FormName As String

                FormName = "frm_000_010_REFERENCE_MAIN.sbf03.form"
                Set Form = Forms!frm_000_010_REFERENCE_MAIN.sbf03.Form
               
But this does not, with the subform reference.
               Set Form = Forms(FormName )
That would be something like this, using yet a string variable:

Form(SubformControlName).Form(ControlName)

Open in new window

I'll look at this later tonight. But I still need to go down one more subform level.
But not always. Sometimes main form, sometimes one level, sometimes 2.
So, now we are getting the the solution I'm currently doing, which is essential different CallByName types, for each level.
I was really looking for a catch-all for all the different subform combinations. But it looks like I'll have to build a different one for each level.

Forms!frm_000_010_REFERENCE_MAIN
Forms!frm_000_010_REFERENCE_MAIN.sbf03.Form
Forms!frm_000_010_REFERENCE_MAIN.sbf03.Form.sbf1.form
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Gustav  Well, that's pretty much what I ended up doing.  As always, you've been a great help!

Thanks!!
(And to everyone else that contributed, as well)
You are welcome!
Thanks to all who responded