Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Why does this code blow away Class instantiation & set it to nothing 1

Status
Not open for further replies.

SBendBuckeye

Programmer
May 22, 2002
2,166
US
In Class_Initialize procedure I have the following code:

Dim mdl As Module
DoCmd.RunCommand acCmdNewObjectModule
Set mdl = Modules(0)
mdl.AddFromString "Public Sub Misc(), etc. End Sub"

As long as I do NOT execute the mdl.AddFromString line, everything is OK. I can find my class embedded in the ME object, etc when the code returns.

BUT, if I execute the mdl.AddFromString line it works as the new procedure shows up in the standard module, however when the code returns, the class object embedded within ME now shows up as Nothing.

How is the above code impacting the class object like this? Thoughts anyone?

Thanks in advance for any help you can give me!
Please remember to give helpful posts the stars they deserve! This makes the post more visible to others in need![thumbsup]
 
I'm confused about the phrase "class embedded within the ME object". I figure "ME" couldn't refer to the class that this fragment comes from, because it couldn't be instantiating itself. But the only other "ME" would be in an outer class that instantiates the class whose code fragment you gave. I'm envisioning something like this:

Class Module 'Inner'
Public mdl As Module

Private Sub Class_Initialize
DoCmd.RunCommand acCmdNewObjectModule
Set mdl = Modules(0)
mdl.AddFromString "Public Sub Misc(), etc. End Sub"
End Sub


Class Module 'Outer'
Dim objInner As Inner

Public Sub SomeMethod (could be Class_Initialize, too)
Dim mdlTheModule As Module

Set Me.objInner = New Inner
' Instantiation occurs, Class_Initialize is called
' *** Is problem here: Me.objInner is Nothing? ***

Set mdlTheModule = Me.objInner.mdl
' *** Or is it here: mdlTheModule is Nothing? ***
End Sub






an object (for reference, say it's of class "Outer") that is instantiating this object (class "Inner"), which instantiates a Module object. Is that the case? And are you then saying that the Outer object instantiates an Inner object variable, and when the Inner.Class_Initialize includes the AddFromString method call, Rick Sprague
 
Sorry, I didn't communicate very well. Let me try again with some sample code.

1. Created a class module named MyClass with the following:

Option Compare Database
Option Explicit

Private str1 As String
Private str2 As String
Private mdl As Module

Private Sub Class_Initialize()
str1 = "Gary"
str2 = "Leslie"
DoCmd.RunCommand acCmdNewObjectModule
Set mdl = Modules(Modules.Count - 1)
mdl.InsertText "Public Sub GLWTest" & vbCrLf & "End Sub"
End Sub

2. Created a form named frmTest with the following:

Option Compare Database
Option Explicit

Private mMyClass As MyClass

Private Sub Form_Current()

End Sub

Private Sub Form_Load()
Set mMyClass = New MyClass
End Sub

3. If you comment out the mdl.InsertText above and put the form into single step mode for form load you get this:

A. Before instantiation mMyClass shows a value of Nothing
when browsing the form's me object in debug mode

B. After instantiation mMyClass shows the values expectd
when browsing the form's me object (eg str1 = "Gary",
str2 = "Leslie", mdl.Name = "Module1", etc).

C. A new standard module is created and displayed.

4. But, if you uncommnet the mdl.InsertText above and put the from into single step mode for form load and form current you get this:

A. Same as above

B. Text is inserted into Module1 properly

C. Error message pops up saying:
Can't enter break mode at this time

D. Clicking on Continue or End will bring you back to the
form

E. If you look at the form's me object again, mMyClass
now shows a value of empty as if it was never created
or was somehow destroyed by referencing the module.

Hope this is a little bit more clear and thanks for your response.

Have a great day!

Please remember to give helpful posts the stars they deserve! This makes the post more visible to others in need![thumbsup]
 
I was able to reproduce your problem. I did some experimenting, and figured out that immediately after the InsertText executes, the project becomes reset. Not only is mMyClass set to Nothing, all global and local variables are reset. Code continues to execute until it exits the current event, but it's executing in a barren wasteland--everything is Empty or Nothing or zero or an empty string.

I think this is normal behavior, although I've never seen it specifically documented. It's probably a compromise adopted by the designers of VBA. Consider: When a module is changed, an ambiguity arises because the execution environment has changed. New procedures may exist, or old ones may have been deleted. Public variables, constants, and types may have changed. All of this can affect existing code in other modules, which (assuming it's been compiled and saved) may no longer work correctly.

If you're changing the code in the user interface, VBA knows about the compile-time dependencies and can invalidate the compiled code that's affected, so that the procedures will be recompiled the next time they're needed. But in the runtime environment, some of those procedures may actually be in execution at the time. VBA is smart enough to recompile on the fly if you're at a breakpoint, but I suspect doing so while code is actually in execution is too complicated, maybe impossible, and the VBA designers chose to just shut off the debugging interface and reset the project until the code finishes executing, after which the recompiling can take place in a stable environment.

Something like this, in fact, happens when you call the Application.Quit method. It isn't documented, but I've discovered that sometime after the Form_Unload procedures are called for all open forms, but before the forms are closed, the debugging interface is shut off and the project is reset. If you've got Application.Quit in an application, don't expect to save persistent data (such as registry settings) in Form_Close routines, because the data is already gone before you the Close events happen. You need to save your data before calling Application.Quit.

I don't think you're going to be able to get this to work, unless you move the module-building code into a library database. Since a library is a separate project, it won't be reset when you create or change a module in the CurrentDb. The Access-provided code building wizards are all in external libraries, of course, and they work fine.

Hope this helps. Rick Sprague
 
This behavior is in fact by design, and RickSpr is right about using a Library database - which is the suggested solution given by Microsoft.

See:
Microsoft Knowledge Base Article - Q198637
thread705-354090
VBSlammer
redinvader3walking.gif

Unemployed in Houston, Texas
 
Rick,

Thanks for the very enlightening post. I learned a lot by reading it.

Have a great weekend!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top