[AccessD] Same form, different actions

Charlotte Foust cfoust at infostatsystems.com
Mon Jan 30 10:41:07 CST 2006


I usually pass in the name of the calling form in OpenArgs (along with
anything else, semicolon delimited) and set a property of the called
form to point to the previous form.  You can go futher and use a stack
to keep track of the parent and child objects, but it depends on what
you really need to accomplish.

Charlotte foust


-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of John Clark
Sent: Monday, January 30, 2006 8:11 AM
To: accessd at databaseadvisors.com
Subject: Re: [AccessD] Same form, different actions


OK John, as usual, you are making my brain hurt ;) Seriously, I have
downloaded your demo, and I am looking through your code, in the
clsOpenArgs module. I think I actually understand some of it too. 

I guess the first thing that comes to mind is, does it work with
non-properties of forms? One of the things I want to do is tell the form
where to go on close...actually, when the exit button is clicked. If the
user goes there from the menu, it should return to the menu. However, if
the user goes there, from anther form, it should return to that form,
and pass the name with it.

I am going to try something, with your demo, to test this. Nope...just
did this real quick, and it didn't work. Actually the whole thing pretty
much quit working...what the heck did I do ;)

>>> jwcolby at colbyconsulting.com 1/29/2006 11:20:21 PM >>>
>>The open Args are quite useful, but tacked on the end of a Do.cmd
statement they don't do much Just text or numbers (usually) tacked on
the end of an OpenForm Do.Cmd statement.  The real 'power' is in the
interpretation at the other end

Darren,

First let me say that I have put up a demo on my site which shows how to
use the two classes in the following discussion.  Go to my website -
www.colbyconsulting.com.  If you haven't already, Register.  Log in. 
Click
Example Code / Utilities.  Select C2DbOpenArgs to download the demo.


I pass openargs in the form Varname1=VarVal1;VarName2=VarVal2;etc=etc1;
This
is a syntax that has been around since early Access days and was used
extensively by, and perhaps even "invented by" Ken Getz.  The = is used
as the separator, the semicolon as the delimiter.

I wrote a pair of classes which handle my openargs.  A "control class"
which I name OpenArgs (plural) grabs the openargs string and parses the
varname and value for each openarg.  It then instantiates a OpenArg
(singular) class to store this VarName and VarVal in.  VarName is a
string type, VarVal is a variant type.  Making it Variant causes an
automatic coercion in a lot of cases - currency values get turned into
Currency variants, dates get turned into dates etc.  At any rate, each
OpenArg instance is stored in a collection in the OpenArgs (plural)
class.

The OpenArgs class is dimensioned in the form header, and instantiated
in the OnOpen of the form.  By the time it finishes loading, all of the
OpenArgs are parsed and sitting in OpenArg class instances in the
collection in OpenArgs.  OpenArgs has a method for reading OpenArg
instances from the collection.  OpenArg instances are stored in the
collection keyed on the VarName.  

Thus you have a pair of classes which automatically handles getting
openargs for you, one or a hundred, it doesn't matter, and it doesn't
have to be "re-invented" every time you want to get your openargs.
Syntax is now standardized everywhere in your app.

The form of course must know what openargs it is expecting, so it can
now simply call OpenArgs.Arg("VarName") and get back VarVal (a variant).

What
the form does with the OpenArg is up to you, but getting the OpenArgs
available to the form is trivial.

All of the code follows.  My clsOpenArgs (plural, the controller) also
has the ability to automatically interpret openargs as properties of the
form. In other words, if a param is passed in to clsOpenArgs that says
to do so, then if an OpenArg VarName is the same as a property of the
form, the form property is set to VarVal.  I have actually demoed this
in the state form, where the form that opens frmState passes in the
values for properties


strOpenArgs = "DataEntry=True;AllowEdits=True;AllowDeletions=False;"

The state form opens, the OpenArgs class parses the OpenArgs string
passed in, discovers that I want it to use the openargs to set form
properties, and does so.

Any OpenArgs which do not match the name of a form property are left
uninterpreted and the form can use them for whatever purpose you choose.
You can also not tell clsOpenArgs to interpret the openargs as form
properties, in which case all OpenArgs are left uninterpreted and you
can do with them all as you will.

The code:

'===========================================================
'Class OpenArg
'===========================================================
Option Compare Database
Option Explicit

'
'This class stores one OpenArg
'
Private mstrArgName As String
Private mvarArgVal As Variant
Private mblnIsProperty As Boolean

Function mInit(lstrArgName As String, lvarArgVal As Variant)
    mstrArgName = lstrArgName
    mvarArgVal = lvarArgVal
End Function
Function pName() As String
    pName = mstrArgName
End Function
Function pVal() As Variant
    pVal = mvarArgVal
End Function
Property Let pIsPrp(lmblnIsProperty As Boolean)
    mblnIsProperty = lmblnIsProperty
End Property
Property Get pIsPrp() As Boolean
    pIsPrp = mblnIsProperty
End Property


