[AccessD] Same form, different actions

Darren DICK darrend at nimble.com.au
Sun Jan 29 22:51:19 CST 2006


Brilliant
Many thanks for that John
I am grateful
 
I never quite 'got into' classes
It was always on my to-do list
Now I virtually do nothing with Access <sigh>
I only lurk the list because of sentimental attachment :-)))

See ya

Darren
 

-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of John Colby
Sent: Monday, 30 January 2006 3:20 PM
To: 'Access Developers discussion and problem solving'
Subject: Re: [AccessD] Same form, different actions

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




More information about the AccessD mailing list