Learn Microsoft Access Advanced Programming Techniques, Tips and Tricks.

Update Class Object Dictionary Item through Form

Introduction

Last week we did a trial run for adding/retrieving Class Objects into/from Dictionary Object Items.  One important point we have highlighted there was that each Class Object Item added to the Dictionary Object must be a new instance of the Class Object, every time.  

This is not peculiar to Class Object or Dictionary Object alone.  This method must be followed to avoid inadvertent loss of important data while adding Objects to a Collection, Dictionary, or to the Array of an object itself.  A review of the procedure, in brief, is given below:@@@

  1. Create a temporary Object instance (Set tmpObj = New Object)

  2. Assign Values to the temporary Object instance’s properties.

  3. Add the temporary Object instance, as Dictionary Object Item or Collection Object Item or as the Object’s declared Array element.

  4. Remove the temporary Object instance (Set tmpObj = Nothing) from memory.

  5. To add more items repeat steps 1 to 4.

If you would like to know why we can’t use only one instance of the Class Object to add several Items to the Dictionary Object, visit the page Add Class Object as Dictionary Object Items?

Class Object Instances as Dictionary Items

Now, let us get ourselves prepared for a trial run to Add, Edit, Update, and Delete Class Object Items in Dictionary Object, through Ms-Access Form.  We worked with Form and Dictionary Object about two weeks back, for adding and retrieving simple items in Dictionary Object. 

This time we are dealing with Objects and Properties in Dictionary Objects, not simple Items, with added data management functions.  Besides that, when the Form is closed the Dictionary Item Values (ClsArea Class Object Property Values) are saved to a Table.

We will use our simple ClsArea Class Object, with only three Property Values to fill in (Description, Length, and Width Values), for our trial run.

Even though the Table is used only at the end of the session we will design the simple table first with the fields: Description (strDesc), Length (dblLength), and Width (dblWidth) matching the Class Module ClsArea Object Property Names in brackets.

  1. Create a new Table with the name ClsArea with the Field Names and Field Types shown in the Table Design Image shown below. For Numeric Data Fields select Double Precision Number Type.
  2. Next, we need a Form with the following design to manage the data of Dictionary Object.

  3. Design a Form with the following Controls (not bound to the Table.):

    • Combo Box on the Header:

      Name Property Value: cboKey

      Row Source Type = Value List

    • Four Unbound Text Boxes in the Detail Section of the Form with the following names:

      strDesc

      dblLength

      dblWidth

      Area

    • Create another TextBox to the right of the last TextBox with the Name:

      ItemCount

    • Create three Command Buttons below the Text Boxes, on the Detail Section, with the Names:

      cmdAdd and Caption: Add

      cmdEdit and Caption: Edit

      cmdDelete and Caption: Delete

    • Create two Command Buttons in the Footer Section of the Form with the Names:

      cmdSave and Caption: Save to Table

      cmdExit and Caption: Exit

  4. The Form’s Normal View Image, with some sample data, is given below:

As the Form control names suggest we can key in Property Values of ClsArea Class Object and add the Class Object to Dictionary Object, as its Item.  The strDesc Property Value will be used as Dictionary Key.  Ensure that while Keying in data the Description Field Value must be unique among all items, otherwise, it will not accept in the Dictionary Object and will end up with Errors.  I have avoided extensive validation checks in the Code, to maintain the code as simple as possible.

A particular class Object’s property values can be retrieved from Dictionary Object, using the Key-Value selected from the cboKey Combo Box, edit the values on the Form and Update the changes back into the Dictionary. If it is an unwanted item, then it can be deleted from Dictionary Object.

The Form Module Event Procedures.

There are several Event Procedures behind the Form’s Class Module and a brief explanation is given under each Procedure given below. 

Option Compare Database
Option Explicit

Dim C As ClsArea, xC As ClsArea
Dim D As Object, Desc As String
Dim editFlag As Boolean, saveFlag As Boolean
Dim strV As String

All important Objects and Variables are declared at the Global declaration area.

Private Sub Form_Load()

Private Sub Form_Load()
    Set D = CreateObject(“Scripting.Dictionary)
    Me.cmdEdit.Enabled = False
    Me.cmdDelete.Enabled = False
    saveFlag = False
End Sub

At the Form Load Event, the Dictionary Object is instantiated.

Edit and Delete Command Buttons are disabled because the Form will be in data entry mode by default.  Data save detection flag saveFlag is set to false. The flag will be set to True when the Dictionary Data is saved to the Table, from one of two possible selections of Command Buttons at the Footer of the Form.

Private Sub Form_Current()

Private Sub Form_Current()
Dim o As String
    o = cboKeys.RowSource
    If Len(o) = 0 Then
       Me.cboKeys.Enabled = False
    Else
       Me.cboKeys.Enabled = True
    End If
End Sub

Checks whether the Combo box's Row Source property has any Value in it (when the Form is open, it will be empty), if not disable Combo box Control.

Private Sub strDesc_GotFocus()
Private Sub strDesc_GotFocus()
 If editFlag Then
  Me.cmdAdd.Enabled = False
  Me.cmdEdit.Enabled = True
  Me.cmdDelete.Enabled = True
 Else
  Call initFields
  Me.cmdAdd.Enabled = True
  Me.cmdEdit.Enabled = False
  Me.cmdDelete.Enabled = False
  editFlag = False
 End If

End Sub

Checks whether the form is in Edit mode or not.  Edit Mode Flag is set when the user clicks the Edit Command Button.  This happens after the user selects an item from the Combobox.

If in edit mode, then the data entry fields are not cleared, Edit and Delete Command Buttons are enabled, Add Command Button is disabled.

If in Add mode, then data fields are emptied in preparation for a new Item, Add Command Button is enabled, and the Edit and Delete Command Buttons are disabled.

