By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,762 Members | 1,838 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,762 IT Pros & Developers. It's quick & easy.

Eval Function - Recursive call?? Routine Being Called Multiple Times

P: 4
Hi there

I'm hoping someone can help me out with the use of the Eval function. I am using Access2003 under WinXP Pro. I can successfully use the Eval function and get it to call any function with or without parms. I know that any function that is passed to Eval() must be declared Public. It can be a Sub or Function, as long as it's Public. I even have it where the "function" evaluated by Eval can be in a form (class) module or in a standard code module (and if in a form module, as long as the call is fully qualified, I can call it). That's all good.That's not the problem. The problem is with the # of times my routine that houses my Eval function call is run by Access.

I have done some research on this, but it appears that those out there having the same problem have never really gotten a good answer to/reason for this problem (just some work arounds I imagine)

Research Links:
Here problem did get a resolution, but Dirk's post shows that he was having problems with the function being called twice too:

http://awomantoldme.com/women/how-to/31178849/why-does-this-code-not-wo.aspx

Same posting: http://www.microsoft.com/communities...325a8633e8&p=1

And there was another older posting I've seemed to have lost the link to where the poster was having the same recursive call problem, but there were no responses ever posted ;-(

SCENARIO
=========


I have a Main Form (frmMain) containing 2 subforms (fsubChild1 and fsubChild2).

The SourceObject value for fsubChild2 is constantly being changed to show whatever form I am working on at the time (think of frmMain as simply a container form for my 2 subforms and really does nothing more and has no other controls on it, other than an Exit Application button)

fsubChild1 contains labels, that, when clicked on, excutes a standard function that must exist in the code-behind-form for any valid form that can be plugged in as the SourceObject for fsubChild2. Let's call this standard function mtdRunTheCode. It exists as a PUBLIC function in every form that could potentially be the SourceObject for fsubChild2 and is passed the name of a function to execute, depending on the label clicked in fsubChild1 (each label in fsubChild1 passes mtdRunTheCode a different function. Think of mtdRunTheCode() as a wrapper function. It always contains the Eval(strFunction) code line, but may also contain code or calls to other routines specific to the form in which it is executing. I wanted to do this so that fsubChild1 could call generic functions (located in a standard code module) that must be run when a label is clicked (no matter what form is contained in fsubChild2), but, depending on the form in fsubChild2, can run code specific to fsubChild2 first (such as validating the current record, saving, etc etc)

Let's imagine that I had 2 forms: frmCust and frmProd.

Both of these forms at any given time, could be the SourceObject for fsubChild2
Both of these forms contain their own version of mtdRunTheCode - declared Public, named the same and located in the subform's form module (ie the function becomes a "method" of the form)..

This is how the function looks in frmCust

Expand|Select|Wrap|Line Numbers
  1. Public Function mtdRunTheCode(strFunction)
  2.    'This function is called by the OnClick event of a given label in fsubChild1
  3.    'The value of strFunction changes, depending on the label that was clicked
  4.    'and contains the name of a unique, public function to execute. All of these
  5.   ' public functions are contained in a single Code Module.
  6.  
  7.    'Code that is specific to this form
  8.    Application.RunCommand acCmdSaveRecord
  9.  
  10.    'Execute the general function passed in by clicking a label in fsubChild1
  11.    Eval(strFunction)
  12.  
  13. End Function
  14.  
And this is how that same function it looks in frmProd
Expand|Select|Wrap|Line Numbers
  1. Public Function mtdRunTheCode(strFunction)
  2.    'This function is called by the OnClick event of a given label in fsubChild1
  3.    'The value of strFunction changes, depending on the label that was clicked
  4.    'and contains the name of a unique, public function to execute. All of these
  5.   ' public functions are contained in a single Code Module.
  6.  
  7.    'Code that is specific to this form
  8.    DoCmd.OpenReport "rptSomeName"
  9.    etc
  10.  
  11.    'Execute the function passed in by clicking a label in fsubChild1
  12.    Eval(strFunction)
  13.  
  14. End Function
  15.  
The Calling Code in fsubChild1

Expand|Select|Wrap|Line Numbers
  1. Private Sub lblTask1_Click()
  2.  
  3.   Call Forms!frmMain!fsubChild2.mtdRunTheCode("udfGeneralFunc()")
  4.  
  5. End Sub
  6.  
  7. Private Sub lblTask2_Click()
  8.  
  9.   Call Forms!frmMain!fsubChild2.mtdRunTheCode("udfAnotherFunc()")
  10.  
  11. End Sub
  12.  
  13.  
And finally, the generic function located in it's own standard code module
Expand|Select|Wrap|Line Numbers
  1. Public Function udfGeneralFunc() As Boolean
  2.  
  3.   MsgBox "This is nifty stuff"
  4.  
  5. End Function
  6.  
By doing the above, I can utilize the same general functions for an OnClick of a lable, no matter what subform is in fsubChild2, yet execute form specific code first, if needed.

THE PROBLEM
============
I don't get errors if I try to run Eval routine in any of the the mtdRunTheCode() routines. What happens is that the mtdRunTheCode routine runs TWICE. I tracked it and when I click the label in fsubChild1, the following events occur:

