Microsoft Access VBA Tutorials for self-paced learning, Class Modules, SQL Techniques, and AI Integration Guides.

Ms-Access and Collection Object Basics

Collection Object Basics.

A Collection object is a built-in VBA object that provides a convenient way to store and manage a group of related objects or values as a single unit. It is available in all Microsoft Office applications that support VBA, including Microsoft Access, Excel, Word, Outlook, and PowerPoint.

Unlike an array, a Collection is dynamic, meaning items can be added or removed at runtime without resizing the collection. Each item in the Collection is automatically assigned a numeric index, and it may also be assigned a unique string key for direct data retrieval.

Key Characteristics

  • Dynamic storage – Items can be added or removed at any time during program execution.

  • Ordered collection – Items are maintained in the order in which they are added unless inserted at a specific position.

  • Heterogeneous contents – A Collection can contain objects, variables, or values of different data types.

  • Indexed access – Items can be accessed by their numeric position (1-based indexing).

  • Key-based access – Items may optionally be assigned unique string keys for faster identification.

  • Automatic memory management – VBA manages the internal storage of Collection, eliminating the need for manual resizing.

Typical Uses

The Collection object is widely used to:

  • Store instances of custom class objects.
  • Maintain lists of Forms or Controls.
  • Organize records or business objects in memory.
  • Build reusable object frameworks.
  • Manage wrapper class instances in Microsoft Access applications.
  • Replace dynamically resized arrays where frequent additions or deletions are required.

In VBA, Arrays are more commonly used than Collection objects for storing multiple sets of related values (in rows and columns). We have already used Arrays to store User-Defined Types and Class Module objects. Now, it’s time to explore something new—the use of Collection and Dictionary objects. The Collection object is particularly convenient for grouping related items together. As for the Dictionary object, we will discuss its usage at the appropriate time.

When using Arrays, we must dimension a variable, User-Defined Type, or Class Module object with the required number of elements in advance—or re-dimension it later to increase or decrease its size—before storing values in it. This extra step is not necessary with a Collection object. Once a Collection object is instantiated, we can dynamically add any number of items to it. Its members can be of any data type, including built-in objects, Class Module objects, or even other Collection objects with their own item members.

Collection Object Demo Program.

Let us write a simple program to demonstrate the usage of a Collection Object.

Public Sub CollTest1()
Dim C As Collection
Dim j As Integer

‘instantiate the Object
Set C = New Collection
                            
C.Add 5
C.Add 15
C.Add "iPhone"
C.Add "Disk 2TB"
C.Add 35.75

'Print the items in debug window
GoSub Listing

C.Remove 3 'Remove 3rd item

GoSub Listing

Set C = Nothing

Exit Sub

Listing:
Debug.Print
For j = 1 To C.Count
    Debug.Print C.Item(j)
Next
Return

End Sub

Code Review Line By Line.

The first two lines declare the Variable C as a Collection Object. The next line declares the Variable j as an Integer type, as a control variable for the For... Next Loop.  The third line instantiates the Collection Object C in memory.

The Collection Object has four built-in methods: Add, Count, Item, and Remove, for managing the Collection items in memory.

The Collection Object Instance image given below displays its list of methods.

  • The Add method adds a new Item to the Collection.  The Remove method removes an item by its numeric index or key.

  • To access a specific item, we can use the Item method with its index number. The Count property returns the total number of items in the Collection.

  • In the current example, we are not working with object-type items but with a few simple mixed data types—Integer, String, and Double—as members of the Collection. Using the Add method of the Collection object named C, we have inserted five items: the first two are integers, the next two are strings, and the last one is a double-precision number.

  • The syntax: C.Add (Item, [Key], [Before], [After])  The Add method is followed by a space, and then the actual value to be added. Other parameters are optional.

  • The Add method accepts four optional parameters, as shown in the image below.

  • The parameters are: Item, [Key], [Before], [After].  The first parameter, Item, is mandatory; the Value to be added to the Collection.

  • The next three parameters are optional. 

  • When using any of the optional parameters of the Add method, you must insert comma placeholders to skip over unused parameters—except when you are specifying parameters from the rightmost side in order.

    Alternatively, you can explicitly use parameter names with their values, which allows you to provide the parameters in any order.

    We will explore this technique in another VBA example.

    Note: Do not misinterpret the Item Parameter of the Add Method with the Item() Method of the Collection Object.

  • We have added five items as Collection Object members with the Add method.  Two integer-type values, two String-type Values, and one double-precision number. 

    It demonstrates that you can add any data type, except User-Defined Types (UDTs), into the Collection.  When you want to add UDTs into a Collection, convert your UDTs into a Class Module Object.

    Next, the program calls a printing subroutine that outputs the Collection members to the Debug window. This subroutine uses a For...Next loop that runs from 1 to the total number of items (C.Count) in the Collection. The loop control variable j is used as the index parameter of the Collection’s Item() method to retrieve each value and print it to the Debug window.

    The next Line removes the third item (iPhone) from the item members by calling the Remove method.

    The printing subroutine is called again to print the list of items after removing the third item from the earlier list.

    The Exit Sub statement prevents the program control from dropping into the internal subroutine lines and stops the program.  The listing will appear in the Debug Window as shown below.

    The Output in the Debug Window.

    5 
    15 
    iPhone
    Disk 2TB
    35.75
    
    5 
    15 
    Disk 2TB
    35.75
    

    We can insert a value before a particular item member by specifying the item number with the Before key Name.

    C.Add 2, Before:=1 ‘add value 2 Before existing first item 
    

    OR

    C.Add 2,,1

    The above statement will add value 2 as the first item in the above program, pushing all existing items down.

    C.Add 20, After:=3 ‘Add value 20 After existing item number 3
    

    OR

    C.Add 20,,,3

    This statement inserts the value 20 after the third item, after value 15,  in the list.

    The Code below demonstrates the Before:= and After:= Parameter Names.

    Public Sub CollTest2()
    Dim C As Collection
    Dim j As Integer
    
    Set C = New Collection
    
    C.Add 5
    C.Add 15
    C.Add "iPhone"
    C.Add "Disk 2TB"
    C.Add 35.75
    
    GoSub Listing
    
    C.Add 2, Before:=1 'Insert the item before the first item
    C.Add 20, After:=3 'Insert the item after first 3 items
    
    GoSub Listing
    
    Set C = Nothing
    Exit Sub
    
    Listing:
    'Print the items
    Debug.Print
    For j = 1 To C.Count
       Debug.Print C(j)
    
    Next
    Return
    
    End Sub
    

    Note: By using parameter names, you can pass values in any order you want when you need to use more than one parameter in a statement.

    C.Add After:=3,Item:=20

    The second example demonstrates parameter use without explicitly specifying their parameter names, placing each value in its defined correct positional order.

    Public Sub CollTest2_2()
    Dim C As Collection
    Dim k As Integer
    

    Set C = New Collection C.Add 5 C.Add 15 C.Add "iPhone" C.Add "Disk 2TB" C.Add 35.75 GoSub Listing C.Add 2, , 1 'Insert the item before the first item C.Add 20, , , 3 'Insert the item after first 3 items GoSub Listing Set C = Nothing Exit Sub Listing: 'Print the items Debug.Print      For k = 1 To C.Count          Debug.Print C(k)      Next: Debug.Print Return End Sub

    Sample printout in the Debug Window is shown below:

    5 
     15 
    iPhone
    Disk 2TB
     35.75 
    
     2 
     5 
     15 
     20 
    iPhone
    Disk 2TB
     35.75 
    

    In all our printing examples, we have used the Item’s index number to retrieve values for display in the Debug Window. However, when a collection contains many items, it becomes difficult to remember the index number of a specific item we want to access. To overcome this, we can associate each item with an easily memorable Key along with its Value—for example, using a contact’s first name as the Key in an address book Collection—so we can retrieve the item’s value directly by its Key instead of relying on its index number.

    Usage of Item Keys.

    Let’s write a new program to demonstrate how to use Keys with Values in a Collection.

    Public Sub CollTest3()
    Dim C As Collection
    Dim strKey As String
    Dim strGet As String
    
    Set C = New Collection
    
    C.Add 5, Key:="FIVE" 
    C.Add 15, Key:="FIFTEEN"
    C.Add "iPhone", "7+"     'you can omit the KEY param name
    C.Add "Disk 2TB", "DISK" ' Add method's 2nd Parameter is KEY
    C.Add 35.75, "999"
    
    'add value 2 with Key "TWO" before the first item.
    'this item will be the first item in the collection
    'parameter names not in proper order – valid
    
    C.Add Item:=2, Before:=1, Key:="TWO"
    
    'add value 7 with Key "SEVEN" as third item in the collection
    'parameter names not in proper order – valid
    
    C.Add Key:="SEVEN", Item:=7, After:=2
    
    'Retrieve value using it's KEY from collection
    
    strKey = ""
    Do While strKey = ""
        strKey = InputBox("Value Key: " & vbCr & vbCr & "Q - Quit", "Enter Key", "")
        
        Select Case strKey
            Case "Q"
               Exit Do
            Case "TWO", "FIVE", "SEVEN", "FIFTEEN", "7+", "DISK", "999"
               strGet = C(strKey)
            Case Else
               strGet = " Not Found!"
       End Select
       
    MsgBox "Key:<<" & strKey & ">> Value: " & strGet
    strKey = ""
    Loop
    
    Set C = Nothing
    
    End Sub
    

    The KEY value must be of String Type.  The KEY value must be a unique identifier.

    Refer to the second image on this page to view the Add method of the Collection Object and the proper order of Parameters, displayed by the VBA IntelliSense.

    The sample programs shown earlier, with mixed data types, were intended solely for demonstration purposes. In practical use, a Collection object typically stores items of a single data type, most commonly used to hold objects—such as Forms, Reports, Class Module objects, or Database objects—along with their associated properties and methods.

    CLASS MODULES.

    1. MS-Access Class Module and VBA
    2. MS-Access VBA Class Object Arrays
    3. MS-Access Base Class and Derived Objects
    4. VBA Base Class and Derived Objects-2
    5. Base Class and Derived Object Variants
    6. MS-Access Recordset and Class Module
    7. Access Class Module and Wrapper Classes
    8. Wrapper Class Functionality Transformation

    COLLECTION OBJECT.

    1. MS-Access and Collection Object Basics
    2. MS-Access Class Module and Collection Object
    3. Table Records in Collection Object and Form

    DICTIONARY OBJECT.

    1. Dictionary Object Basics
    2. Dictionary Object Basics-2
    3. Sorting Dictionary Object Keys and Items
    4. Display Records from Dictionary to Form
    5. Add Class Objects as Dictionary Items
    6. Update Class Object Dictionary Item on Form