Private Sub dblWidth_LostFocus()

Private Sub dblWidth_LostFocus()
'Area is displayed for info purpose only
  Me!Area = Nz(Me!dblLength, 0) * Nz(Me!dblWidth, 0)
End Sub

On the dblWidth Text Box's LostFocus Event the product of dblLength * dblwidth is displayed in the Area Text Box.

Private Sub cmdAdd_Click()

Private Sub cmdAdd_Click()
'--------------------------------------------------
'1. Add Class Object as Item to Dictionary Object
'2. Update Combobox RowSource Property
'--------------------------------------------------
Dim tmpstrC As String, tmpLength As Double, tmpWidth As Double
Dim flag As Integer, msg As String
Dim cboVal As String, cbo As ComboBox

editFlag = False
Set cbo = Me.cboKeys

tmpstrC = Nz(Me!strDesc, "")
tmpLength = Nz(Me!dblLength, 0)
tmpWidth = Nz(Me!dblWidth, 0)

flag = 0
If Len(tmpstrC) = 0 Then flag = flag + 1
If tmpLength = 0 Then flag = flag + 1
If tmpWidth = 0 Then flag = flag + 1
If flag > 0 Then
   msg = "Invalid Data in one or more fields, correct them and retry."
   MsgBox msg, , "cmdAdd()"
   Exit Sub
End If

Desc = ""
Set C = New ClsArea 'create a new instance
'add Property Values
    C.strDesc = tmpstrC
    C.dblLength = tmpLength
    C.dblWidth = tmpWidth
    
'add Class Object instance to Dictionary
    
    D.Add tmpstrC, C 'Description is the Key
    
    Call comboUpdate(tmpstrC) 'update description as combobox item
       
    Me.ItemCount = D.Count 'display dictionary Items count
    
    'Call initFields 'set all fields to blanks
    Me.strDesc.SetFocus 'make description field current
    
'Clear Class Object
    Set C = Nothing

End Sub

The TextBox values are transferred into temporary variables and checked whether any text box is empty or not.

The ClsArea Class Object Properties are assigned with strDesc, dblLength & dblwidth text box values, from temporary variables.

Adds Class Object to Dictionary Object.

Updates Combo Box with the Dictionary Object Key, from Class Object's Description (strDesc) Value.

The Dictionary Items Count is displayed on ItemCount Text Box.

The focus is set in the strDesc field, by which the text boxes are cleared to enter new values to add.

Private Sub cboKeys_AfterUpdate()

Private Sub cboKeys_AfterUpdate()
On Error Resume Next

strV = Me!cboKeys
Set xC = D(strV)
If Err > 0 Then
   MsgBox "Item for Key: " & strV & " Not Found!"
   Exit Sub
End If

Me!strDesc = xC.strDesc
Me!dblLength = xC.dblLength
Me!dblWidth = xC.dblWidth
Me!Area = xC.Area

Me.cmdAdd.Enabled = False
Me.cmdEdit.Enabled = True
Me.cmdDelete.Enabled = True
Me.strDesc.Enabled = False

On Error GoTo 0

End Sub

Retrieving the Dictionary Item

After adding several items to the Dictionary Object you may retrieve an Item from Dictionary Object and display the details on Form, by selecting the Dictionary Key Item from the Combo Box. The Add Command Button will be disabled. The strDesc Field will be disabled. Will unlock it only if you click on the Edit Button.

If you select an invalid Key (the Key value changed during earlier edit operations) from Combobox,  then an error message: 'Item for Key: XXXX. Not Found' will be displayed, indicating that the item doesn't exist in Dictionary Object.

Private Sub cmdEdit_Click()

Private Sub cmdEdit_Click()
'Edit the displayed item properties
Dim cap As String
Dim mDesc As String

editFlag = True

strV = Me!cboKeys

cap = Me.cmdEdit.Caption
Select Case cap
   Case "Edit"
      Me.strDesc.Enabled = True
      Me.cmdAdd.Enabled = False 'when editing Add button is disabled
      Me.cmdEdit.Caption = "Update" 'Edit Button Caption is changed
      
   Case "Update" 'Button clicked when Caption is Update
   'directly replace the property value in the Item
      xC.strDesc = Me!strDesc
      xC.dblLength = Me!dblLength
      xC.dblWidth = Me!dblWidth
      mDesc = Me!strDesc 'changed Description is copied to mDesc
      
   If mDesc <> strV Then 'checks with key in combobox value if not same then
      D.Key(strV) = mDesc 'Change Dictionary Key of Item
      
      'update new desc to Combobox
      'old desc also remains in combobox
      Call comboUpdate(mDesc)
   End If
      Call initFields
      Me.strDesc.SetFocus
      Me.cmdAdd.Enabled = True 'Enable Add button to add new item
      Me.cmdEdit.Caption = "Edit" 'change caption from Update to Edit
      Me.cmdEdit.Enabled = False 'disable Edit Button
      Me.cmdDelete.Enabled = False 'disable Edit Button
End Select

End Sub

Editing Dictionary Item

The item brought from Dictionary to Form can be edited by clicking on the Edit Command Button. The Caption of the Edit Command Button will change to Update when you click on it.

Make any changes, including the Description (if necessary) then Click Edit Button again (with Caption Update) second time to update the change back into Dictionary Object.

If strDesc (The Key value in the Dictionary) is changed, then the Dictionary Object Item's corresponding old Key is updated with the new Description Value. The Combobox will be updated with the new Key,  but, the old Key is not deleted from the ComboBox.

Data fields are cleared, Add Command Button is enabled, Edit and Delete buttons are disabled.

Private Sub cmdDelete_Click()

Private Sub cmdDelete_Click()p
Dim txtKey As String, msg As String