'===========================================================
'Class OpenArgs (Plural) - the controller class
'===========================================================
Option Compare Database
Option Explicit
'.
'.Written By   : John W. Colby
'.Date Created : 04/10/2004
' Rev. History :
'
' BEHAVIORS:
'
'
'When a form opens, it can accept open args, a text string argument.
'The framework will check for openargs, and if they exist will check
'inside the Openagrs for arguments named the same thing as form
properties. 'If such arguments are found, the framework will set the
form's property 'equal to the argument value. ' 'I use this specifically
to set up normal forms to be DataEntry forms '(only allow new records to
be added, not existing records edited) ' 'I decided to encapsulate this
functionality in a class to make the OpenArgs 'processing cleanly
defined. '
'-----------------------------------------------------------------------
---
'THESE CONSTANTS AND VARIABLES ARE USED INTERNALLY TO THE CLASS '*+
Class constant declaration Private Const mcstrModuleName As String =
"clsOpenArgs"
'*- Class constants declaration
'*+ Class variables declarations
'*- Class variables declarations
'.----------------------------------------------------------------------
---
'THESE CONSTANTS AND VARIABLES ARE USED BY THE CLASS TO IMPLEMENT CLASS
FUNCTIONALITY '*+ custom constants declaration '
'*- Custom constants declaration
'*+ custom variables declarations
'
Private mfrm As Form     'A form reference passed in
Private mstrOpenArgs As String
Private mcolOpenArg As Collection
'*- custom variables declarations
'
'Define any events this class will raise here
'*+ custom events Declarations
'Public Event MyEvent(Status As Integer)
'*- custom events declarations
'.----------------------------------------------------------------------
---
'THESE FUNCTIONS / SUBS ARE USED INTERNALLY TO THE CLASS
'*+ Private Init/Terminate Interface
Private Sub Class_Initialize()
On Error GoTo Err_Class_Initialize
    Set mcolOpenArg = New Collection
Exit_Class_Initialize:
Exit Sub
Err_Class_Initialize:
        MsgBox Err.Description, , "Error in Sub
clsTemplate.Class_Initialize"
        Resume Exit_Class_Initialize
    Resume 0    '.FOR TROUBLESHOOTING
End Sub
Private Sub Class_Terminate()
On Error Resume Next
    mTerm
End Sub
'INITIALIZE THE CLASS
Public Sub mInit(lfrm As Form, _
                Optional blnApplyProperties As Boolean = False)
    Set mfrm = lfrm
    'The openargs string might be null
    On Error Resume Next
    mstrOpenArgs = mfrm.OpenArgs
    
    ParseOpenArgs
    '
    'The default is false, do not try and apply OpenArgs as form
properties
    'If the deveopler wants to
    '
    If blnApplyProperties Then
        ApplyFrmProperties
    End If
End Sub
'CLEAN UP ALL OF THE CLASS POINTERS
Public Sub mTerm()
Static blnRan As Boolean    'The term may run more than once so
    If blnRan Then Exit Sub 'just exit if it already ran
    blnRan = True
    On Error Resume Next
    mColEmpty mcolOpenArg
    Set mcolOpenArg = Nothing
End Sub
'*- Public Init/Terminate interface
'.----------------------------------------------------------------------
---
'THESE FUNCTIONS SINK EVENTS DECLARED WITHEVENTS IN THIS CLASS '*+ Form
WithEvent interface
'*- Form WithEvent interface
'THESE FUNCTIONS / SUBS ARE USED TO IMPLEMENT CLASS FUNCTIONALITY
'*+PRIVATE Class function / sub declaration Private Function
cOpenArg(strOpenArg As String) As clsOpenArg Dim intPosEqual As Integer
Dim strArgName As String Dim varArgVal As Variant Dim lclsOpenArg As
clsOpenArg
    intPosEqual = InStr(strOpenArg, "=")
    If intPosEqual > 0 Then
        strArgName = Left$(strOpenArg, intPosEqual - 1)
        varArgVal = Right$(strOpenArg, Len(strOpenArg) - intPosEqual)
        Set lclsOpenArg = New clsOpenArg
        lclsOpenArg.mInit strArgName, varArgVal
        Set cOpenArg = lclsOpenArg
    End If
End Function
'
Private Sub ParseOpenArgs()
Dim lstrOpenArgs As String
Dim strOpenArg As String
Dim intPos As Integer
Dim lclsOpenArg As clsOpenArg
    lstrOpenArgs = mstrOpenArgs
    intPos = InStr(lstrOpenArgs, ";")
    
    While intPos > 0
        strOpenArg = Left$(lstrOpenArgs, intPos - 1)
        Set lclsOpenArg = OpenArg(strOpenArg)
        mcolOpenArg.Add lclsOpenArg, lclsOpenArg.pName
        lstrOpenArgs = Right$(lstrOpenArgs, Len(lstrOpenArgs) -
intPos)
        intPos = InStr(lstrOpenArgs, ";")
    Wend