Share:

Wrapper Class Functionality Transformation

Wrapper Class and Creation of New Objects.

Last week, we created a new Wrapper Class named ClsTiles, which used the ClsArea Class twice within the same Class Module—one instance to store the room’s floor dimensions and another to store the tile dimensions—to calculate the number of tiles needed for the room.

The Wrapper Class Module ClsVolume2 and transform it into a new ClsSales Class. With a complete facelift to ClsVolume2 and repurposing it to calculate the product's selling price with a discount.

Interestingly, the ClsVolume2 Class already has all the necessary properties to store sales-related data: strDesc, dblLength, dblWidth, and dblHeight can be repurposed to represent Description, Quantity, Unit Price, and Discount Percentage, respectively.

Remember, the ClsVolume2 Class is a derived class, originally built using ClsArea as its base class.ClsVolume2 Class Revisited.

But, first, the VBA Code of the ClsVolume2 Class Module  (the Base Class for our new ClsSales Class Module) is reproduced below for reference:

Option Compare Database
Option Explicit

Private p_Height As Double
Private p_Area As ClsArea

Public Property Get dblHeight() As Double
    dblHeight = p_Height
End Property

Public Property Let dblHeight(ByVal dblNewValue As Double)
    p_Height = dblNewValue
End Property

Public Function Volume() As Double
    Volume = CArea.dblLength * CArea.dblWidth * Me.dblHeight
End Function

Public Property Get CArea() As ClsArea
   Set CArea = p_Area
End Property

Public Property Set CArea(ByRef AreaValue As ClsArea)
  Set p_Area = AreaValue
End Property

Private Sub Class_Initialize()
Set p_Area = New ClsArea
End Sub

Private Sub Class_Terminate()
Set p_Area = Nothing
End Sub 

The only obstacle preventing us from using the ClsVolume2 Class directly for sales data entry is that its Property Procedure names—dblLength, dblWidth, and dblHeight—do not correspond to the required sales-related properties: Quantity, Unit Price, and Discount Percentage.

Fortunately, all these properties in the ClsVolume2 Class are of the Double Data type, which is suitable for our sales calculations.

Similarly, the public function names Area() and Volume() are not meaningful in the context of sales, but their underlying calculation logic can be repurposed for sales-related computations without modification.

a) Area = dblLength * dblWidth is suitable for TotalPrice = Quantity * UnitPrice

b) Volume = Area * dblHeight is good for DiscountAmount = TotalPrice * DiscountPercentage

Here, there are two choices to repurpose the ClsVolume2 as a ClsSales Class:

  1. The easiest approach is to create a copy of the ClsVolume2 Class and save it as a new Class Module named ClsSales. Then, update the Property Procedure names and public Function names to reflect sales-related values and calculations. You can also add any additional functions needed for handling sales operations directly within this new class module.

  2. Create a Wrapper Class based on the ClsVolume2 Base Class. In the Wrapper Class, implement corresponding property procedures and public functions that encapsulate and rename the Base Class’s property procedures and functions, effectively masking their original names. Add new functions to the Wrapper Class as needed.

The first option is relatively straightforward and easy to implement. However, we will choose the second option to learn how to access the Base Class’s properties within the new Wrapper Class and how to mask their original names with new property names.