txtKey = Me!cboKeys
msg = "Delete Object with Key: " & txtKey & " ..?"
If MsgBox(msg, vbYesNo + vbDefaultButton2 + vbCritical) = vbYes Then
   D.Remove (txtKey) 'Remove the Item matching the Key
   
   MsgBox "Item Deleted."
   
   Call initFields
   
   Me.strDesc.Enabled = True
   Me.strDesc.SetFocus 'make description field current
   Me.ItemCount = D.Count 'display items count
   Me.cmdAdd.Enabled = True
   Me.cmdEdit.Enabled = False
   Me.cmdDelete.Enabled = False
   
End If

End Sub

Deleting Dictionary Item

When Delete Command Button is clicked, the current Item on the Form is deleted from the Dictionary, after the user reconfirms it.

The data entry fields are cleared, and the item count control is updated with the reduced number of items.

Private Sub cmdSave_Click()

Private Sub cmdSave_Click()
Dim msg As String

msg = "Form will be closed After Saving Data,"
msg = msg & vbCr & "Proceed...?"
If MsgBox(msg, vbYesNo + vbDefaultButton2 + vbInformation, "cmdSave_Click()") = vbNo Then
  Exit Sub
Else
  Call Save2Table
  DoCmd.Close
End If

End Sub
 

Saving Data from the Dictionary Object.

When you have finished working with the Form and want to Save the Dictionary Data ClsArea Class’s property values from Dictionary to the temporary Table (clsArea) and to Close the Form, click on the 'Save to Table' Command Button.

Private Sub cmdExit_Click()

Private Sub cmdExit_Click()
Dim msg As String
If saveFlag Then
    DoCmd.Close
Else
    msg = "Dictionary Data Not saved in Table!"
    msg = msg & vbCr & vbCr & "Click Cancel to Go back"
    msg = msg & vbCr & vbCr & "Click OK to discard Data and close the Form!"
    If MsgBox(msg, vbOKCancel + vbDefaultButton2 + vbQuestion, "cmdExit()") = vbOK Then
        DoCmd.Close
    Else
        Call Save2Table
        DoCmd.Close
    End If
End If
End Sub

If you choose to click on the Exit Command Button, rather than the ‘Save to Table’ Command Button, here also you are reminded to save the data. If you don't want to save then you may select the appropriate option to close the Form, without saving the data in Table.

There are a few common Sub-Routines,  called from more than one event Procedure and their Codes are added to the Full listing of the Code given below.

Private Sub initFields() all text boxes on the Form are cleared when called from Event Procedures.

Private Sub comboUpdate(ByVal stDesc As String) Called from cmdAdd_Click() and cmdEdit_Click() Event Procedures.

Private Sub Save2Table() Called from cmdSave_Click() and cmdExit_Click() Event Procedures.

The Form's Class Module Code.

Highlight, Copy, and Paste the Entire Code, given below, in the Form's Class Module of your Form. Save the Form with the name frmDictionary.

Option Compare Database
Option Explicit

Dim C As ClsArea, xC As ClsArea
Dim D As Object, Desc As String
Dim editFlag As Boolean, saveFlag As Boolean
Dim strV As String

Private Sub Form_Load()
    Set D = CreateObject(“Scripting.Dictionary”)
    Me.cmdEdit.Enabled = False
    Me.cmdDelete.Enabled = False
    saveFlag = False
End Sub

Private Sub Form_Current()
Dim o As String
o = cboKeys.RowSource
If Len(o) = 0 Then
  Me.cboKeys.Enabled = False
Else
  Me.cboKeys.Enabled = True
End If
End Sub


Private Sub cboKeys_AfterUpdate()
On Error Resume Next

strV = Me!cboKeys
Set xC = D(strV)
If Err > 0 Then
   MsgBox "Item for Key: " & strV & " Not Found!"
   Exit Sub
End If

Me!strDesc = xC.strDesc
Me!dblLength = xC.dblLength
Me!dblWidth = xC.dblWidth
Me!Area = xC.Area

Me.cmdAdd.Enabled = False
Me.cmdEdit.Enabled = True
Me.cmdDelete.Enabled = True
Me.strDesc.Enabled = False

On Error GoTo 0

End Sub

Private Sub cmdAdd_Click()
'--------------------------------------------------
'1. Add Class Object as Item to Dictionary Object
'2. Update Combobox RowSource Property
'--------------------------------------------------
Dim tmpstrC As String, tmpLength As Double, tmpWidth As Double
Dim flag As Integer, msg As String
Dim cboVal As String, cbo As ComboBox

editFlag = False
Set cbo = Me.cboKeys

tmpstrC = Nz(Me!strDesc, "")
tmpLength = Nz(Me!dblLength, 0)
tmpWidth = Nz(Me!dblWidth, 0)

flag = 0
If Len(tmpstrC) = 0 Then flag = flag + 1
If tmpLength = 0 Then flag = flag + 1
If tmpWidth = 0 Then flag = flag + 1
If flag > 0 Then
   msg = "Invalid Data in one or more fields, correct them and retry."
   MsgBox msg, , "cmdAdd()"
   Exit Sub
End If

Desc = ""
Set C = New ClsArea 'create a new instance
'add Property Values
    C.strDesc = tmpstrC
    C.dblLength = tmpLength
    C.dblWidth = tmpWidth
    
'add Class Object instance to Dictionary
    
    D.Add tmpstrC, C 'Description is the Key
    
    Call comboUpdate(tmpstrC) 'update description as combobox item
       
    Me.ItemCount = D.Count 'display dictionary Items count
    
    'Call initFields 'set all fields to blanks
    Me.strDesc.SetFocus 'make description field current
    
'Clear Class Object
    Set C = Nothing

End Sub

Private Sub cmdDelete_Click()
Dim txtKey As String, msg As String

