473,416 Members | 1,614 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,416 developers and data experts.

VBA Class Basics

NeoPa
32,556 Expert Mod 16PB
Introduction
For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all of the Reports, opened by it have been closed, and then makes that (calling) Form visible again. All Forms are shown in Restore mode while Reports are shown in Maximise mode. Some selections point to Forms that don't exist and show an error message. One of the selections allows one or more Reports to be run. The main Form (frmMainMenu) and the one that opens the Reports (frmReports) illustrate the fact they're aware the called Form or Report(s) have been closed by showing a Message Box on the screen immediately. It looks untidy as the previous object can still be seen on the screen at the same time, but it's there purely to illustrate the capabilities available.

Hopefully, the relatively simple nature of the process will allow you to understand the concept without too much fluff getting in the way.


Working Attachment
Please find attached, a ZIP file that contains the working example called "UKAUG202311.AccDb". Feel free to download it now and have a play with it; make sure you understand what it's doing. You may have no desire to do what it does. What I'm hoping to show is the concept behind it and how classes are used in this case - in order that you understand where, and how, they can be used to do things you want to do.


VBA Classes with Objects
Although VBA classes do not support the generally-understood concept of Encapsulation, they do allow for objects to be contained within the class code, as well as, importantly, their Events to be handled by the class.

There is a caveat to this however, and that is that Events can only be handled by the class, that already have Event procedures in the objects themselves. Thus you could have two different Forms used by two different instances of a class (or even the same instance at different times) where one could have its Event handled by the class but the other not, if the first form had a procedure for the Event but the second did not.


Class/Object Events
User Defined Classes can also define their own Events. Events support passing parameters and, by using the ByRef keyword, these can be used to pass information both ways. A class needs to both define the Event, as well as Raise it (using RaiseEvent). Be aware that IntelliSense is a little less helpful than usual with this statement (RaiseEvent)so you may have to type it out in full in order to use it. Examples of defining & raising the Events can be found in the code below at lines #17, #18, #96 & #97.


Class/Object Properties
Coding Propertys within a Class is done using the three Property procedure types shown below. Each comes with an example definition & usage :
  1. Property Let
    This allows a Class-User to assign a value to this Property in the same way they would assign a value to any normal variable. This does not support objects - just as you can't simply say A = B with object variables (but have to use Set).
    Expand|Select|Wrap|Line Numbers
    1. Definition
    2. Private lngVar As Long
    3.  
    4. Public Property Let Y(Z As Long)
    5.     lngVar = Z
    6. End Property
    7.  
    8. Usage (from outside of the Class module)
    9. Dim X As YourClass
    10.  
    11. X.Y = 326
    Notice how the 326 is passed as Z in the Property Let definition and that the variable is referenced within the Class module as lngVar rather than Y.
  2. Property Get
    This is essentially the reverse of Property Let, except it also works for Objects.
    Expand|Select|Wrap|Line Numbers
    1. Definition
    2. Private lngVar As Long
    3.  
    4. Public Property Get Y() As Long
    5.     Y = lngVar
    6. End Property
    7.  
    8. Usage (from outside of the Class module)
    9. Dim lngA As Long
    10. Dim X As YourClass
    11.  
    12. lngA = X.Y
  3. Property Set
    This is like Property Let except for assigning Objects.
    Expand|Select|Wrap|Line Numbers
    1. Definition
    2. Private frmVar As Form
    3.  
    4. Public Property Set Y(Z As Form)
    5.     Set frmVar = Z
    6. End Property
    7.  
    8. Usage (from outside of the Class module)
    9. Dim X As YourClass
    10.  
    11. Set X.Y = Forms("frmMain")