The Transformed ClsVolume2 Class.

  1. Open your Database and display the VBA Editing Window (Alt+F11).

  2. Select the Class Module from the Insert Menu to insert a new Class Module.

  3. Change the Class Module’s Name property Value from Class1 to ClsSales.

  4. Copy and Paste the following VBA Code into the Module and Save the Code:

    Option Compare Database
    Option Explicit
    
    Private m_Sales As ClsVolume2
    
    Private Sub Class_Initialize()
        'instantiate the Base Class in Memory
        Set m_Sales = New ClsVolume2
    End Sub
    
    Private Sub Class_Terminate()
        'Clear the Base Class from Memory
        Set m_Sales = Nothing
    End Sub
    
    Public Property Get Description() As String
      Description = m_Sales.CArea.strDesc 'Get from Base Class
    End Property
    
    Public Property Let Description(ByVal strValue As String)
      m_Sales.CArea.strDesc = strValue ' Assign to Base Class
    End Property
    
    Public Property Get Quantity() As Double
    Quantity = m_Sales.CArea.dblLength
    End Property
    
    Public Property Let Quantity(ByVal dblValue As Double)
       If dblValue > 0 Then
         m_Sales.CArea.dblLength = dblValue ' Assign to clsArea, Base Class of ClsVolume2
       Else
         MsgBox "Quantity: " & dblValue & " Invalid.", vbExclamation, "ClsSales"
         Do While m_Sales.CArea.dblLength <= 0
              m_Sales.CArea.dblLength = InputBox("Quantity:, Valid Value >0")
         Loop
       End If
    End Property
    
    Public Property Get UnitPrice() As Double
       UnitPrice = m_Sales.CArea.dblWidth
    End Property
    
    Public Property Let UnitPrice(ByVal dblValue As Double)
       If dblValue > 0 Then
          m_Sales.CArea.dblWidth = dblValue ' Assign to clsArea, Base Class of ClsVolume2
       Else
         MsgBox "UnitPrice: " & dblValue & " Invalid.", vbExclamation, "ClsSales"
           Do While m_Sales.CArea.dblWidth <= 0
              m_Sales.CArea.dblWidth = InputBox("UnitPrice:, Valid Value >0")
           Loop
       End If
    End Property
    
    Public Property Get DiscountPercent() As Double
       DiscountPercent = m_Sales.dblHeight
    End Property
    
    Public Property Let DiscountPercent(ByVal dblValue As Double)
    ' Assign to Class .dblHeight of ClsVolume2
    Select Case dblValue
        Case Is <= 0
           MsgBox "Discount % -ve Value" & dblValue & " Invalid!", vbExclamation, "ClsSales"
           Do While m_Sales.dblHeight <= 0
              m_Sales.dblHeight = InputBox("Discount %, Valid Value >0")
           Loop
        Case Is >= 1
           m_Sales.dblHeight = dblValue / 100
        Case 0.01 To 0.75
           m_Sales.dblHeight = dblValue
    End Select
    End Property
    
    Public Function TotalPrice() As Double
    Dim Q As Double, U As Double
    Q = m_Sales.CArea.dblLength
    U = m_Sales.CArea.dblWidth
    If (Q * U) = 0 Then
       MsgBox "Quantity / UnitPrice Value(s) 0", vbExclamation, "ClsVolume"
    Else
       TotalPrice = m_Sales.CArea.Area 'Get from Base Class ClsArea
    End If
    End Function
    
    Public Function DiscountAmount() As Double
       DiscountAmount = TotalPrice * DiscountPercent
    End Function
    
    Public Function PriceAfterDiscount()
       PriceAfterDiscount = TotalPrice - DiscountAmount
    End Function
     

So far in the Wrapper Class, we have created an instance of the ClsVolume2 class, renamed its property and function members to more suitable names, and added validation checks with appropriate error messages. We also ensured that invalid input does not trigger the Base Class’s own validation routines, which could otherwise display error messages like “Value of the dblLength property is invalid” from the ClsVolume2 class.

Review the highlighted lines in the code above; they should help you understand how the property values are assigned to and retrieved from the Base Class ClsVolume2.

First, review the ClsArea Class Module, and then examine the ClsVolume2 Class Module, which is derived from ClsArea. After understanding both of these, revisit the code in this Wrapper Class for a better perspective.

Test Program for ClsSales Class in Standard Module.

