Circular dependencies between modules

J

Jim Shaw

Blank At "compile time" I'm getting a "Circular dependencies between
modules" error message.
What is the problem??
Is there a work-a-round?

It came up while coding my own events with the "With Events" syntax to
realize Bi-directional inter-module communicattion / synchronization via
event messaging between four forms.

Can it be that Bi-directional event messaging between sibling objects is not
allowed in VBA??!!

I got into this because of a user initiated change request that form objects
which were initially defined as independent of each other, are now
interdependent in a way that needs some type of control over the order of
event processing if I'm to save tons of existing code. Being unable to do
that directly (aparently VBA makes up its own mind on the processing order
of user raised events), I'm trying to get the form objects to explicitly
talk to each other and stay sync'd up that way.

Hopefully this background info will help...
CONTEXT: Access/2002, MS/Windows 2000 Server

The four forms are loaded in the following order
"frmEmpMaint" This is the "Main" form
"subEmpCompDataHist" A sub form on the Main form
"frmAddNewEmp" Optionally loaded by Main form logic
"frmEmp850Criteria" Optionally loaded by Main form logic

The last two forms are not normally open at the same time and there is no
attempt to communicate between them. I'm trying to keep frmEmp850Criteria
synchronized with the first two forms. Either of these three can initiate a
a need for the other two to react. I don't think "frmAddNewEmp" is part of
the problem because I had that code working.

These Events are used to synchronize (i.e.; move to related records in their
underlying table) forms:

AddedEmp(EmpID as String) signals that a new employee has been added

NewEmp(EmpID as String, Name as String) signals that a form has moved
to a new employee in its underlying file

NewEmp(RecComp as form) signals that a form has moved to a new employee
in its underlying file

CurrentRec(RecComp as form) signals that a subform has moved to a new
history record in its underlying file

SyncTo(SyncDate as date) signals a request to move to a record having
an EffectiveDate of SyncDate.

SyncOK(SyncDate as date) signals a successful move to the requested
record

SyncFailed(SyncDate as date) signals that no record exists having an
EffectiveDate of SyncDate.

RecComp is a form object which raised the event thus providing
addressability to its underlying record.

The forms have the following specifications and code snipits that I feel are
relevant to the problem:

----------------------------------------------------------------------
"frmEmpMaint"
-------------
Underlying table: tblEmployee (PK: EmpID)
Events Raised:
NewEmp(EmpID as String, Name as String)
Form850Loaded()
Events Sunk:
frmAddEmp_AddedEmp(EmpID)

Private Sub CmdNew_Click()
DoCmd.OpenForm 'frmAdNewEmp",,,....
Set frmAddEmp = Forms!frmAddNewEmp
End Sub

"frmAddNewEmp"
--------------
Underlying table: tblEmployee (PK: EmpID)
Events Raised:
AddedEmp(EmpID)
Events Sunk:
None

"subEmpCompDataHist"
--------------------
Underlying table: tblEmpCompDataHist (PK: EmpID & EffectiveDate)
Events Raised:
NewEmp(RecComp as form)
CurrentRec(RecComp as form)
SyncFailed(SyncDate as date)
SyncOK(SyncDate as date)
Events Sunk:
frmEmp_NewEmp(EmpID as String, Name as String)
frm850_SyncTo(SyncDate as date)
frmEmp_Form850Loaded()

Private Sub Form_Load()
Set frmEmp = Forms!frmEmpMaint
End Sub

Private Sub FrmEmp_Form850Loaded()
Set frm850 = Forms!frmEmp850Criteria
End Sub

"frmEmp850Criteria"
-------------------
Underlying table: Unbound form. Uses qryDefs to access needed tables &
data
Events Raised:
SyncTo(SyncDate as date)
Events Sunk:
frmComp_NewEmp(RecComp as form)
frmEmp_NewEmp(EmpID as String, Name as String)
frmComp_SyncFailed(SyncDate as date)
frmComp_SyncOK(SyncDate as date)
frmComp_CurrentRec(RecComp as form)

Private Sub Form_Load()
Set frmEmp = Forms!frmEmpMaint
Set frmComp = Forms!subEmpCompDataHist
End Sub