txtKey = Me!cboKeys
msg = "Delete Object with Key: " & txtKey & " ..?"
If MsgBox(msg, vbYesNo + vbDefaultButton2 + vbCritical) = vbYes Then
   D.Remove (txtKey) 'Remove the Item matching the Key
   
   MsgBox "Item Deleted."
   
   Call initFields
   
   Me.strDesc.Enabled = True
   Me.strDesc.SetFocus 'select description field current
   Me.ItemCount = D.Count 'display items count
   Me.cmdAdd.Enabled = True
   Me.cmdEdit.Enabled = False
   Me.cmdDelete.Enabled = False
   
End If

End Sub

Private Sub cmdEdit_Click()
'Edit the displayed item properties
Dim cap As String
Dim mDesc As String

editFlag = True

strV = Me!cboKeys

cap = Me.cmdEdit.Caption
Select Case cap
   Case "Edit"
      Me.strDesc.Enabled = True
      Me.cmdAdd.Enabled = False 'when editing Add button is disabled
      Me.cmdEdit.Caption = "Update" 'Edit Button Caption is changed
      
   Case "Update" 'Button clicked when Caption is Update
   'directly replace the property value in the Item
      xC.strDesc = Me!strDesc
      xC.dblLength = Me!dblLength
      xC.dblWidth = Me!dblWidth
      mDesc = Me!strDesc 'changed Description is copied to mDesc
      
   If mDesc <> strV Then 'checks with key in combobox value if not same then
      D.Key(strV) = mDesc 'Change Dictionary Key of Item
      
      'update new desc to Combobox
      'old desc also remains in combobox
      Call comboUpdate(mDesc)
   End If
      Call initFields
      Me.strDesc.SetFocus
      Me.cmdAdd.Enabled = True 'Enable Add button to add new item
      Me.cmdEdit.Caption = "Edit" 'change caption from Update to Edit
      Me.cmdEdit.Enabled = False 'disable Edit Button
      Me.cmdDelete.Enabled = False 'disable Edit Button
End Select

End Sub

Private Sub cmdExit_Click()
Dim msg As String
If saveFlag Then
    DoCmd.Close
Else
    msg = "Dictionary Data Not saved in Table!"
    msg = msg & vbCr & vbCr & "Click Cancel to Go back"
    msg = msg & vbCr & vbCr & "Click OK to discard Data and close the Form!"
    If MsgBox(msg, vbOKCancel + vbDefaultButton2 + vbQuestion, "cmdExit()") = vbOK Then
        DoCmd.Close
    Else
        Call Save2Table
        DoCmd.Close
    End If
End If
End Sub

Private Sub cmdSave_Click()
Dim msg As String

msg = "Form will be closed After Saving Data,"
msg = msg & vbCr & "Proceed...?"
If MsgBox(msg, vbYesNo + vbDefaultButton2 + vbInformation, "cmdSave_Click()") = vbNo Then
  Exit Sub
Else
  Call Save2Table
  DoCmd.Close
End If

End Sub

Private Sub Save2Table()
Dim db As Database, rst As Recordset
Dim recCount As Long, j As Long, item

On Error GoTo Save2Table_Error

recCount = D.Count

Set db = CurrentDb
Set rst = db.OpenRecordset("ClsArea", dbOpenTable)
For Each item In D.Items
   With rst
        .AddNew
         !strDesc = item.strDesc
         !dblLength = item.dblLength
         !dblWidth = item.dblWidth
        .Update
    End With
Next

rst.Close
Set rst = Nothing
Set db = Nothing

saveFlag = True
MsgBox "Data Saved  to Table: ClsArea"

Save2Table_Exit:
Exit Sub

Save2Table_Error:
MsgBox Err & ":" & Err.Description, , "Save2Table_Click()"
Resume Save2Table_Exit

End Sub

Private Sub Form_Unload(Cancel As Integer)
Set D = Nothing
End Sub

Private Sub strDesc_GotFocus()
    If editFlag Then
        Me.cmdAdd.Enabled = False
        Me.cmdEdit.Enabled = True
        Me.cmdDelete.Enabled = True
    Else
        Call initFields
        Me.cmdAdd.Enabled = True
        Me.cmdEdit.Enabled = False
        Me.cmdDelete.Enabled = False
        editFlag = False
    End If

End Sub


Private Sub dblWidth_LostFocus()
'Area is displayed for info purpose only
  Me!Area = Nz(Me!dblLength, 0) * Nz(Me!dblWidth, 0)
End Sub

Private Sub initFields()
'Empty all fields
    Me!strDesc = Null
    Me!dblLength = Null
    Me!dblWidth = Null
    Me!Area = Null
    Me.cmdAdd.Enabled = True
End Sub

Private Sub comboUpdate(ByVal stDesc As String)
Dim cbo As ComboBox, cboVal As String
Set cbo = Me.cboKeys
    cboVal = cbo.RowSource
    cboVal = cboVal & ";" & stDesc
    cbo.RowSource = cboVal
    cbo.Requery
    If Len(cboVal) > 0 Then
      Me.cboKeys.Enabled = True
    End If
End Sub

Perform a Demo Run.

  1. Open the Form frmDictionary and try out adding a few entries into the Dictionary Object.

  2. Select an item from the Combo Box to display the Property Values of the corresponding Class Object.

  3. Click on Edit Command Button, and make some changes to the Description, Length, and Width Values.

  4. Click on Edit Command Button again (with the caption Update) to write the changes back into the Dictionary Object.  If you click on the Combobox you can see the item with the changed description and the old description of the item.

  5. Select the old description from the Combo Box. You will get an error message saying that the item doesn’t exist because the Dictionary Key of the Item is updated with a changed value.

  6. Select an item from the Combo Box and Click on the Delete Command Button to delete the item displayed on the Screen.

