[AccessD] Same form, different actions

John Colby jwcolby at ColbyConsulting.com
Sun Jan 29 22:20:21 CST 2006


>>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

.....




More information about the AccessD mailing list