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