Tried to keep the Event Procedure Code simple, avoiding Validation checks on input values,  error trap routines, or safeguarding other side effects of user activities on the Form.

You may improve the Code if the need arises and use it for your own Projects.

Downloads

You may download this demo database from the link given below.

Download Dictionary_2003.zip

Download Dictionary_2007.zip


MS-ACCESS CLASS MODULE

  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

    COLLECTION OBJECT

  8. Ms-Access and Collection Object Basics
  9. Ms-Access Class Module and Collection Object
  10. Table Records in Collection Object and Form

    DICTIONARY OBJECT

  11. Dictionary Object Basics
  12. Dictionary Object Basics-2
  13. Sorting Dictionary Object Keys and Items
  14. Display Records from Dictionary to Form
  15. Add Class Objects as Dictionary Items
  16. Update Class Object Dictionary Item on Form

Share:

Add Class Objects as Dictionary Items

Introduction.

We have learned the fundamentals of Dictionary Object, done trial runs for sorting simple items, and displayed Access Table records through Dictionary Object to Ms-Access Form.

Now, let us learn how to add Ms-Access Class Objects to Dictionary, how to retrieve each item, and display its Property Values and Method output in the Debug Window.

If you would like to go back and take a look at earlier related Articles then the links are given below.

We need the Class Object: ClsArea Code in your database to try out this example of Dictionary Object.  If it is not already in there, then ClsArea Class Module Code is given below.

Insert a Class Module and change the Name Property Value to ClsArea then copy and paste the following VBA Code in there and save the Module:

Option Compare Database
Option Explicit

Private p_Desc As String
Private p_Length As Double
Private p_Width As Double

Public Property Get strDesc() As String
  strDesc = p_Desc 'copy the value from p_Desc
End Property

Public Property Let strDesc(ByVal strNewValue As String)
  p_Desc = strNewValue
End Property

Public Property Get dblLength() As Variant
  dblLength = p_Length
End Property

Public Property Let dblLength(ByVal dblNewValue As Variant)
    Do While Val(Nz(dblNewValue, 0)) <= 0
      dblNewValue = InputBox("Negative/0 Values Invalid:", "dblLength()", 0)
    Loop
  p_Length = dblNewValue
End Property

Public Property Get dblWidth() As Variant
  dblWidth = p_Width
End Property

Public Property Let dblWidth(ByVal dblNewValue As Variant)
    Do While Val(Nz(dblNewValue, 0)) <= 0
      dblNewValue = InputBox("Negative/0 Values Invalid:", "dblwidth()", 0)
    Loop
  p_Width = dblNewValue
End Property

Public Function Area() As Double
  If (Me.dblLength > 0) And (Me.dblWidth > 0) Then
     Area = Me.dblLength * Me.dblWidth
  Else
     Area = 0
     MsgBox "Error: Length/Width Value(s) Invalid., Program aborted."
  End If
End Function

Private Sub Class_Initialize()
    p_Length = 0
    p_Width = 0
    'MsgBox "Initialize.", vbInformation, "Class_Initialize()"
End Sub

Private Sub Class_Terminate()
   'MsgBox "Terminate.", vbInformation, "Class_Terminate()"
End Sub

The ClsArea Class Object has three Properties (strDesc, dblLength, dblWidth) and a method: Area(). We will instantiate this Class Object to calculate the Area of several rectangular shapes or Rooms and add each Class Object instance to Dictionary Object Item.  The value entered in the Class Object’s strDesc Property will be used as the Key of each Dictionary Object Item. 

As we already know that the Dictionary Object Keys must be Unique Values. Ensure that no duplication occurs in the Class Object’s strDesc Property Value.

For example, if we have two or three bedrooms to find the area, then their names must be something like Bed Room1, Bed Room2, Bed Room3, and so on.

The ClassObjInDictionary() Procedure Code.

Let us try Dictionary with the Class Module Object ClsArea as Items. Sample VBA Code for Dictionary Object is given below.  Copy and Paste it into a Standard Module and save the Module.

Public Sub ClassObjInDictionary()
'--------------------------------------------------
'Add Class Object as Items to Dictionary Object
'Retrieve the Class Object from Dictionary Object
'and Print the values in the Debug Window.
'--------------------------------------------------
Dim C As ClsArea
Dim D As Object, Desc As String, mKey

Set D = CreateObject("Scripting.Dictionary")
D.CompareMode = 1
Desc = ""

Do While Not Desc = "Q"
'instantiate Class Object
Set C = New ClsArea
    
    'Get input Values for ClsArea Object\
    Do While Len(Desc) = 0
      Desc = InputBox("Description or Q=Quit:")
    Loop
       If Desc = "Q" Then Exit Do
       
    C.strDesc = Desc
    C.dblLength = CDbl(InputBox("Length of " & UCase(Desc) & ": "))
    C.dblWidth = CDbl(InputBox("Width of " & UCase(Desc) & ": "))
    
'add to Dictionary
'Description is added as Key of Dictionary Object
    D.Add Desc, C
    Desc = ""
'Clear Class Object
    Set C = Nothing
Loop


If D.Count = 0 Then
  MsgBox "No Data in Dictionary Object!" & vbCr & "Program Aborted."
  Exit Sub
End If

'Output Section
Debug.Print "Key Value", "Description", "Length", "Width", "Area"

For Each mKey In D.keys
        Set C = D(mKey)
        Debug.Print mKey, C.strDesc, C.dblLength, C.dblWidth, C.Area
Next

End Sub

The VBA Code Line by Line.

At the beginning of the Code, we created and instantiated the Dictionary Object D.

The Desc String variable is to key in the Description for strDesc Property Value of the Class Object and that value is used as a control for the Do While . . . Loop.  The control is that the Loop will execute till the single character Q (for Quit) is entered into the Variable Desc.  By this method, you can enter any number of Class Objects into the Dictionary Object Items.  When you are done, enter Q into the Description Desc Variable to Quit from the Loop.