End Sub
'
'This function cycles through all the openargs applying them to form
properties 'if an argument is named the same as a form property, and the
property is writeable '(doesn't require being in design view to set it)
then the application of the value 'to the property will be performed and
Err will not be set.  For these OpenArgs we 'set the IsPrp to true '
'All of this provides a way for the developer to ppass in openargs to an
opening form 'which are then used to set form properties.  It is up to
the developer to ensure that 'the property is settable, that the value
they pass in is valid (correct data type, 'correct value range etc.) '
'In the end, the only way to know whether a passed in OpenArg is a
property is to try 'it and see.  If there is no error then the name is a
property name, it is settable in 'form view mode, and the value is
acceptable. ' Public Sub ApplyFrmProperties() Dim lclsOpenArg As
clsOpenArg
    On Error Resume Next
    For Each lclsOpenArg In mcolOpenArg
        mfrm.Properties(lclsOpenArg.pName) = lclsOpenArg.pVal
        lclsOpenArg.pIsPrp = (Err.Number = 0)
        Err.Clear
    Next lclsOpenArg
End Sub
'
'Empties out a collection containing class instances
'
Public Function mColEmpty(col As Collection)
On Error GoTo Err_mColEmpty

Dim obj As Object
On Error Resume Next
    
    For Each obj In col
        obj.mTerm
    Next obj

On Error GoTo Err_mColEmpty
    While col.Count > 0
        col.Remove 1
    Wend
exit_mColEmpty:
Exit Function
Err_mColEmpty:
    Select Case Err
    Case 91 'Collection empty
        Resume exit_mColEmpty
    Case Else
        MsgBox Err.Description, , "Error in Function
clsSysVars.mColEmpty"
        Resume exit_mColEmpty
    End Select
    Resume 0    '.FOR TROUBLESHOOTING
End Function

'*-PRIVATE Class function / sub declaration
'*+PUBLIC Class function / sub declaration
Function OpenArg(strArgName As String) As Variant
On Error GoTo Err_OpenArg
    OpenArg = mcolOpenArg(strArgName).pVal
Exit_OpenArg:
Exit Function
Err_OpenArg:
    Select Case Err
    Case 91
        MsgBox "OpenArg " & strArgName & " does not exist"
        Resume Exit_OpenArg
    Case Else
        MsgBox Err.Description, , "Error in Function
clsOpenArgs.OpenArg"
        Resume Exit_OpenArg
    End Select
    Resume 0    '.FOR TROUBLESHOOTING
End Function'*-PUBLIC Class function / sub declaration

'===========================================================
'Form frmStates - a demo form that displays a state lookup table
'===========================================================
Option Compare Database
Option Explicit

Private lclsOpenArgs As clsOpenArgs

Private Sub Form_Open(Cancel As Integer)
    Set lclsOpenArgs = New clsOpenArgs
    lclsOpenArgs.mInit Me, True
End Sub
Private Sub cmdClose_Click()
On Error GoTo Err_cmdClose_Click

    DoCmd.Close

Exit_cmdClose_Click:
    Exit Sub
Err_cmdClose_Click:
    MsgBox Err.Description
    Resume Exit_cmdClose_Click
End Sub

'===========================================================
'Form frmOpenArgsDemo - a demo form that opens the state form, 
'passing in openargs
'===========================================================
Option Compare Database
Option Explicit

Private Sub cmdStatesDataEntry_Click()
On Error GoTo Err_cmdStatesDataEntry_Click

    Dim stDocName As String
    Dim stLinkCriteria As String
    Dim strOpenArgs As String
    
    strOpenArgs = "DataEntry=True;AllowEdits=True;AllowDeletions=False;"
    stDocName = "frmStates"
    DoCmd.OpenForm stDocName, , , stLinkCriteria, , , strOpenArgs

Exit_cmdStatesDataEntry_Click:
    Exit Sub

Err_cmdStatesDataEntry_Click:
    MsgBox Err.Description
    Resume Exit_cmdStatesDataEntry_Click
    Resume 0
End Sub

John W. Colby
www.ColbyConsulting.com 


-----Original Message-----
From: accessd-bounces at databaseadvisors.com 
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Darren DICK
Sent: Sunday, January 29, 2006 5:29 PM
To: 'Access Developers discussion and problem solving'
Subject: Re: [AccessD] Same form, different actions

Hi John
Anyone feel free to jump in if I have this wrong 

The open Args are quite useful, but tacked on the end of a Do.cmd
statement they don't do much Just text or numbers (usually) tacked on
the end of an OpenForm Do.Cmd statment

The real 'power' is in the interpretation at the other end

.....

-- 
AccessD mailing list
AccessD at databaseadvisors.com 
http://databaseadvisors.com/mailman/listinfo/accessd 
Website: http://www.databaseadvisors.com
-- 
AccessD mailing list
AccessD at databaseadvisors.com
http://databaseadvisors.com/mailman/listinfo/accessd
Website: http://www.databaseadvisors.com



More information about the AccessD mailing list