clsForm Code
Here is the code from that class (clsForm). Feel free to copy it to somewhere more visible, and thus have it to hand, while you go through this section.
NB. When I refer to parts of the code I will do so via the line numbers as shown here below.
Expand|Select|Wrap|Line Numbers
  1. Option Compare Database
  2. Option Explicit
  3.  
  4. '21/1/2004  Added Private Set & Public Get code for frmTo.
  5. '21/9/2004  Removed ResumeTo functionality. _
  6.             Now handled by the OnTimer() subroutine in the calling form _
  7.             checking for (Visible) which indicates the called form is finished.
  8. '24/2/2005  Added function Uninitialised to show if instance of this object _
  9.             has yet been initialised with the callers info. _
  10.             It also checks this before it tries to open a new form.
  11. '31/3/2008  Added varOpenArgs as optional parameter to ShowForm.  Simply to be _
  12.             passed directly to the opened form using DoCmd.OpenForm(). _
  13.             Also set .OpenForm() to treat Cancel of the open as NOT an error.
  14. '3/11/2023  Added the Closed Event which allows the calling code to handle the _
  15.             associated Form being closed.
  16.  
  17. 'Public Event Closed()
  18. Public Event Closed(ByVal strName As String)
  19.  
  20. Private Const conUnInitMsg As String = _
  21.                   "Object uninitialised - unable to show form."
  22.  
  23. Private frmParent As Form
  24. Private WithEvents frmCalled As Form
  25.  
  26. Public Property Set frmFrom(frmValue As Form)
  27.     Set frmParent = frmValue
  28. End Property
  29.  
  30. Private Property Get frmFrom() As Form
  31.     Set frmFrom = frmParent
  32. End Property
  33.  
  34. Private Property Set frmTo(frmValue As Form)
  35.     Set frmCalled = frmValue
  36. End Property
  37.  
  38. Public Property Get frmTo() As Form
  39.     Set frmTo = frmCalled
  40. End Property
  41.  
  42. 'Uninitialised returns True if frmFrom not yet initialised.
  43. Public Function Uninitialised() As Boolean
  44.     Uninitialised = (frmParent Is Nothing)
  45. End Function
  46.  
  47. 'ShowForm opens form strTo and hides the calling form.  Returns True on success.
  48. Public Function ShowForm(strTo As String, _
  49.                          Optional strFilter As String = "", _
  50.                          Optional varOpenArgs As Variant = Null) As Boolean
  51.     ShowForm = True
  52.     'Don't even try if caller hasn't initialised Form object yet
  53.     If Uninitialised() Then
  54.         ShowForm = False
  55.         Call ShowMsg(strMsg:=conUnInitMsg, strTitle:="clsForm.ShowForm")
  56.         Exit Function
  57.     End If
  58.     Call DoCmd.Restore
  59.     'Handle error on OpenForm() only.
  60.     On Error GoTo ErrorSF
  61.     Call DoCmd.OpenForm(FormName:=strTo, _
  62.                         WhereCondition:=strFilter, _
  63.                         OpenArgs:=varOpenArgs)
  64.     On Error GoTo 0
  65.     Set frmCalled = Forms(strTo)
  66.     frmFrom.Visible = False
  67.     Exit Function
  68.  
  69. ErrorSF:
  70.     ShowForm = False
  71.     ' If open is cancelled (either by user or code - 2501) then simply exit
  72.     With Err
  73.         If .Number <> 2501 Then
  74.             Call ErrorHandler(strName:=strTo, _
  75.                               strFrom:=frmFrom.Name & ".ShowForm", _
  76.                               lngErrNo:=.Number, _
  77.                               strDesc:=.Description)
  78.  
  79.             'Call .Raise(Number:=.Number _
  80.                       , Source:=frmFrom.Name & ".ShowForm" _
  81.                       , Description:=.Description)
  82.         End If
  83.     End With
  84. End Function
  85.  
  86. '************************* Contained Object Method(s) *************************
  87. 'For these subroutines to be activated the contained object must have the
  88. ''On Close' property set to a valid subroutine within the contained object.
  89. Private Sub frmCalled_Close()
  90.     Dim strName As String
  91.  
  92.     frmParent.Visible = True
  93.     Call DoCmd.Restore
  94.     strName = frmCalled.Name
  95.     Set frmCalled = Nothing
  96.     'RaiseEvent Closed
  97.     RaiseEvent Closed(strName)
  98. End Sub
  99. '******************************************************************************
Lines #17 - #18 define the Event named Closed which is exposed by the class. Line #17 shows the simpler usage and #18 is used to illustrate how you can pass information to & from the class while handling the Event.

Lines #20 - #21 define an error message used when the class is invoked inappropriately.

Lines #23 - #24 show two different ways to define objects in VBA. #24 is different & special as it allows Events from the object (In this case a Form obviously.) to be handled in the class itself. See lines #86 through #99 of this module for the format of a class's handling of (one of) its WithEvents objects. Notice the name of the Event Procedure includes the name of the specified object as declared in line #24.