In the next step,  creates an instance of the Class Object ClsArea with Object Variable C.

Again the Desc = InputBox() function statement is put within a second Do While . . . Loop,  to ensure that the user keys in some value into the Desc Variable. 

If the user presses Enter Key, Clicks OK, or Cancel Button, without entering some value, then keep the InputBox() function running, till the User types in a Value.

The valid Description Value is assigned to C.strDesc Property of the Class Object.

Through the next two InputBox() functions collect the Length and width values of Room from the user and assign them to C.dblLength and C.dblWidth Properties respectively. 

Now, the ClsArea Class Object is ready to Add to the Dictionary Object.

The statement D.Add Desc, C adds the current instance of the ClsArea Class Object in the Dictionary Object as its first Item to Desc (or C.strDesc Property Value) as the Key of Dictionary Item.

Next, we clear the ClsArea Class Object instance C from memory.

You might have noticed by now that the Class Object instance C is created, at the beginning of the outer Do While . . . Loop, fill up the Class Object Property Values, Adds it to the Dictionary Object, and the Class Object instance C is Set to Nothing, as the last statement within the Loop.  That means we are creating a New Class Object instance for each Item in the Dictionary Object.

Why it has to be this way, creating new instances of the Class Object for each Item, is an important point you should know about?

When we add the Class Object instance, as an Item to the Dictionary Object, internally only the Class Object’s Location Address is saved in the Dictionary Object as a Pointer.  The actual Class Object Property values are not moved to the Dictionary Object Item. 

When we execute the statement Set C = Nothing the Class Object instance C is cleared, but the instance’s location reference (pointer) is saved in the Dictionary Object Item.  The actual ClsArea Class Object remains in that location and we can retrieve it using the Object Pointer saved in Dictionary Object Item.

When a new Class Object Instance is created, it is created in a new location in memory and its reference is added to the Dictionary Object.

Enter some Description to a few bedrooms, Length, and Width Values to test the Code. Enter the letter Q to complete the Data entry, when you are ready to take a dump of the data in the Debug Window.

A sample Listing is given below:

Key Value     Description   Length        Width         Area
Bed Room1     Bed Room1      14            15            210 
Bed Room2     Bed Room2      12            12            144 
Living Room   Living Room    23            24            552 
Kitchen       Kitchen        11            11            121 
Store Room    Store Room     21            14            294 

In the Printing Code segment, we have not created an instance of the ClsArea Object C, to read the Class Object Pointers from the Dictionary Item into it, before printing the Values, from the location the Pointer pointing to, into the Debug Window. 

Note: If you feel more comfortable by creating an instance of the ClsArea Class Object in C, then you may do so.  In this case, both methods work well. 

The Set C = D(mKey) reads the Location Reference (Pointer) of ClsArea Class Object from the Dictionary Item into C and retrieves its Property and Method values to print in the Debug Window. 

If you made a sample Run of the Code and understood how the Code works, then try running the Code after shifting the Class Object instance creating and removal statements outside the Do While . . . Loop.  After the change runs the Code, add a few items into Dictionary and let it print the input Class Object  Property Values, and check the output in the Debug Window.

Take a Trial Run With the Following Changes in the Code

The Do While . . . Loop segment with suggested changes is given below for you to make changes in your code.  Check the highlighted statements above and below the Do While . . . Loop.

Desc = ""
Set C = New ClsArea

Do While Not Desc = "Q"
'instantiate Class Object
    
    'Get input Values for ClsArea Object
    Do While Len(Desc) = 0
      Desc = InputBox("Description or Q=Quit:")
    Loop
       If Desc = "Q" Then Exit Do
       
    C.strDesc = Desc
    C.dblLength = CDbl(InputBox("Length of " & UCase(Desc) & ": "))
    C.dblWidth = CDbl(InputBox("Width of " & UCase(Desc) & ": "))
    
'add to Dictionary
'Description is added as Key of Dictionary Object
    D.Add Desc, C
    Desc = ""
'Clear Class Object
Loop
    Set C = Nothing

I have shifted the statement Set C = New ClsArea to a position above the Do While . . . Loop.  The statement Set C = Nothing below the statement Loop so that it executes only after completing the data entry of Class Objects for Dictionary within the Do While . . . Loop.

I have keyed in all the five sample items listed above, in the same order of their names, with different values for Length and Width.

Finally, the printing section lists out all five items in the Debug Window.  But, unfortunately only the last item values are printed for all five Items we have entered.

Key Value     Description   Length        Width         Area
Bed Room1     Store Room     12            13            156 
Bed Room2     Store Room     12            13            156 
Living Room   Store Room     12            13            156 
Kitchen       Store Room     12            13            156 
Store Room    Store Room     12            13            156 


Why it has happened this way?

When we add an Object with its Properties to Dictionary Object only the Reference (Location Address) of the Class Object is saved in Dictionary Object Item. 

When an instance of the Class Object is created with the New Key Word that instance’s Location Address will not change.  The Values keyed into its Properties keep on overwriting earlier values.  Every time the Class Object’s Location Address is Added to the Dictionary Object Item, instead of the Object Property Values of the Class Object.

By creating different instances of the Class Object, within every cycle of the Loop, it always creates a new Class Object with a different Location Address. The Dictionary Object keeps this address for its own reference. 

When the statement Set C = Nothing is executed it sets the Object Variable C not pointing anywhere but the physical data created at the memory location is not deleted and kept alive by the Pointer saved in the Dictionary Object. 

But, after shifting the Set C = New ClsArea and Set C = Nothing statements, above and below the Do While . . . Loop, respectively, we are forced to use only one instance of the Class Object to enter several Class Object property values, one after the other, overwriting the earlier property values.  

