[AccessD] Filters - was filtered reports

John W. Colby jwcolby at colbyconsulting.com
Sat Jan 8 18:13:31 CST 2005


As I said, the plain vanilla fltr in a module works quite well for most
purposes.   It is clean and simple.  A collection can hold thousands of
these filters.  The biggest issue becomes tracking what has been used where
if you start using them extensively.  It is only at that point that perhaps
using class instances makes sense so that you don't inadvertently reuse an
existing filter for another process.

John W. Colby
www.ColbyConsulting.com 

Contribute your unused CPU cycles to a good cause:
http://folding.stanford.edu/

-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of William Hindman
Sent: Saturday, January 08, 2005 6:07 PM
To: Access Developers discussion and problem solving
Subject: Re: [AccessD] Filters - was filtered reports


..mucho gracias mi compadre ...necesito digerir esto, eh :)

William Hindman


----- Original Message ----- 
From: "John W. Colby" <jwcolby at colbyconsulting.com>
To: "'Access Developers discussion and problem solving'" 
<accessd at databaseadvisors.com>
Sent: Saturday, January 08, 2005 10:54 AM
Subject: [AccessD] Filters - was filtered reports


> William,
>
> The class approach adds a level of indirection and so I do not 
> recommend
> it
> unless you specifically need it.
>
> The class approach simply embeds the collection, the Boolean and the 
> function in a class.  That really all there is to it.  Because the 
> whole thing is encapsulated you can now create an instance of filters 
> for purpose a, an instance for purpose b etc.  Perhaps you have a 
> module, with related forms that need to be able to pass parameters 
> back and forth.  The typical method of doing this is to start adding 
> global variables, add a new variable
> every time you need to pass some other thing.  With a class you create an
> instance and all the objects of that functional area can pass stuff back 
> and
> forth using the class instance that is dedicated to their use.
>
> The class would then look something like:
>
> '#####################################################################
> ######
> ##
> Option Compare Database
> Option Explicit
> '
> 'The collection to hold the filter values
> '
> Private mcolFilter As Collection
> '
> 'Set up the collection
> '
> Private Sub Class_Initialize()
>    Set mcolFilter = New Collection
> End Sub
> '
> 'Tear down the collection
> '
> Private Sub Class_Terminate()
>    Set mcolFilter = Nothing
> End Sub
> '
> 'Get a pointer to the collection
> '
> Public Property Get pcolFilter() As Collection
>    Set pcolFilter = mcolFilter
> End Property
> '
> 'The actual filter function
> '
> Public Function Fltr(lstrName As String, Optional lvarValue As Variant) As
> Variant
> On Error GoTo Err_Fltr
>    If IsMissing(lvarValue) Then
>        On Error Resume Next
>        Fltr = mcolFilter(lstrName)
>        If Err <> 0 Then
>            Fltr = Null
>        End If
>    Else
>        On Error Resume Next
>        mcolFilter.Remove lstrName
>        mcolFilter.Add lvarValue, lstrName
>        Fltr = lvarValue
>    End If
> Exit_Fltr:
> Exit Function
> Err_Fltr:
>        MsgBox Err.Description, , "Error in Function clsFltr.Fltr"
>        Resume Exit_Fltr
>    Resume 0    '.FOR TROUBLESHOOTING
> End Function
>
'###########################################################################
> ##
> The class is pretty simple, an Initialize function that sets the 
> collection,
> a Terminate function that cleans up, a property to return the entire
> collection, and the Fltr function already explained in the previous email.
> No surprises here.
>
>
> A module to test it:
>
> '#####################################################################
> ######
> ##
> Option Compare Database
> Option Explicit
>
> Private mclsFltrSet1 As clsFltr
> '
> 'Method One for using Filter classes
> '
> Function cFS1() As clsFltr
> Dim intCnt As Integer
> On Error Resume Next
>    '
>    'This line is used to test if the class is initialized yet
>    'You will get an error if the class is not initialized
>    '
>    intCnt = mclsFltrSet1.pcolFilter.Count
>    If Err <> 0 Then
>        '
>        'If you get an error, then initialize the class
>        '
>        Set mclsFltrSet1 = New clsFltr
>    End If
>    '
>    'Nolw we know that we have a valid class, get the pointer to it
>    '
>    Set cFS1 = mclsFltrSet1
> End Function
>
> Function testMethod1()
>    cFS1.Fltr "MyName", "John W. Colby"
>    Debug.Print cFS1.Fltr("MyName")
> End Function
>
> '
> 'Method Two for using filter classes
> '
> Function FltrWrapper(lstrName As String, Optional lvarValue As 
> Variant) As Variant
>    '
>    'If the lvarValue is missing we are retrieving a previously set filter
>    '
>    If IsMissing(lvarValue) Then
>        FltrWrapper = cFS1.Fltr(lstrName)
>    Else
>   'Else we are setting a filter value
>        cFS1.Fltr lstrName, lvarValue
>    End If
> End Function 
> '#####################################################################
> ######
> ##
>
> This module sets up a private variable to hold a pointer to the class.
> What
> we are going to do is create a function that tests for a class instance 
> and
> instantiates the class if it hasn't already done so (the first time).  We
> test for a valid instance by trying to get the count of the collection
> inside the class.  If that fails then the collection is not initialized, 
> and
> by inference the class itself is not instantiated.
>
> Once we know the class is instantiated we simply return a pointer to 
> the class.  TestMethod1 then calls the cfs1.filter method, passing in 
> the name of the filter we want to set up, and the value.  At a later 
> time we then call the same method passing in just the name of the 
> filter and retrieve the value.
>
> For many purposes that is enough.  Unfortunately Access queries cannot 
> reference properties of a class so you must wrap a call to one of the 
> class instances in a function which a query can then use in a where 
> clause, aliased field etc.  FltrWrapper does exactly that.  Notice 
> that the function
> takes exactly the same parameters as the core filter function buried down 
> in
> the fltr class.  This function must determine whether we are setting a 
> value
> or retrieving a value and act appropriately.
>
> Unfortunately the whole concept of a class is to have multiple 
> instances, and this method of dimming an explicit variable for each 
> class instance soon becomes an issue since you now need a function to 
> return a pointer to each class instance.  The next conceptual level is 
> a class (I call them "supervisor" classes) that contains a collection 
> of the filter classes. Doing it this way allows us to set up a single 
> supervisor class, and then it
> can hold as many filter classes as desired.  Essentially you take 
> everything
> in this test module and throw it in a class just like we took the filter
> module and threw it in a class.  The supervisor then needs a simple module
> to initialize it's single variable, and a method to return a pointer to 
> that
> class instance.  I will put all of that in another email so that the
> discussion doesn't get too long.
>
> John W. Colby
> www.ColbyConsulting.com
>
> Contribute your unused CPU cycles to a good cause: 
> http://folding.stanford.edu/





More information about the AccessD mailing list