- Calls mtdRunTheCode
- Executes the Eval function (which in turns calls the passed in function located in a code module)
- Recursively calls mtdRunTheCode again
- Re-executes the Eval function again.

So for example, if the strFunction arg passed to mtdRunTheCode was a call to the public function udfOpenTheForm('frmTest'), and udfOpenTheForm simply ran the openform command to open the frmTest form (in Normal Window mode), this is what happens

- Calls mtdRunTheCode
- Executes the Eval function (calls udfOpenTheForm which opens the frmTest form)
- Recursively calls mtdRunTheCodeagain
- Re-executes the Eval function again (recalls udfOpenTheForm)

If udfOpenTheForm opens the form in dialog mode, since that halts execution until the form is closed, it causes different problems, making the user click twice to close that form ->

- Calls mtdRunTheCode
- Executes the Eval function (calls udfOpenTheForm which opens the frmTest form in acDialog mode). Waits until user closes form.
- Recursively calls mtdRunTheCode again
- Re-executes the Eval function again (recalls udfOpenTheForm)
- waits until user closes the form, then finally leaves the mtdRunTheCode routine


I don't really want to put the mtdRunTheCode() in a standard code module, because I really want to be able to execute form specific things before executing the code resulting from a label's onclick event (and I may not want to do that for a different form)

Does anyone know the reason for the recursive call?? I've been struggling with this for a bit now and it's driving me nuts.

Thanks!
RandomElle
Dec 29 '07 #1
Share this Question
Share on Google+
6 Replies


ADezii
Expert 5K+
P: 8,636
Hello RandomElle. In my humble opinion, you will be struggling for a long, long time to come if you continue with your current approach:
  1. The 'Public' to which you refer as a requirement for evaluating Functions with Eval(), refers to Standard Code Modules, not Form Modules. A Public Function, or for that matter Sub-Routine, in a Form's Class Module becomes a Method of the Form and is technically no longer a Function or Sub-Routine. You make this point yourself in your calls.
    Expand|Select|Wrap|Line Numbers
    1. Call Forms!frmMain!fsubChild2.mtdRunTheCode("udfAnotherFunc()")
    You are not calling a Function, but executing the mtdRunTheCode Method of fSubChild2. Since when does a Function/Sub-Routine Call have a Dot (.) qualifier?
  2. Having Functions/Sub-Routines with the same Names, even when differentiated by Scope, is seldom a good idea.
  3. In the short amount of time that I had to look over your problem, I feel as though either 1 or both of the above listed points are contributing to your duplication problem, and I truly believe that if you continue with the current logic, there will be more problems down the road. Good Luck!
  4. It would also be a good idea to wait and see what some of the other Experts/Moderators/Members have to say on the Subject.
Dec 30 '07 #2

FishVal
Expert 2.5K+
P: 2,653
Hi, there.

Couldn't reproduce the error. In the attached example form's method runs once as expected.

Regards,
Fish

P.S.
Having Functions/Sub-Routines with the same Names, even when differentiated by Scope, is seldom a good idea
Are you superstitious? ;)
Attached Files
File Type: zip DupCall.zip (14.5 KB, 116 views)
Dec 30 '07 #3

ADezii
Expert 5K+
P: 8,636
Hi, there.

Couldn't reproduce the error. In the attached example form's method runs once as expected.

Regards,
Fish

P.S.

Are you superstitious? ;)
Hello Fish, sorry, but I seem to be very slow today.
Are you superstitious?
What does the reference mean?

P.S. - Have a Happy New Year!
Dec 30 '07 #4

FishVal
Expert 2.5K+
P: 2,653
Hello Fish, sorry, but I seem to be very slow today.

What does the reference mean?

P.S. - Have a Happy New Year!
Hello, ADezii.

That was just a joke relating to:
  1. .....
  2. Having Functions/Sub-Routines with the same Names, even when differentiated by Scope, is seldom a good idea.
  3. .....
  4. .....
It seems to me a bit overkill to provide unique names for methods of different classes. I'm almost sure there is nothing unsafe in it. For example, many classes have property "Name".

I think the source of the fault is somewhere beyond the details provided by OP.

Best regards and have a Happy New Year!

Fish
Dec 30 '07 #5

ADezii
Expert 5K+
P: 8,636
Hello, ADezii.

That was just a joke relating to:

It seems to me a bit overkill to provide unique names for methods of different classes. I'm almost sure there is nothing unsafe in it. For example, many classes have property "Name".

I think the source of the fault is somewhere beyond the details provided by OP.

Best regards and have a Happy New Year!

Fish
Gottcha! See ya next year! (LOL).
Dec 30 '07 #6

P: n/a
I was having a similar issue in Excel 2007 when trying to dynamically call a procedure. My code basically looked like:

Application.Run Range("A1").Value

where cell A1.value = "someproc()"

I found that when the parenthesis were included the procedure would end up being called twice. After changing the value of A1 to "someproc" the procedure was only called once.
Sep 30 '10 #7

Post your reply

Sign in to post your reply or Sign up for a free account.