Since all the Items in Dictionary Object carry the same Class Object instance’s Reference, the printout displays the last entered Class Object Values only, for all different Items entered into the Dictionary Object.  The Key values are maintained separately and show correctly in the listing in the Debug Window.

Next week we will try how to Add, Edit, Update and Delete Class Objects in Dictionary, through Ms-Access Form.

MS-ACCESS CLASS MODULE

  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

    COLLECTION OBJECT

  8. Ms-Access and Collection Object Basics
  9. Ms-Access Class Module and Collection Object
  10. Table Records in Collection Object and Form

    DICTIONARY OBJECT

  11. Dictionary Object Basics
  12. Dictionary Object Basics-2
  13. Sorting Dictionary Object Keys and Items
  14. Display Records from Dictionary to Form
  15. Add Class Objects as Dictionary Items
  16. Update Class Object Dictionary Item on Form

Share:

Display Records from Dictionary to Form

Introduction.

We will do a similar exercise, that we did for Collection Object, for displaying Table Records retrieved from Collection Object on Form, based on the Key value selected from a Combo-box on the Form.

We will add Employee Records to Dictionary Object, with the Last Name as the Key.  Design a sample Form with a Combo box in the Header Section of the Form and a few TextBoxes in the Detail Section, to display the employee information from Dictionary Object, when the Last Name Key value is selected from the Combo Box.

We need Form-based Event Procedure Programs, in the Form’s Class Module, first to load the data records from the Table / Query into Dictionary Object and to retrieve a specific record, as dictated by the Combo-box selection on the Form, and display it in Text Boxes on the Form.

Note: You can download a Demo Database, with the Form and VBA Code, from the bottom of this page.

Let us start with the preparation steps so that you will know what it takes to complete this Project.  You will be better informed of the whole process if you plan to implement this method in one of your own projects.

The Employees Table for Sample Data.

We need some data to load into the Dictionary Object.

  1. Import the Employees Table from the Northwind sample database.
  2. Copy and Paste the following SQL String into the SQL editing window and save it with the name: EmployeesQ
    SELECT Employees.[Last Name], Employees.[First Name], Employees.[E-mail Address], Employees.[Job Title], Employees.[Business Phone], Employees.[Home Phone]
    FROM Employees;
    

    The Sample Form with Few TextBoxes and a Combo Box.

    We will take only a few fields of data from the Employees table.  We can quickly design a Form with the field names from EmployeesQ, but without attaching the EmployeeQ to the Form, as a record source.  The next steps will be needed to add Text Boxes with correct data field names, without typing them into the Name Property of the TextBoxes.

    NB: You can give any name to the TextBoxes, it works with any name.

  3. Select the Design Form option from the Forms Group of Create Menu.  It will open a Blank Form.

  4. Right-Click on the Form and select Form Header/Footer to insert Header and Footer sections to the Form.

    The Sample Design of the Form is given below.

  5. Click on the Detail Section of the Form to make it an active Section.

    Now, we will add six TextBoxes with Employee record field names as TextBox Names.

  6. Click on Add Existing Field Button from the Tools Buttons Group in Design Menu.
  7. Find the Employees Table and Click on the [+] Symbol to show the Employees Table Fields.
  8. Double-Click on the following list of Fields, one by one, to insert them into the Detail Section of the Form:
    • Last Name
    • First Name
    • E-mail Address
    • Job Title
    • Business Phone
    • Home Phone

    NB: This is an Unbound Form and the inserted Field controls also must be Unbound Text Boxes.

    Keep the Text Box's Name Property Value (Field Name) and remove the Control Source Property Value.

  9. Click on the first Text Box to select it.
  10. Display the Property Sheet (F4) of the selected Text Box.
  11. Remove the data Field Name from the Control Source Property to make the text box Unbound.  Ensure that the Name Property Value remains intact.
  12. Remove other Text Box's Control Source Property Values.

    Next, we need a Combo Box on the header of the Form with the list of the Last Name of Employees.

  13. Select the Combo-Box control from the Controls Group under the Design Menu and place the Combo-box Control in the Header Section of the Form.  If the Control Wizard is active, then follow steps 14 to 18, others go to step 19 

  14. If Control Wizard is On, then select the first option and click Next.

  15. Select the Query Option on the next screen, select EmployeeQ and click Next.

  16. In the next Screen double-click on the Last Name to select and insert it into the right panel and click Next.

  17. Select the Last Name in the first text box to sort Last Names in Ascending Order and Click Next.

  18. On the next screen, click Finish.

  19. Change the Name Property Value of the Combo-Box to cboLastName.

  20. Find the Limit to List Property of the Combo Box and change the Value to Yes.

  21. Copy and paste the following SQL into the Row Source Property of the Combo-Box:

    SELECT EmployeesQ![Last Name] FROM EmployeesQ;  
  22. Insert a Command Button in the Footer Section of the Form.

  23. Change the Caption of the Command Button to Exit and Name Property value to cmdClose.

  24. Select the View Code Button from the Tools Group to display the Class Module of the Form.

  25. Highlight the entire VBA Code below, Copy and Paste it into the Form’s Class Module, overwriting the existing lines of Code:

    The Form's Class Module VBA Code.

    Option Compare Database
    Option Explicit
    
    Private D As Object
    Dim txtBox() As String
    
    Private Sub Form_Load()
    Dim db As Database
    Dim rst As Recordset
    Dim Rec() As Variant
    Dim fldCount As Long, ctl As Control
    Dim k As Long, frm As Form, Sec As Section
    Dim strKey As String
    
    'Restore the Form to it's actual design size
    DoCmd.Restore
    
    'instantiate Dictionary Object
       Set D = CreateObject("Scripting.Dictionary")
       
    
    'Open Recordset Source to save in Dictionary
       Set db = CurrentDb
       Set rst = db.OpenRecordset("EmployeesQ", dbOpenDynaset)
    'get recordset fields count
       fldCount = rst.Fields.Count - 1
    
    'Redimension Field Names Array (Rec) for number of fields in Table
       ReDim Rec(0 To fldCount) As Variant
    
       'Add records to Dictionary Object
       Do While Not rst.EOF
         'Get current record field values into Rec Variant Array
         For k = 0 To fldCount
            Rec(k) = rst.Fields(k).Value
         Next
         'Last Name as Dictionary Key
         strKey = rst.Fields("[Last Name]").Value
         
        'Add record to Dictionary Object with 'Last Name' Key
         D.Add strKey, Rec
         rst.MoveNext
       Loop
       
       'Set current Form
       Set frm = Me
       
    'Set Detail Section of Form to look for Text Boxes
       Set Sec = frm.Section(acDetail)
       
    'Redim txtBox Array to save Textbox Names on the Form
    'To display field values
       ReDim txtBox(0 To fldCount) As String
      
      'Get Text Box Names,from Detail Section of Form, and save them into Array.
      'this will be used in the ComboBox AfterUpdate Event
      k = 0
      For Each ctl In Sec.Controls
         If TypeName(ctl) = "TextBox" Then
            txtBox(k) = ctl.Name
            k = k + 1
         End If
      Next
       
       rst.Close
       Set rst = Nothing
       Set db = Nothing
    End Sub
    
    
    Private Sub cboLastName_AfterUpdate()
      Dim strD As String, R As Variant
      Dim j As Long
      Dim L As Long
      Dim H As Long
    
    'Get Selected Key from ComboBox
     strD = Me![cboLastName]
      
      'Retrieve the record from Dictionary
      'using KEY and load the field
      'Values into the Variant Array
      R = D(strD)
      L = LBound(R)
      H = UBound(R)
    'Read Field Values from Array and display
    'them into it's corresponding Textbox names on the Form
      For j = L To H
        Me(txtBox(j)) = R(j)
      Next
      Me.Refresh
    
    End Sub
    
    Private Sub cmdClose_Click()
      DoCmd.Close
    End Sub
    
    
    Private Sub Form_Unload(Cancel As Integer)
      'Clear Dictionary Object from Memory
      Set D = Nothing
    End Sub
    
      
  26. Save the Form with the name Dict_Employees or any other name you prefer.