----------------------------------------------------------------

Believe it or not, this all makes sense to me. :cool:

Thanks
Jim
 
M

Michel Walsh

Hi,


Events are only allowed for class, not for modules.


Why you don't use standard CALL. Instead of

RaiseEvent AddedClient


use

CALL FORM!FormClient!AddedClient( )

or similar?


There is less overhead with a standard subroutine call than there is with an
event. And since it seems you code BOTH the class that "raise the event" and
the class that respond to it, YOU ARE IN CHARGE along the whole process, and
the event model is thus an un-necessary complexities.


Sure, that does not answer to why you got a circular reference in your
"modules"... That can happen if you refer, from dbA.mdb, in the libraries,
to dbB.mdb and dbB.mdb refers... to dbA.mdb. That is a COM circular
reference of library.



Hoping it may help,
Vanderghast, Access MVP
 
J

Jim Shaw

Michel! Thanks for responding, but I'm still in trouble in several places.

-------First, I can't make your call logic
work---------------------------------------------
In Access 2002, I set up the following two trivial forms to test your call
logic and I can't make it work. I have:

"frmB" defined with a text box "txtB" and
Public Sub SetData(txtA As String)
txtB = txtA
End Sub

frmA defined with a text box " txtA"and
Private Sub txtA_AfterUpdate()
Call Form!frmB!SetData(txtA)
End Sub

With both forms loaded, I type data into txtA and exit the field.
I get a syntax error on the call statement in frmA!
I've tried other syntax approaches, but they all result in compile errors.
Can you help me here?

-------Second, I'm confused----------------------------------------
You wrote: "Events are only allowed for class, not for modules."

In a form, when I write event property VBA code, the form's property "HAS
MODULE" is set, by VBA, to "yes".
From that I assume that the code I've written is in a "module" and the form
itself is an "object" of a forms class.

I have user defined events working in these modules!!?? And they are not
allowed for modules? My problem is: They work for monologs only, not for
dialogs. (i.e., one way communication only) I get circular definition
errors on dialog type coding.
Can you clarify this for me?

If I write my own "class" (as I have in this application), I fail to see how
to code an initiator event (or object load event) sub routine, to prepare it
to sink events... I can't find those events in the class definition
features of the VBA language.
Can you tell me how to do this?

I guess my understanding and experience is the reverse or yours..."events
are for modules and not for class"...?


-------Third, You asked, so I'll share with you, my reason for using event
code--------------------------
I am basically an object oriented programmer who normally works in true
object oriented languages and I'm trying to use that metaphor to implement
my inter-module communications here in VBA. (My client is making me do that)
I'm basically self taught in VBA.

I'm willing to pay a little in performance to achieve more important
benefits.

Calls, such as you recommend, are bound to specific forms at coding/compile
time. An explicitly coded call is needed for each "listening" form.
With events, I can add "listeners" at will during application development
/execution time without having to add additional calls.

With calls, I must add logic to assure the listening form is loaded before
each call is executed, or the logic will crash. Not elegant.!
With events, I don't have to worry about "who", or "whether" anyone, is
listening to broadcast messages, thus achieving better decoupling between
forms and improving encapsulation.

In a nutshell, event based messaging leads to more robust applications that
are more easily understood and maintained over the long haul. Well, its
just my opinion and I submit to your better experience with VBA. I don't
want to start any programming style wars here (Smile)

However, I'm beginning to understand that what I'm trying to do with VBA may
be too advanced for the features of the language. So I'm trying to get your
approach to work. At least that way I can finish this application and get
on to other stuff.

Your help would be appreciated.

Thanks,
Jim
 
M

Michel Walsh

Hi,

Indeed, the exact not-ambiguous syntax should be:


Call Forms.FormB.SetData(Me.Text0.Value)



need a "s" at the end of the keyword forms. Dots are also required, and
since a control can be passed as control or as value, I don't take any
chance, I specify the dot-Value (that would be important is you "dim" the
argument as VARIANT, rather than As String, since a Variant can be anything,
the whole control, or just the Value).

The called procedure must be public, and the form loaded, but you already
have that right.




Hoping it may help,
Vanderghast, Access MVP
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top