Let us write a Test Program to try out the Wrapper Class.

  1. Copy and Paste the following VBA Code into a Standard Module.

    Public Sub SalesTest()
    Dim S As ClsSales
    
    Set S = New ClsSales
    
    S.Description = "Micro Drive"
    S.Quantity = 12
    S.UnitPrice = 25
    S.DiscountPercent = 0.07
    
    Debug.Print "Desccription", "Quantity", "UnitPrice", "Total Price", "Disc. Amt", "To Pay"
    With S
        Debug.Print .Description, .Quantity, .UnitPrice, .TotalPrice, .DiscountAmount, .PriceAfterDiscount
    End With
    End Sub

    Run The Code.

  2. Keep the Debug Window open (Ctrl+G).

  3. Click in the Code, press the F5 key to run the code, and print the output in the Immediate window.

  4. You can further test the code by entering negative numbers for any input value and running it to trigger the new error messages. You may also try disabling one or more input lines by placing a comment symbol (') at the beginning of the line, then rerun the code and observe the results.

Calculate Price/Discount for an Array of Products.

The following test code creates an array of three Products and Sales Values by entering directly from the Keyboard. 

Copy and paste the following Code into a Standard Module, and run to test the Wrapper Class.

Public Sub SalesTest2()

Dim S() As ClsSales
Dim tmp As ClsSales
Dim j As Long

For j = 1 To 3
Set tmp = New ClsSales
   tmp.Description = InputBox(j & ") Description")
   tmp.Quantity = InputBox(j & ") Quantity")
   tmp.UnitPrice = InputBox(j & ") UnitPrice")
   tmp.DiscountPercent = InputBox(j & ") Discount Percentage")
 ReDim Preserve S(1 To j) As ClsSales
 Set S(j) = tmp
 Set tmp = Nothing
Next

'Output Section
Debug.Print "Desccription", "Quantity", "UnitPrice", "Total Price", "Disc. Amt", "To Pay"
For j = 1 To 3
   With S(j)
       Debug.Print .Description, .Quantity, .UnitPrice, .TotalPrice, .DiscountAmount, .PriceAfterDiscount
   End With
Next

For j = 1 To 3
  Set S(j) = Nothing
Next

End Sub

Once the correct values have been successfully entered into the array, the product names and corresponding sales values are displayed in the Debug Window.

CLASS MODULES.

Demo Database Download


  1. MS-Access Class Module and VBA
  2. MS-Access VBA Class Object Arrays
  3. MS-Access Base Class and Derived Objects
  4. VBA Base Class and Derived Objects-2
  5. Base Class and Derived Object Variants
  6. MS-Access Recordset and Class Module
  7. Access Class Module and Wrapper Classes
  8. Wrapper Class Functionality Transformation

COLLECTION OBJECT.

  1. MS-Access and Collection Object Basics
  2. MS-Access Class Module and Collection Object
  3. Table Records in Collection Object and Form

DICTIONARY OBJECT.

  1. Dictionary Object Basics
  2. Dictionary Object Basics-2
  3. Sorting Dictionary Object Keys and Items
  4. Display Records from Dictionary to Form
  5. Add Class Objects as Dictionary Items
  6. Update Class Object Dictionary Item on Form
Share:

Access Class Module and Wrapper Classes

Class Module and Wrapper Classes.

Some instances require a particular Class Module Object to be instantiated more than once to use a similar set of values for a specific application. 

For example, our ClsArea Class Module, which we designed for calculating the carpet area of Rooms, is a candidate for similar applications.  Assume we want to calculate the number of floor Tiles needed for a room; we should be able to input the Length and width of the Tile, and the dimensions of the Floor.  Since both the Floor and Tiles have similar Property values, we can use two instances of the ClsArea Class Module: one instance named FLOOR and the second instance named TILES, for area calculations.  Floor Area / Tile Area gives the total number of tiles for a particular room. 

Two Instances of the same Class Module.

We can do this by creating two different instances of the ClsArea Class Module in the Standard Module Program if there is only one Room.

Public Sub FloorTiles()
Dim FLOOR As ClsArea
Dim TILES As ClsArea
Dim flrArea As Double, tilearea As Double
Dim lngTiles As Long

Set FLOOR = New ClsArea
Set TILES = New ClsArea

FLOOR.strDesc = "Bed Room1"
FLOOR.dblLength = 25
FLOOR.dblWidth = 15
flrArea = FLOOR.Area()

TILES.strDesc = "Off-White"
TILES.dblLength = 2.5
TILES.dblWidth = 1.25
tilearea = TILES.Area()

lngTiles = flrArea / tilearea

Debug.Print FLOOR.strDesc & " Required Tiles: " & lngTiles & " Numbers - Color: " & TILES.strDesc

Set FLOOR = Nothing
Set TILES = Nothing

End Sub

Handling an Array of Objects.

But what if we want to apply the same method to an array of rooms, each with different dimensions or tile colors?

The solution is to create a new Class Module that contains two separate instances of the ClsArea Class—one instance to represent the Floor properties and the other to represent the Tile properties. Both the FLOOR and TILE instances of the ClsArea Class can be encapsulated (wrapped) within the new Class Module.

Let us do that.

  1. Open your Database and display the Code Editing Window (ALT+F11).

  2. Select the Class Module from the Insert Menu.

  3. Change the Name Property value to ClsTiles.

  4. Copy and Paste the following VBA Code into the ClsTiles Class Module and save the Code:

    Option Compare Database
    Option Explicit
    
    Private pFLOOR As ClsArea
    Private pTILES As ClsArea
    
    Private Sub Class_Initialize()
        Set pFLOOR = New ClsArea
        Set pTILES = New ClsArea
    End Sub
    
    Private Sub Class_Terminate()
        Set pFLOOR = Nothing
        Set pTILES = Nothing
    End Sub
    
    Public Property Get Floor() As ClsArea
     Set Floor = pFLOOR
    End Property
    
    Public Property Set Floor(ByRef NewValue As ClsArea)
      Set pFLOOR = NewValue
    End Property
    
    Public Property Get Tiles() As ClsArea
      Set Tiles = pTILES
    End Property
    
    Public Property Set Tiles(ByRef NewValue As ClsArea)
      Set pTILES = NewValue
    End Property
    
    Public Function NoOfTiles() As Long
       NoOfTiles = pFLOOR.Area() / pTILES.Area()
    End Function
    

    Both instances, pFLOOR and pTILES, are declared as Private Properties of the ClsTiles Class Object.

    The Class_Initialize() Subroutine instantiates both objects in memory when the ClsTiles Class Module is instantiated in the user program.

    The Class_Terminate() subroutine removes both instances (pFLOOR and pTILES) from memory. 

    The Get and Set Property Procedures enable retrieving values from, and assigning values to, the pFLOOR instance within the ClsTiles Class Object.

    We have added a new function, NoOfTiles(), in the New Class Module to calculate the number of tiles, based on the floor area and Tile dimensions.

    Let us write a Program to learn several instances of the same Class Object usage in a new Class Module: ClsTiles. Or let us say encapsulation of different Class Objects into a new derived Class Object or Wrapper Class Object. 

    The member Class Objects are built for a particular function and considered error-free on their own merits, meaning they are individually tested, and all measures are taken to safeguard against any pitfalls that may occur during their use anywhere. It is considered a suitable object to be a part of a bigger Class object.

  5. The next Get and Set Property Procedures allow the same operations in the pTILES instance of the ClsArea Class.

  6. Copy and paste the following VBA Code into a Standard Module:
    Public Sub TilesCalc()
    Dim FTiles As ClsTiles
    Dim TotalTiles As Long
    
    Set FTiles = New ClsTiles
    
    FTiles.Floor.strDesc = "Warehouse"
    FTiles.Floor.dblLength = 100
    FTiles.Floor.dblWidth = 50
    
    FTiles.Tiles.dblLength = 2.5
    FTiles.Tiles.dblWidth = 1.75
    
    TotalTiles = FTiles.NoOfTiles()
    
    Debug.Print "Site Name", "Floor Area", "Tile Area", "No. of Tiles"
    Debug.Print FTiles.Floor.strDesc, FTiles.Floor.Area, FTiles.Tiles.Area, TotalTiles
    
    End Sub
     
  7. Keep the Debug Window Open (CTRL+G) to print the test data.

  8. Click anywhere in the VBA Code and press the F5 Key to run the Code.  The result is printed in the Debug Window.

    If you need to calculate the tile requirements for multiple rooms or rooms across several floors of a high-rise building, running the above program repeatedly and manually recording the results would be impractical.

    Finding Tile Requirements of Several Rooms.

    Now, let us write another program to find the tile requirements for several rooms, using an  Array of ClsTiles Objects by inputting the Property values directly from the keyboard.

  9. Copy and Paste the following VBA Code into a Standard Module.
    Public Sub TilesCalc2()
    Dim tmpFT As ClsTiles
    Dim FTiles() As ClsTiles
    Dim j As Long, L As Long, H As Long
    
    For j = 1 To 3
       Set tmpFT = New ClsTiles
          'Floor dimension
        With tmpFT.Floor
          .strDesc = InputBox(Str(j) & ") Floor Desc", , 0)
          .dblLength = InputBox(Str(j) & ") Floor Length", , 0)
          .dblWidth = InputBox(Str(j) & ") Floor Width", , 0)
        End With
        
        'Tile Dimension
        With tmpFT.Tiles
          .strDesc = InputBox(Str(j) & ") Tiles Desc", , 0)
          .dblLength = InputBox(Str(j) & ") Tile Length", , 0)
          .dblWidth = InputBox(Str(j) & ") Tile Width", , 0)
        End With
       
       ReDim Preserve FTiles(1 To j) As ClsTiles
       Set FTiles(j) = tmpFT
       
       Set tmpFT = Nothing
    Next
    
    'Take Printout
    L = LBound(FTiles)
    H = UBound(FTiles)
    
    Debug.Print "FLOOR", "Floor Area", "TILES", "Tile Area", "Total Tiles"
    For j = L To H
      With FTiles(j)
       Debug.Print .Floor.strDesc, .Floor.Area(), .Tiles.strDesc, .Tiles.Area(), .NoOfTiles
      End With
    Next
       
    'Remove all objects from memory
    For j = L To H
       Set FTiles(j) = Nothing
    Next
      
    End Sub
    
    
  10. Keep the Debug Window open to print the output there.
  11. Run the Code as before and input values for Floor and Tile dimensions for three Rooms.

As you can see from the code, both Room and Tile dimension values are input into the same Class Object Array instance, side by side. 

The above program is a demo that runs only for three sets of values within the For... Next loop.  It can be modified with a conditional loop that runs a required number of times till a conditional break statement terminates the program. 

The program can be modified to save each set of data values and calculation results in a Table for future reference.

A Wrapper Class is a container class designed to hold instances of other classes, data structures, or collections of objects, with all the capabilities of the member objects plus the new Object.

List of All the Links on this Topic.

  1. MS-Access Class Module and VBA
  2. MS-Access VBA Class Object Arrays
  3. MS-Access Base Class and Derived Objects
  4. VBA Base Class and Derived Objects-2
  5. Base Class and Derived Object Variants
  6. MS-Access Recordset and Class Module
  7. Access Class Module and Wrapper Classes
  8. Wrapper Class Functionality Transformation
  9. MS-Access and Collection Object Basics
  10. MS-Access Class Module and Collection Object
  11. Table Records in Collection Object and Form
  12. Dictionary Object Basics
  13. Dictionary Object Basics-2
  14. Sorting Dictionary Object Keys and Items
  15. Display Records from Dictionary to Form
  16. Add Class Objects as Dictionary Items
  17. Add Class Objects as Dictionary Items
  18. Update Class Object Dictionary Item on Form
Share:

MS-Access Recordset and Class Module

MS Access Recordset and Class Module.

Sorting and Updating the Table Records.

In this section, we will create a Class Module designed for data processing tasks. An DAO.Recordset object will be passed to the custom class. Since we are passing an object to our custom class, we need to implement a pair of Property Set and Property Get procedures to assign the object to the class and to retrieve the object or its property values when required.

We have a small Table (Table 1) with a few records.  Here is the image of Table 1.

The table above has only four fields: Description, Quantity, Unit Price, and Total Price.  The Total Price field is empty.

  • One of the tasks in this tutorial is to update the TotalPrice field with the product of Qty * UnitPrice in our Class Module.

  • The Class Module includes a subroutine that sorts the records on a user-specified column, and the output is listed in the Debug Window.

  • Another subroutine creates a copy of the Table with a new name for the sorted data.

ClsRecUpdate Class Module.

  1. Open your Access Database and open the VBA Window.

  2. Insert a Class Module.

  3. Change the Name Property Value to ClsRecUpdate.

  4. Copy and Paste the following Code into the Class Module and save the Module:

    Option Compare Database
    Option Explicit
    
    Private rstB As DAO.Recordset
    
    Public Property Get REC() As DAO.Recordset
       Set REC = rstB
    End Property
    
    Public Property Set REC(ByRef oNewValue As DAO.Recordset)
    If Not oNewValue Is Nothing Then
       Set rstB = oNewValue
    End If
    End Property
    
    Public Sub Update(ByVal Source1Col As Integer, ByVal Source2Col As Integer, ByVal updtcol As Integer)
    'Updates a Column with the product of two other columns
    Dim col As Integer
    
    col = rstB.Fields.Count
    
    'Validate Column Parameters
    If Source1Col > col Or Source2Col > col Or updtcol > col Then
        MsgBox "One or more Column Number(s) out of bound!", vbExclamation, "Update()"
        Exit Sub
    End If
    
    'Update Field
    On Error GoTo Update_Err
    rstB.MoveFirst
    Do While Not rstB.EOF
       rstB.Edit
         With rstB
          .Fields(updtcol).Value = .Fields(Source1Col).Value * .Fields(Source2Col).Value
          .Update
          .MoveNext
         End With
    Loop
    
    Update_Exit:
    rstB.MoveFirst
    Exit Sub
    
    Update_Err:
    MsgBox Err & " : " & Err.Description, vbExclamation, "Update()"
    Resume Update_Exit
    End Sub
    
    Public Sub DataSort(ByVal intCol As Integer)
    Dim cols As Long, colType
    Dim colnames() As String
    Dim k As Long, colmLimit As Integer
    Dim strTable As String, strSortCol As String
    Dim strSQL As String
    Dim db As Database, rst2 As DAO.Recordset
    
    On Error GoTo DataSort_Err
    
    cols = rstB.Fields.Count - 1
    strTable = rstB.Name
    strSortCol = rstB.Fields(intCol).Name
    
    'Validate Sort Column Data Type
    colType = rstB.Fields(intCol).Type
    Select Case colType
        Case 3 To 7, 10
            strSQL = "SELECT " & strTable & ".* FROM " & strTable & " ORDER BY " & strTable & ".[" & strSortCol & "];"
            Debug.Print "Sorted on " & rstB.Fields(intCol).Name & " Ascending Order"
    
        Case Else
            strSQL = "SELECT " & strTable & ".* FROM " & strTable & ";"
    
            Debug.Print "// SORT: COLUMN: <<" & strSortCol & " Data Type Invalid>> Valid Type: String,Number & Currency //"
            Debug.Print "Data Output in Unsorted Order"
    End Select
    
    Set db = CurrentDb
    Set rst2 = db.OpenRecordset(strSQL)
    
    ReDim colnames(0 To cols) As String
    
    'Save Field Names in Array to Print Heading
    For k = 0 To cols
       colnames(k) = rst2.Fields(k).Name
    Next
    
    'Print Section
    Debug.Print String(52, "-")
    
    'Print Column Names as heading
    If cols > 4 Then
       colmLimit = 4
    Else
       colmLimit = cols
    End If
    For k = 0 To colmLimit
        Debug.Print colnames(k),
    Next: Debug.Print
    Debug.Print String(52, "-")
    
    'Print records in Debug window
    rst2.MoveFirst
    Do While Not rst2.EOF
      For k = 0 To colmLimit 'Listing limited to 5 columns only
         Debug.Print rst2.Fields(k),
      Next k: Debug.Print
    rst2.MoveNext
    Loop
    
    rst2.Close
    Set rst2 = Nothing
    Set db = Nothing
    
    DataSort_Exit:
    Exit Sub
    
    DataSort_Err:
    MsgBox Err & " : " & Err.Description, vbExclamation, "DataSort()"
    Resume DataSort_Exit
    
    End Sub
    
    Public Sub TblCreate(Optional SortCol As Integer = 0)
    Dim dba As DAO.Database, tmp() As Variant
    Dim tbldef As DAO.TableDef
    Dim fld As DAO.Field, idx As DAO.Index
    Dim rst2 As DAO.Recordset, i As Integer, fldcount As Integer
    Dim strTable As String, rows As Long, cols As Long
    
    On Error Resume Next
    
    strTable = rstB.Name & "_2"
    Set dba = CurrentDb
    
    On Error Resume Next
    TryAgain:
    Set rst2 = dba.OpenRecordset(strTable)
    If Err > 0 Then
      Set tbldef = dba.CreateTableDef(strTable)
      Resume Continue
    Else
      rst2.Close
      dba.TableDefs.Delete strTable
      dba.TableDefs.Refresh
      GoTo TryAgain
    End If
    Continue:
    On Error GoTo TblCreate_Err
    
    fldcount = rstB.Fields.Count - 1
    ReDim tmp(0 To fldcount, 0 To 1) As Variant
    
    'Save Source File Field Names and Data Type
    For i = 0 To fldcount
        tmp(i, 0) = rstB.Fields(i).Name: tmp(i, 1) = rstB.Fields(i).Type
    Next
    'Create Fields and Index for new table
    For i = 0 To fldcount
       tbldef.Fields.Append tbldef.CreateField(tmp(i, 0), tmp(i, 1))
    Next
    'Create index to sort data
    Set idx = tbldef.CreateIndex("NewIndex")
    With idx
       .Fields.Append .CreateField(tmp(SortCol, 0))
    End With
    'Add Tabledef and index to database
    tbldef.Indexes.Append idx
    dba.TableDefs.Append tbldef
    dba.TableDefs.Refresh
    
    'Add records to the new table
    Set rst2 = dba.OpenRecordset(strTable, dbOpenTable)
    rstB.MoveFirst 'reset to the first record
    Do While Not rstB.EOF
       rst2.AddNew 'create record in new table
        For i = 0 To fldcount
            rst2.Fields(i).Value = rstB.Fields(i).Value
        Next
       rst2.Update
    rstB.MoveNext 'move to next record
    Loop
    rstB.MoveFirst 'reset record pointer to the first record
    rst2.Close
    
    Set rst2 = Nothing
    Set tbldef = Nothing
    Set dba = Nothing
    
    MsgBox "Sorted Data Saved in " & strTable
    
    TblCreate_Exit:
    Exit Sub
    
    TblCreate_Err:
    MsgBox Err & " : " & Err.Description, vbExclamation, "TblCreate()"
    Resume TblCreate_Exit
    
    End Sub
    
    

The 'rstB' Property is declared as a 'DAO.Recordset' Object.

Through the Set Property Procedure, a Recordset object can be passed to the ClsRecUpdate Class Object.

The Update() Subroutine accepts three column numbers (0-based column indexes) as parameters to calculate and update the third column with the product of the 'first column' x 'second column'.

The DataSort() subroutine sorts the records in ascending order based on the Column Number passed as a parameter. 

The Sorting Column data type must be either Number, Currency, or String.  Other data types are ignored. The Recordset column numbers are 0-based, meaning the first column number is 0, the second column 1, and so on.

A listing of the records will be displayed in the Debug Window. The output will be limited to the first five fields; if the record source contains more than five fields, the remaining fields will be ignored.

The TblCreate() subroutine sorts the data based on the column number specified as a parameter and creates a new data table with a modified name. The parameter is optional; if no column number is specified, the data will be sorted by the first column (provided its data type is valid). The new table will retain the original table name with “_2” appended. For example, if the source table is namedTable1 The newly created table will be named Table1_2.

The Test Program for ClsUpdate.

Let us test the ClsRecUpdate Class Object with a small Program.

The test program code is given below:

Public Sub DataProcess()
Dim db As DAO.Database
Dim rstA As DAO.Recordset

Dim R_Set As ClsRecUpdate
Set R_Set = New ClsRecUpdate

Set db = CurrentDb
Set rstA = db.OpenRecordset("Table1", dbOpenTable)

'send Recordset Object to Class Object
Set R_Set.REC = rstA

'Update Total Price Field
Call R_Set.Update(1, 2, 3) 'col3=col1 * col2

'Sort Ascending Order on UnitPrice column & Print in Debug Window
Call R_Set.DataSort(2)

'Create New Table Sorted on UnitPrice in Ascending Order
Call R_Set.TblCreate(2) 
Set rstA = Nothing
Set db = Nothing
xyz:
End Sub

You may pass any Recordset to test the Class Object.

You can specify any column numbers when updating a particular column; they do not need to be consecutive. The third column number parameter identifies the target column to be updated. The result will be Column3 = Column1 * Column2.  You may modify the Class Module code to perform any other operation on the table as needed.

List of All the Links on this Topic.

  1. MS-Access Class Module and VBA
  2. MS-Access VBA Class Object Arrays
  3. MS-Access Base Class and Derived Objects
  4. VBA Base Class and Derived Objects-2
  5. Base Class and Derived Object Variants
  6. MS-Access Recordset and Class Module
  7. Access Class Module and Wrapper Classes
  8. Wrapper Class Functionality Transformation
  9. MS-Access and Collection Object Basics
  10. MS-Access Class Module and Collection Object
  11. Table Records in Collection Object and Form
  12. Dictionary Object Basics
  13. Dictionary Object Basics-2
  14. Sorting Dictionary Object Keys and Items
  15. Display Records from Dictionary to Form
  16. Add Class Objects as Dictionary Items
  17. Update Class Object Dictionary Item on Form
Share:

Base Class and Derived Object Variants

Base Class and Derived Object Variants.

Encapsulation of Objects.

Last week, we explored an example where a Base Class Object was passed through a Set Property Procedure, allowing it to become part of another object in memory. The passed object essentially became an extension or child object of the main object. In that earlier program, we passed the child object to the target object during the instantiation phase of our test program and then assigned values to the child object’s properties later in the code.

In the next example, we will take a slightly different approach.

For those who would like to go through the earlier Articles on the MS-Access Class Module, the links are given below:

This time, we will open both objects—ClsArea (the base class) and ClsVolume2 (the target class)—separately in our test program. We will assign values to the ClsArea base class properties before passing it to the ClsVolume2 target class object. Remember, the ClsVolume2 class has only one property, p_Height, and its Volume() method requires the Length and Width values from the base class ClsArea to calculate the volume.

  1. Copy and paste the following sample Test Code into a Standard Module.

    The SetNewVol2_2 Procedure.

    Public Sub SetNewVol2_2()
    'Method 2/2
    Dim CA As ClsArea
    Dim Vol As ClsVolume2
    
    Set CA = New ClsArea
    Set Vol = New ClsVolume2
    
    CA.strDesc = "Bed Room"
    CA.dblLength = 90
    CA.dblWidth = 10
    Stop
    
    
    'Here ClsArea class Object CA is passed to the 
    ‘Property procedure Set CArea of ClsVolume2 object Vol
    Set Vol.CArea = CA 'Pass ClsArea obj to ClsVolume2
    
    Vol.dblHeight = 10 'assign height to ClsVolume2
    
    
    Debug.Print "Description", "Length", "Width", "Area", "Height", "Volume"
    With Vol.CArea
      Debug.Print .strDesc, .dblLength, .dblWidth, .Area(), Vol.dblHeight, Vol.Volume()
    End With
    Stop
    
    Set CA = Nothing
    Set Vol = Nothing
    
    End Sub
    

    VBA Code Review.

    In the first Dim statement, CA is declared as a ClsArea object and Vol as a ClsVolume2 object. The next two statements instantiate these objects in memory.

    The following three statements assign values to the properties of the ClsArea object.

    A Stop statement is then used to pause code execution, allowing us to inspect the object property values in the Locals window.

    Next, the statement Set Vol.CArea = CA assigns the ClsArea object (CA) as a child object of the ClsVolume2 object (Vol).

    After that, the value 10 is assigned to the dblHeight property of the ClsVolume2 object.

    The subsequent statements, placed before the next Stop statement, print the property values from memory to the Debug window.

    Finally, the last two Set statements release both objects from memory before the program ends.

    Display the Locals Window.

  2. Inspecting the Locals Window

    1. Open the Locals Window
      From the View menu in the VBA Editor, select Locals Window.

    2. Run the Code

      • Click anywhere in the middle of the code window.

      • Press F5 to run the program until it pauses at the Stop statement.

      • Alternatively, press F8 to run the code step by step, which lets you observe the changes in the Locals Window at each step.

    3. Expand the Objects
      Click the [+] symbol next to the object names in the Locals Window to expand and display their properties and current values.

    4. Observe Object References

      • Check the CArea and p_Area object references under the Vol object.

      • At this point, their values will show as Nothing because we have not yet passed the CA object to the Vol object.

    5. Continue Running the Code

      • After reviewing the Locals Window, run the code until it pauses at the next Stop statement.

      • Now, the CArea Set Property Procedure assigns the p_Area object reference to the ClsArea object, linking it into the ClsVolume2 object.

    Next, we will try another variation of this example using the same two classes — ClsArea and ClsVolume2 — to demonstrate a slightly different approach.

New Class Module: ClsVolume3.

1.  Insert a new Class Module and change its name Property Value to ClsVolume3.

2.  Copy and Paste the following VBA Code into the ClsVolume3 Class Module:

Option Compare Database
Option Explicit
'Method three 
Private p_Height As Double
Public p_Area As ClsArea

Public Property Get dblHeight() As Double
    dblHeight = p_Height
End Property

Public Property Let dblHeight(ByVal dblNewValue As Double)
    p_Height = dblNewValue
End Property

Public Function Volume() As Double
    Volume = p_Area.dblLength * p_Area.dblWidth * Me.dblHeight
End Function

Private Sub Class_Initialize()
    Set p_Area = New ClsArea
End Sub

Private Sub Class_Terminate()
    Set p_Area = Nothing
End Sub

In the code, p_Height is declared as a Private Property, while p_Area is declared as a public ClsArea object within the ClsVolume3 class. This means p_Area appears as a property of the ClsVolume3 class, with its own accessible properties and methods for direct Get/Let operations in the user program (from a standard module). Although the ClsArea object is exposed as a public property of ClsVolume3, its internal properties and methods remain encapsulated within the ClsArea class itself.

It is important to ensure that the ClsArea class is fully developed and free of errors before it is encapsulated into other classes.

The Class_Initialize() and Class_Terminate() routines handle the lifecycle of the embedded object: The ClsArea object is instantiated in Class_Initialize() when a ClsVolume3 object is created, and released from memory in Class_Terminate() When the user program ends.

The Testing Program.

The sample Test VBA Code is given below.

Copy and paste the code into the Standard Module.

Public Sub SNewVol3()
'Here ClsArea class is declared as a Public Property of ClsVolume3
Dim volm As ClsVolume3

Set volm = New ClsVolume3

volm.p_Area.strDesc = "Bed Room"
volm.p_Area.dblLength = 15 'assign length
volm.p_Area.dblWidth = 10 'assign width in clsArea
volm.dblHeight = 10 'assign height to ClsVolume2

Debug.Print "Description", "Length", "Width", "Area", "Height", "Volume"
With volm.p_Area
   Debug.Print .strDesc, .dblLength, .dblWidth, .Area, volm.dblHeight, volm.Volume
End With
Set volm = Nothing

End Sub

Display the Locals Window (View -> Locals Window), if it is not already open.

Click somewhere in the middle of the code, and press F8 to execute the VBA Code one line at a time and watch the Locals Window to track what happens at each step.

All the above variants of the ClsVolume Class have been written with less Code, except the ClsVolume Class.  

Working with the Recordset Object.

Next week, we will work with a built-in Object 'DAO.Recordset' and build a Class Module to:

  1. Calculate and update a Field,

  2. Sort the Data,

  3. Print the sorted data in the Debug Window,

  4. And create a Clone of the Table with the data sorted.

That is a lot of action next week.

List of All the Links on this Topic.

  1. MS-Access Class Module and VBA
  2. MS-Access VBA Class Object Arrays
  3. MS-Access Base Class and Derived Objects
  4. VBA Base Class and Derived Objects-2
  5. Base Class and Derived Object Variants
  6. MS-Access Recordset and Class Module
  7. Access Class Module and Wrapper Classes
  8. Wrapper Class Functionality Transformation
  9. MS-Access and Collection Object Basics
  10. MS-Access Class Module and Collection Object
  11. Table Records in Collection Object and Form
  12. Dictionary Object Basics
  13. Dictionary Object Basics-2
  14. Sorting Dictionary Object Keys and Items
  15. Display Records from Dictionary to Form
  16. Add Class Objects as Dictionary Items
  17. Update Class Object Dictionary Item on Form

Share:

VBA Base Class and Derived Object-2

VBA Base Class and Derived Object-2.

Object Encapsulation-2.

Last week, we created a derived Class, 'lsVolume', using ClsArea as the base class. In that approach, we added property procedures in the derived class to expose the base class’s properties and functions to the user programs. This method, however, requires repeating the base class property procedures in the derived class.

In this section, we will explore how to create the same derived ClsVolume class without duplicating the property procedures of the ClsArea base class.

So far, we have learned about Get and Let property procedures in classes. There is also a third type: the Set Property Procedure, which is used to directly assign an object to a class object of the same type.

Before proceeding, you may want to revisit the earlier pages on this topic if you haven’t already. Links are provided below:


ClsVolume Class, the Makeover.

We shall create a different variant of the same ClsVolume Class Module we created last week, using ClsArea as the base class, with a different approach and less Code. 

Create a new Class Module and change its Name Property Value to ClsVolume2.

Copy and Paste the following Code into the Class Module ClsVolume2 and Save the Module:

Option Compare Database
Option Explicit
'Method two-1
Private p_Height As Double
Private p_Area As ClsArea

Public Property Get dblHeight() As Double
    dblHeight = p_Height
End Property

Public Property Let dblHeight(ByVal dblNewValue As Double)
    p_Height = dblNewValue
End Property

Public Function Volume() As Double
    Volume = p_Area.dblLength * p_Area.dblWidth * p_Height
End Function

'The new Get and Set Property Procedure for the ClsArea Object.

Public Property Get CArea() As ClsArea
   Set CArea = p_Area
End Property

Public Property Set CArea(ByRef AreaValue As ClsArea)
  Set p_Area = AreaValue
End Property

From the Debug menu, select Compile [Project Name] to compile all the VBA code in your database and ensure it is error-free. If errors in other VBA programs, locate and correct them, then recompile the project.

While unresolved errors will not prevent you from assigning or retrieving values from object properties, the VBA IntelliSense—which displays a list of an object’s properties and functions—will not work properly until the project compiles successfully.

Seeing the property list appear in IntelliSense is an invaluable aid during coding, especially while learning and experimenting with class objects.

Get / Set instead of the Get / Let Property Procedure.

In this version of the ClsVolume class, we have omitted all the property procedures  ClsArea that were present in the previous version. Instead, we use Get and Set property procedures rather than the traditional Get/Let pair.

Take a look at the declaration: the private member p_Area is declared as a ClsArea class object. Normally, when an object is declared this way, we would create an instance of it in the Class_Initialize() procedure.

However, in this approach, we have not instantiated it within the class. The plan is to create and populate the ClsArea object in the user program, set its properties with appropriate values, and then pass it to the ClsVolume2 class. The class will then use these values during the final calculation phase.

Take note of the Set CArea() procedure. Its ByRef parameter, AreaValue, is declared as a ClsArea object. When an ClsArea instance is passed to this property procedure, the object variable AreaValue receives it and assigns it to the private p_Area property of the ClsVolume2 object.

This mechanism allows the ClsVolume2 class to use an externally created and populated ClsArea object without having to instantiate it internally, maintaining flexibility and reusability.

The Get CArea() Property procedure returns the Object to the calling program.

In our earlier programs, we wrote property procedures for individual elements of an object, such as Length, Width, and Height—to assign or retrieve values. In this version, the difference is that we are passing an entire object as a parameter to a Set property procedure.

To access a property of this passed object—for example, dblLength—we use the syntax CArea.dblLength. Here, the Get/Set property procedure name CArea essentially becomes a child object of the main object when declared in the main program. Its individual properties can then be accessed directly using the object address, such as:

Vol.CArea.dblLength

This approach allows the main object to interact with the entire child object and its properties as a single unit, simplifying property management and enhancing reusability.

A Test Program in a Standard Module.

We will now create a small test program in a Standard Module to verify the functionality of our newly derived class object. ClsVolume2.

  1. Insert a new Standard Module into your project.

  2. Copy and paste the following code into the module.

  3. Save the module before running the program.

Public Sub SetNewVol2_1()
'Method 1/2
Dim Vol As New ClsVolume2

'ClsArea Object instantiated and passed to the
'Property Procedure Set CArea in ClsVolume2.

Set Vol.CArea = New ClsArea 'declare and instantiate the object in one statement

Stop

Vol.CArea.strDesc = "Bed Room"
Vol.CArea.dblLength = 90
Vol.CArea.dblWidth = 10

Vol.dblHeight = 10 'assign height to ClsVolume2

Stop

Debug.Print "Description", "Length", "Width", "Area", "Height", "Volume"
Debug.Print Vol.CArea.strDesc, Vol.CArea.dblLength, Vol.CArea.dblWidth, Vol.CArea.Area, Vol.dblHeight, Vol.Volume

Set Vol.CArea = Nothing
Set Vol = Nothing

End Sub

Code Review Line by Line.

Let’s quickly review the VBA code above.

  1. The first line instantiates the ClsVolume2 class with the object name Vol.

  2. After the comment lines, the Set Vol.CArea statement calls the property procedure and passes the newly instantiated ClsArea object as its parameter.

I included a Stop statement on the next line to pause the program so you can observe how the object is assigned to the CArea property. We’ll explore how to inspect this in memory shortly.

  1. The following four lines assign values to the ClsArea object properties (strDesc, dblLength, dblWidth) and to the dblHeight property of the ClsVolume2 object.

  2. The next Stop statement pauses the program again, allowing you to inspect how these values are stored in memory.

  3. The subsequent line prints the headings in the Debug Window for clarity.

  4. Finally, the last line prints the values of the object properties retrieved from memory, displaying them in the Debug Window.

Run the Code to the Next Stop Statement

  1. Let’s run the code and inspect the memory to see what happens at each stage where the Stop statements are placed.

    1. Click anywhere in the code and press F5 to run the program. The execution will pause at the first Stop statement.

    2. From the View menu, select Locals Window. This opens a window below the code editor that displays the ClsArea and ClsVolume2 objects, along with their properties and member procedures, as they are stored in memory.

    3. Observe the structure of the objects and how the property values are held. A sample image of the Locals Window is shown below for reference.

    The Locals Window View.


    To give more space for the Locals Window, drag the sizing handles of other windows upward to reduce their height. Alternatively, you can close the Debug Window and press Ctrl+G to bring it back when needed.

    The Locals Window provides a graphical view of all objects and their properties in memory:

    1. The first item with a plus [+] symbol shows the name of the Standard Module the program is running.

    2. The next plus [+] symbol represents the Vol object, which is the instantiated ClsVolume2 object in memory.

    Click the plus [+] symbols to expand each item and display detailed information about the object’s properties and member procedures.

    You will find the next level of Objects and Properties.

    The [+]CArea indicates that this Object has the next level of Properties and their Values.

    The dblHeight Get property Procedure comes directly under the Vol Object.

    The [+]p_Area is the Private Property declared in the ClsArea Class in the ClsVolume2 Class.

    The p_Height is also declared as a private property in ClsVolume2.

    Click the plus [+] symbols to expand the objects to show their Properties and Values.

    Expanding the [+] CArea node displays the ClsArea object that was passed to the Set CArea() property procedure.

    The expansion of the [+] p_Area view of the ClsArea Property declared as Private.

    Note that the p_Area Private Property of the ClsVolume2 Class Object, and all its elements, are accessible only through the CArea Object Property Get/Set Procedures to the outside world.

    The second column in the Locals Window displays the values assigned to the object’s properties. At this stage, no values have been assigned, so the fields are currently empty.

    The Third Column shows the Data Type or Object Class Module Names.

    Press F5 to run the program till it pauses at the next Stop statement, after assigning some values to the Object Properties.  The program pauses at the Stop statement.  Check the Locals Window for changes in Values.

    In the CArea object, the first two values (90 and 10) and the final `strDesc` variable with the value `"Bedroom"` are assigned via their respective `Get Property` procedures. Likewise, `p_Desc`, `p_Length`, and `p_Width` are assigned through the corresponding `Set Property` procedures to the `p_Area` property of the `ClsVolume2` class object. 

    The p_Area Object of the ClsArea Class is declared as the Private Property of ClsVolume2 and is seen with its Get/Set Property Procedures and assigned values.

    Check the Type Column of [-]CArea and [-]p_Area; both Objects are derived from the ClsArea Base Class.

    Usage of ClsArea and ClsVolume2 Class Objects Differently.

    Next week, we will explore another approach using the same two objects.

    If you’d like to experiment on your own beforehand, here’s a clue to get you started:

    1. Instantiate the ClsVolume2 and ClsArea classes as two different Objects in the Standard Module Program.

    2. Assign values to both Object Properties.

    3. Assign the ClsArea Class Object instantiated in the CArea object to the ClsVolume2 Class Object before printing the Values to the Debug Window.

    In this example, we can achieve the same result as in the previous example without having to repeat the Get/Let property procedures in the ClsVolume class module.

    The Links of All the Pages in this Topic.

    1. MS-Access Class Module and VBA
    2. MS-Access VBA Class Object Arrays
    3. MS-Access Base Class and Derived Objects
    4. VBA Base Class and Derived Objects-2
    5. Base Class and Derived Object Variants
    6. MS Access Recordset and Class Module
    7. Access Class Module and Wrapper Classes
    8. Wrapper Class Functionality Transformation
    9. MS Access and Collection Object Basics
    10. MS Access Class Module and Collection Object
    11. Table Records in Collection Object and Form
    12. Dictionary Object Basics
    13. Dictionary Object Basics-2
    14. Sorting Dictionary Object Keys and Items
    15. Display Records from Dictionary to Form
    16. Add Class Objects as Dictionary Items
    17. Add Class Objects as Dictionary Items
    18. Update Class Object Dictionary Item on Form

Share:

PRESENTATION: ACCESS USER GROUPS (EUROPE)

Translate

PageRank

Post Feed


Search

Popular Posts

Blog Archive

Powered by Blogger.

Labels

Forms Functions How Tos MS-Access Security Reports msaccess forms Animations msaccess animation Utilities msaccess controls Access and Internet MS-Access Scurity MS-Access and Internet External Links Queries Array Class Module msaccess reports Accesstips msaccess tips WithEvents Downloads Objects Menus and Toolbars MsaccessLinks Process Controls Art Work Collection Object Property msaccess How Tos Combo Boxes ListView Control Query VBA msaccessQuery Calculation Dictionary Object Event Graph Charts ImageList Control List Boxes TreeView Control Command Buttons Controls Data Emails and Alerts Form Custom Functions Custom Wizards DOS Commands Data Type Key Object Reference ms-access functions msaccess functions msaccess graphs msaccess reporttricks Command Button Report msaccess menus msaccessprocess security advanced Access Security Add Auto-Number Field Type Form Instances ImageList Item Macros Menus Nodes Recordset Top Values Variables msaccess email progressmeter Access2007 Copy Excel Expression Fields Join Methods Microsoft Numbering System RaiseEvent Records Security Split SubForm Table Tables Time Difference Utility WScript Workgroup Wrapper Classes database function msaccess wizards tutorial Access Emails and Alerts Access Fields Access How Tos Access Mail Merge Access2003 Accounting Year Action Animation Attachment Binary Numbers Bookmarks Budgeting ChDir Color Palette Common Controls Conditional Formatting Data Filtering Database Records Defining Pages Desktop Shortcuts Diagram Disk Dynamic Lookup Error Handler Export External Filter Formatting Groups Hexadecimal Numbers Import Labels List Logo Macro Mail Merge Main Form Memo Message Box Monitoring Octal Numbers Operating System Paste Primary-Key Product Rank Reading Remove Rich Text Sequence SetFocus Summary Tab-Page Union Query User Users Water-Mark Word automatically commands hyperlinks iSeries Date iif ms-access msaccess msaccess alerts pdf files reference restore switch text toolbar updating upload vba code