Lines #26 - #40 show examples of Property Let/Get/Set procedures. These are explained above under Class/Object Properties. Notice how frmCalled, as defined on line #24, is how the object is referred to internally, yet when presented to users of this class, it is as the Property frmTo.

Lines #42 - #45 show the Uninitialised() Method. Any user of the class must set the value of frmParent using the frmFrom() Property before anything else can work sensibly. This function is provided to test that. It is Public so it can also be called from outside of the class module itself.

Lines #47 - #84 show the ShowForm() Method. This roughly mirrors the DoCmd.OpenForm() Method - at least the parameters I ever use. It explicitly handles the Form failing to open but passes any other errors onto the main error handler, which I don't cover here (as irrelevant). However, the code can be found in the attached example database if interested.

Fundamentally, it checks the class instance has been properly initialised then, if it has, Restores the window before opening the Form, using the parameters as passed. Once this has succeeded it sets frmCalled to this Form and hides the parent/calling Form.

Lines #86 - #99 handle the Close event of the called Form (internally referenced as frmCalled - hence the name of frmCalled_Close()). Once it closes, this procedure ensures frmCalled is reset to Nothing and the parent/calling Form is made visible again. For good measure it Restores the window again. The working basis is that Forms look better in Restore mode while Reports look better Maximised. It also raises the clsForm.Closed Event which allows the calling code, if it handles that Event, to be informed that the called Form has just closed. In this example, for illustration only, it also passes the name of the Form that has just closed. Calling code will ignore this if no Procedure has been defined for this Event.


Conclusion
While the attached example database also includes a clsReport class, along with the clsForm one as shown here, the fundamentals of class usage, & I hope I've kept to the very basics in order to show how straightforward it is getting into the subject, are covered here.

Feel free to leave comments below, but please post any related questions separately (in the Access Questions Forum). Also, feel free to use any parts of this work. Attribution is purely voluntary.
Attached Files
File Type: zip UKAUG202311.Zip (498.1 KB, 74 views)
Oct 24 '23 #1
3 37853
Nauticalgent
100 64KB
Excellent contribution, more to come?
Nov 2 '23 #2
NeoPa
32,556 Expert Mod 16PB
Thank you :-)

I'm working on a description & breakdown of the clsReport class - also included in the attached database (already).
Nov 2 '23 #3
NeoPa
32,556 Expert Mod 16PB
For anyone interested, I've just reposted an updated version. This new version contains information on how to get a class to define & raise Events. Thanks are due to John Colby who presented recently at AUG Pacific on some of what he's been doing with classes.

I have also caught up with myself and posted the VBA Class Basics (Report Class) companion article that deals with the clsReport class found in this same database.
Nov 6 '23 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: Steven Lien | last post by:
I wrote a simple vector class that can store Cards, and my question is if i had Card class, should i "new" it to store into vector , or simply use copy structure?. if i need the vector class to be...
2
by: Kurien Baker Fenn | last post by:
I would like to show the progress of an application using the progress bar in visual basics using the timer.Please help me. Thanks in advance.
2
by: D | last post by:
Hello I'm learning C++ and having done some Asm and C. I would like input on the following. If I understand what I'm reading then Objects of a type of class gets a copy of it's class' (including...
5
by: Stephen Russell | last post by:
In the past public void has worked. But I need to return an XMLDocument, and this class needs a string param for the SP to call. public void makeXML (string lcStatement) wont allow me to return...
5
by: Simon Harris | last post by:
Hi All, Being a classic ASP programmer, I'm trying to get to grips with OOP, specifically using classes. I have setup my class with various properties, so far so good. What I dont quite get...
3
by: Peskov Dmitry | last post by:
Hi, What is the memory layout of an object, and the derived object. For example : class A { private: int prv_data; protected: int pro_data;
0
by: babu8880 | last post by:
www.convensysglobal.com/elearn You can login and attend courses and similar resources ask your doubts from experienced engineers in iphone and Objective C Domain You can attend live classes...
1
by: perto1 | last post by:
Hi, I am a first semester student, learning the OOPs basics. I need help for a program: class Message{ public: void input(); int output(); private: long token_number;// next token to be...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.