How it All Works Together.

There are four Subroutines in the above Code.

  • Private Sub Form_Load() Event Procedure.
  • Private Sub cboLastName_AfterUpdate()
  • Private Sub cmdClose_Click()
  • Private Sub Form_Unload(Cancel As Integer)

In the Declaration area of the Module defined an Object variable D for Dictionary Object.  The txtbox() array variable is declared for storing the Text Box names from the Form’s Detail Section and will be used for displaying the selected record’s field values.   

The Dictionary Object is created In the Form_Load Event Procedure,

Immediately after instantiating the Dictionary Object the EmployeesQ Recordset is open for adding records to the Dictionary Object.  A Select Query is created to pick only selected fields of the Employees Table, rather than using the Employees Table directly.

The Rec() Variant Array is Re-dimensioned for the number of fields in the record.  Each field value is added to the Rec Variant Array element and the whole array is inserted into the dictionary Object as a single Item (a record), with the Last Name field value as a unique Dictionary Key.

In the next stage of the code, the Dict_Employees Form’s Detail Section area is scanned to look for Text Boxes and their names are saved into the textbox() Array, for use in the cboLastName_AfterUpdate() Event Procedure.  The txtbox() Array was declared in the Global area of the Module.

When the user selects a name from the Combo Box the Private Sub cboLastName_AfterUpdate() Event Procedure is executed.  The Form's Normal View image is given below:

When the user selects the Last Name from the cboLastName Combo Box it is saved into the String Variable strD. The statement R=D(strD) reads the corresponding employee record field values array into the Variant Variable R. 

We have not explicitly defined the Variant Variable R as an Array. But when we read an Array of values from Dictionary Object Item into it, it automatically re-dimensions itself for the number of required elements and loads each field value into its elements.  

The next two-step determines the Array Index range values. 

Within the For. . .Next Loop the record values are displayed in the Form Text Boxes, using the test box names we have saved in the Form_Load() Event Procedure.

You may select other names from the Combo box to display their details on the Form.  When you are ready to close the Form, click on the Exit Command Button.

When the user clicks on the Exit Command Button the Form is closed. Before closing the Form the Form_Unload Event is triggered and the Dictionary Object is cleared from Memory.

Download the Demo Database.


Download Dictionary2003.zip


Download Dictionary2007.zip


MS-ACCESS CLASS MODULE

  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

    COLLECTION OBJECT

  8. Ms-Access and Collection Object Basics
  9. Ms-Access Class Module and Collection Object
  10. Table Records in Collection Object and Form

    DICTIONARY OBJECT

  11. Dictionary Object Basics
  12. Dictionary Object Basics-2
  13. Sorting Dictionary Object Keys and Items
  14. Display Records from Dictionary to Form
  15. Add Class Objects as Dictionary Items
  16. 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 Class Module External Links Queries Array msaccess reports Accesstips WithEvents msaccess tips Downloads Objects Menus and Toolbars Collection Object MsaccessLinks Process Controls Art Work Property msaccess How Tos Combo Boxes Dictionary Object ListView Control Query VBA msaccessQuery Calculation 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 RaiseEvent Recordset Top Values Variables Wrapper Classes msaccess email progressmeter Access2007 Copy Excel Export Expression Fields Join Methods Microsoft Numbering System Records Security Split SubForm Table Tables Time Difference Utility WScript Workgroup 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 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