Learn Microsoft Access Advanced Programming Techniques, Tips and Tricks.

Tree View Control Check-Mark Add Delete Nodes

Introduction.

Adding or Deleting Nodes in TreeView Control

In this episode of the TreeView Control Tutorial, we will explore how to add or delete nodes dynamically. Before performing these actions, we will determine the position of the selected node—whether the new node should be added at the same level (sibling) or as a child node. Similarly, when deleting, we will identify the currently selected node and remove it using the Remove() method.

This functionality makes the TreeView control more flexible, allowing users to build or modify hierarchical menus on the fly.


TreeView Control Tutorial Sessions So Far

  1. Microsoft TreeView Control Tutorial
  2. Creating an Access Menu with a TreeView Control
  3. Assigning Images to TreeView Control
  4. Assigning Images to TreeView Control-2

The Normal View of the Demo Tree View Control on MS-Access Form, with other controls. 

The Data Table for TreeView Control’s Demo.

We will once again make use of the Sample table that we introduced in the very first tutorial session. This small table contains records representing the structure of common Microsoft Access objects—such as Tables, Forms, and Reports—arranged in a hierarchical order. Its simplicity makes it an excellent source for demonstrating how to add or delete nodes in the TreeView control.

The ID column (used as the TreeView Key) is defined as an AutoNumber field.

Note for New Visitors:
To get up to speed with this session, please download the Demo Database from the second tutorial page: Creating Access Menu with Tree View Control. This database contains a table named Sample and a form named frmSample. You may import both into your current project.

Additionally, the database includes another form named frmMenu. From this form, copy the Expand All and Collapse All command buttons along with their Click Event procedures into the frmSample code module to continue smoothly with this session.

As mentioned earlier, the ImageList Control—with all the images uploaded in the last tutorial—can be shared across projects. We will make a copy of that ImageList Control and bring it into this session. It will then be linked to the TreeView control on frmSample, enabling us to display node images as before.

Importing the ImageList Control with Images.

You can bring an existing ImageList Control (with uploaded images) from another database into your active project in one of the following ways:

  1. Import the entire form that contains the ImageList Control into your current database. Once imported, open the form, then copy and paste the ImageList Control onto the form where you want to use it.

  2. Alternatively, copy the ImageList Control directly:

    • Open the database where the ImageList Control with images already exists.

    • Copy the ImageList Control to the Clipboard.

    • If you have downloaded the Demo Database from the earlier tutorial session, you already have this control with all the uploaded images. After copying, close that database.

    • Open your target database, open the form where you want the ImageList Control, and paste it onto the form.

Once the ImageList Control is in place, you can link it to your TreeView control. In the CreateTreeView() subroutine, add the following code lines to pass the ImageList object reference to the TreeView control:

Set TreeView0.ImageList = Me.ImageList0.Object

This ensures that the TreeView control can access and display the images stored in the ImageList.

After that, you can add the Image Key Names to the TreeView Nodes.Add() Method’s last two parameters. 

These exercises we have already done in the earlier sessions.  To remind you, we are using the Table and TreeView Control we created in the first Tutorial Session and implemented with the above-explained changes. 

Displaying the Check-Marked Nodes Property Values.

The selected Node’s Key, Parent Key, and Text properties are displayed in the TextBoxes on the right-hand side of the TreeView control. In addition to that, a CheckBox (labeled Child Node), along with the Delete Node and Add Node command buttons, has been added to the form. Their functions will be explained shortly.

Displaying CheckBoxes on the TreeView Control

By default, the TreeView control does not display checkboxes. To enable them, you must set the appropriate property in the TreeView control’s Property Sheet.

However, it’s important to note that the TreeView’s built-in checkbox feature has limited functionality. The operations we are about to demonstrate could be performed without using checkboxes at all.

A more practical use of checkboxes in the TreeView would be for scenarios such as generating a report on selected branches of a company. In such a case, the user could tick the checkboxes next to the desired branch nodes in the Access Project Menu, and the report could then be prepared based on those selections.  

  1. Here, our aim is simply to introduce this feature and run a short demo to show how it works.

    1. Open the Form containing the TreeView control in Design View.

    2. Right-click on the TreeView control, highlight the TreeCtrl Object, and select Properties to open the Property Sheet.

    3. In the Property Sheet, enable the CheckBox option by placing a check mark in its box.

    4. Once enabled, checkboxes will be displayed next to each TreeView node, as shown in the image below.

The Demo TreeView Image - the first Image on this Page, Details.

Let us take a closer look at the Demo Form frmSample shown at the top of this page.

  • The TreeView Control and the top two command buttonsExpand All and Collapse All—function exactly as we saw in the last episode.

  • On the right side, under the heading Property Values, three text boxes display the Key, ParentKey, and Text values of the currently checked node.

  • The Delete Node command button removes the selected node. If the node has child nodes, those will be removed as well.

  • To add a new node, you must first edit the Text property in the Property Values section, replacing it with the text you want to assign to the new node.

Just above the Add Node button is a Child Node check box. Together, these two controls define where the new node will be inserted:

  • If Child Node is checked, the new entry will appear as a child of the selected node.

  • If the Child Node is not checked, the new node will be added at the same level as the currently selected node.


Understanding the Add Node Action.

For example, let’s say we want to add a new node for the Hyperlink field under the Fields parent group in the data type list.

In the demo image at the top of this page, notice that the Date Field node is currently selected (checkmarked). On the right-hand Property display, its details are shown as:

  • Key: X15

  • ParentKey: X4

  • Text: Date Field

To create a new Hyperlink node:

  1. Change the Text property from Date Field to Hyperlink in the Property display text box.

  2. Click the Add Node button.

The result will appear as shown below:

If you place the check mark on the Fields parent node and also check the Child Node option (above the Add Node button), the new node will be added under Fields as one of its child items. The result will be the same as in the previous example.

On the other hand, if you keep the check mark on the Date Field node (instead of the parent node) and then set the Child Node option before clicking the Add Node button, the new entry will be created as a child of Date Field.

The result is as shown below:

The Child Node will be created directly under the check-marked node.

When the Add Node action is triggered, a new record must first be created in the underlying Sample table. This record will contain the new Text value (for example, HyperLink) and the corresponding ParentID value.

The AutoNumber field in the table will then generate a unique ID for the new record. This value is retrieved and assigned as the Key for the new TreeView node, ensuring its uniqueness within the control.

The Add Node sub-Routine VBA Code is given below:

Private Sub cmdAdd_Click()
Dim strKey As String
Dim lngKey As Long
Dim strParentKey As String
Dim lngParentkey As Long
Dim strText As String
Dim lngID As Long
Dim strIDKey As String

Dim childflag As Integer
Dim db As DAO.Database
Dim strSql As String
Dim intflag As Integer
Dim tmpnode As MSComctlLib.Node

Dim i As Integer
i = 0
For Each tmpnode In tv.Nodes
    If tmpnode.Checked Then
       tmpnode.Selected = True
        i = i + 1
    End If
Next
If i > 1 Then
      MsgBox "Selected Nodes: " & i & vbCr & "Select only One Node to mark Addition.", vbCritical, "cmdAdd()"
    Exit Sub
End If

'Read Property Values from Form
strKey = Trim(Me![TxtKey])
lngKey = Val(Mid(strKey, 2))

strParentKey = Trim(Me![TxtParent])
lngParentkey = IIf(Len(strParentKey) > 0, Val(Mid(strParentKey, 2)), 0)

strText = Trim(Me![Text])

'Read child Node Option setting
childflag = Nz(Me.ChkChild.Value, 0)

intflag = 0

strSql = "INSERT INTO Sample ([Desc], [ParentID] ) "
If lngParentkey = 0 And childflag = 0 Then
    'Add Root-level Node, ParentKey is Blank
    strSql = strSql & "SELECT '" & strText & "' AS [Desc], '" & " "
    strSql = strSql & "' AS ParentID FROM Sample WHERE ((Sample.ID = 1));"
        intflag = 1
ElseIf (lngParentkey >= 0) And (childflag = True) Then

    'Inserts a child Node to the Check-marked Node, here Key value used as ParentKey
    strSql = strSql & "SELECT '" & strText & "' AS [Desc], '" & lngKey
    strSql = strSql & "' AS ParentID FROM Sample WHERE ((Sample.ID = 1));"
        intflag = 2
ElseIf (lngParentkey >= 0) And (childflag = False) Then
    'Inserts Node at the check-marked level, Add item under the same ParentKey
    strSql = strSql & "SELECT '" & strText & "' AS [Desc], '" & lngParentkey
    strSql = strSql & "' AS ParentID FROM Sample WHERE ((Sample.ID = 1));"
        intflag = 3
End If

Set db = CurrentDb
db.Execute strSql

'Get newly created autonumber to use as Key
lngID = DMax("ID", "Sample")
strIDKey = KeyPrfx & CStr(lngID)

On Error GoTo IdxOutofBound

Select Case intflag
    Case 1
        'Add Root-level Node, ParentKey is Blank
        tv.Nodes.Add , , strIDKey, strText, "folder_close", "folder_open"
    Case 2
        'Inserts a child Node to the Check-marked Node, here Key value used as ParentKey
        tv.Nodes.Add strKey, tvwChild, strIDKey, strText, "left_arrow", "right_arrow"
    Case 3
        'Inserts Node at the check-marked level, Add item under the same ParentKey
        tv.Nodes.Add strParentKey, tvwChild, strIDKey, strText, "left_arrow", "right_arrow"
End Select
tv.Refresh

    'Erase Property Values from Form
        With Me
            .TxtKey = ""
            .TxtParent = ""
            .Text = ""
        End With

Set db = Nothing
cmdExpand_Click
 
cmdAdd_Click_Exit:
Exit Sub

IdxOutofBound:
    CreateTreeView
Resume cmdAdd_Click_Exit
End Sub

Let us now examine the VBA code behind the Add Node process.

  1. Variable Declarations
    After the local variables are declared, the code scans through the TreeView Nodes to identify checkmarks and counts the number of checked items.

    • If more than one Node is checked, a message is displayed, and the procedure is aborted.

  2. Node Selection

    • Instead of check-marking, a Node can also be selected by directly clicking on it.

    • In both cases, the Checked/Selected Node is passed as a parameter to the Event procedure.

    • Using checkmarks is particularly useful when selecting multiple items—for example, choosing different sets of data for a report.

  3. Property Extraction

    • The checked Node’s Key, ParentKey, and Text values are read from the Form controls into the variables:

      • strKey

      • strParentKey

      • strText

    • From these values, the numeric portions of ID and ParentID are extracted and stored in:

      • lngKey (Node ID)

      • lngParentKey (Parent Node ID)

    • These will be used to build the SQL statement.

  4. Child Node Option

    • The value of the Child Node checkbox is saved in the variable ChildFlag.

  5. SQL String Preparation

    • Based on the selection and the Child Node option, three different SQL string variations are prepared:

      • Insert at the same level as the selected Node

      • Insert as a child Node under the selected Node

      • Insert as a child Node under the selected Node’s Parent

  1. Node Creation Logic

    When the Add Node button is clicked, the program determines the type of Node to be created based on the ParentID property value and the Child Node checkbox status.

    1. Root-Level Node

      • Condition: ParentID is empty, and the Child Node option is not checked.

      • Action: A Root-Level Node is created because the user had check-marked a Root Node.

    2. Child Node

      • Condition: ParentID >= 0 and the Child Node option is checked.

      • Action: A new Node is created as a Child of the check-marked Node.

        • The Key (ID) of the check-marked Node is used as the ParentID in the new record.

    3. Sibling Node (Same Level)

      • Condition: ParentID >= 0 and Child Node option is not checked.

      • Action: A new Node is created at the same level as the check-marked Node, sharing the same Parent.


    Control Flow

    • The variable intFlag is assigned values 1, 2, or 3 depending on which of the above cases applies.

      • 1 → Root-Level Node

      • 2 → Child Node

      • 3 → Sibling Node

    • The appropriate SQL INSERT statement is executed to add a new record to the Sample table.

    • Access automatically generates a new AutoNumber ID for this record.

    • Using DMax()The program retrieves this new ID and assigns it as the Key value for the new Node in the TreeView control.

    • Finally, based on the intFlag value, the Node is created in the correct position (root, child, or sibling).

    • The Property display TextBox values are cleared to reset the form for the next action.

Deleting Node or Node with Children.

The Delete Node Option is much easier than the earlier exercise.  Simply deletes the Check-Marked Node and its Children, if present, from the Tree View Control.  The related records are deleted from the Table.

The VBA Code for Node Removal is given below:

Private Sub cmdDelete_Click()
Dim nodId As Long, nodParent As Long
Dim strSql As String
Dim db As DAO.Database
Dim j As Integer
Dim tmpnode As MSComctlLib.Node
Dim strKey As String
Dim strMsg As String

j = 0 ' Get check-marked Nodes count
For Each tmpnode In tv.Nodes
    If tmpnode.Checked Then
        tmpnode.Selected = True
        strKey = tmpnode.Key
        j = j + 1
    End If
Next

   If j > 1 Then
      MsgBox "Selected Nodes: " & j & vbCr & "Select Only One Node to Delete.", vbCritical, "cmdDelete()"
      Exit Sub
   End If

Set tmpnode = tv.Nodes.Item(strKey)
tmpnode.Selected = True
Set db = CurrentDb

'check the presense of Child Node(s) of marked Node
If tmpnode.Children > 0 Then
'Warnings:
'       Deleting Nodes at Random will leave orphaned Nodes
'       in the Table and end up with errors, during next Tree View loading process
    strMsg = "The Marked Node have " & tmpnode.Children & " Children. " & vbCr & "Delete the Child Nodes also?"
    If MsgBox(strMsg, vbYesNo + vbCritical, "cmdDelete()") = vbYes Then
       'Double check and get confirmation.
       strMsg = "Delete Only the deepest set of Child Nodes" & vbCr
       strMsg = strMsg & "and their Parent Node at one time." & vbCr & vbCr
       strMsg = strMsg & "Are you sure to Proceed..?"
       If MsgBox(strMsg, vbYesNo + vbCritical, "cmdDelete()") = vbYes Then
            Do Until tmpnode.Children = 0
                nodId = Val(Mid(tmpnode.Child.Key, 2))
        'Delete Child Node
                tv.Nodes.Remove tmpnode.Child.Index
        'Delete the related record
                strSql = "DELETE Sample.*, Sample.ID FROM Sample WHERE (((Sample.ID)= " & nodId & "));"
                db.Execute strSql
            Loop
        Else
            Exit Sub
        End If
    Else
        Exit Sub
    End If
End If

        nodId = Val(Mid(tmpnode.Key, 2))
    'Delete Parent
       tv.Nodes.Remove tmpnode.Key
       tv.Refresh
    'Delete Marked Record
        strSql = "DELETE Sample.*, Sample.ID FROM Sample WHERE (((Sample.ID)= " & nodId & "));"
        db.Execute strSql
       
      
    'Erase Property Values from Form
        With Me
            .TxtKey = ""
            .TxtParent = ""
            .Text = ""
        End With
    Set db = Nothing
    
End Sub


Delete Node Logic

After the local variable declarations, the procedure to delete a Node follows these steps:

  1. Count Check-Marked Nodes

    • A For Each … Next loop scans through the Nodes.

    • If more than one Node is check-marked, a message is displayed and the program is aborted.

    • If exactly one Node is check-marked, the program continues.


  1. Validation Check – Child Node Presence

    • The program checks if the selected Node has Child Node(s).

    • If Child Nodes are found:

      • A message is displayed to inform the user.

      • The user must reconfirm their intention before proceeding.

      • Deletion must occur from the deepest level first (child → parent → grandparent).


⚠️ Important Rule for Simplicity

  • Always delete the deepest-level Child Nodes first, or delete a parent with its immediate children.

  • Avoid deleting higher-level (grandparent) Nodes directly, as this can leave some Nodes orphaned.

  • Orphaned Nodes will cause errors the next time the TreeView is opened.


  1. Delete Operation

    • If Child Nodes exist:

      • Each Child Node is removed one by one, along with its corresponding record in the underlying table.

      • Finally, the selected Parent Node is deleted, both from the TreeView and the table.

    • If no Child Nodes are present:

      • The selected Node is deleted immediately, and its corresponding table record is also deleted.


  1. Cleanup

    • After deletion, the Property display TextBox values (Key, ParentKey, and Text) are cleared to reset the form.


The Form frmSample’s Complete Class Module VBA Code.

Complete VBA Code in frmSample’s Class Module

Below is the complete code for the form frmSample, which includes:

  • Utility subroutines for Expanding and Collapsing Nodes

  • The TreeView0_NodeCheck() event procedure

  • The cmdExit_Click() event

  • The Form_Load() procedure

  • The CreateTreeView() subroutine

  • And the full implementation of the Add Node and Delete Node logic

Option Compare Database
Option Explicit

Dim tv As MSComctlLib.TreeView
Dim ImgList As MSComctlLib.ImageList
Const KeyPrfx As String = "X"

Private Sub cmdAdd_Click()
Dim strKey As String
Dim lngKey As Long
Dim strParentKey As String
Dim lngParentkey As Long
Dim strText As String
Dim lngID As Long
Dim strIDKey As String

Dim childflag As Integer
Dim db As DAO.Database
Dim strSql As String
Dim intflag As Integer
Dim tmpnode As MSComctlLib.Node

Dim i As Integer
i = 0
For Each tmpnode In tv.Nodes
    If tmpnode.Checked Then
       tmpnode.Selected = True
        i = i + 1
    End If
Next
If i > 1 Then
      MsgBox "Selected Nodes: " & i & vbCr & "Select only One Node to mark Addition.", vbCritical, "cmdAdd()"
    Exit Sub
End If

'Read Property Values from Form
strKey = Trim(Me![TxtKey])
lngKey = Val(Mid(strKey, 2))

strParentKey = Trim(Me![TxtParent])
lngParentkey = IIf(Len(strParentKey) > 0, Val(Mid(strParentKey, 2)), 0)

strText = Trim(Me![Text])

'Read child Node Option setting
childflag = Nz(Me.ChkChild.Value, 0)

intflag = 0

strSql = "INSERT INTO Sample ([Desc], [ParentID] ) "
If lngParentkey = 0 And childflag = 0 Then
    'Add Root-level Node, ParentKey is Blank
    strSql = strSql & "SELECT '" & strText & "' AS [Desc], '" & " "
    strSql = strSql & "' AS ParentID FROM Sample WHERE ((Sample.ID = 1));"
        intflag = 1
ElseIf (lngParentkey >= 0) And (childflag = True) Then

    'Inserts a child Node to the Check-marked Node, here Key value used as ParentKey
    strSql = strSql & "SELECT '" & strText & "' AS [Desc], '" & lngKey
    strSql = strSql & "' AS ParentID FROM Sample WHERE ((Sample.ID = 1));"
        intflag = 2
ElseIf (lngParentkey >= 0) And (childflag = False) Then
    'Inserts Node at the check-marked level, Add item under the same ParentKey
    strSql = strSql & "SELECT '" & strText & "' AS [Desc], '" & lngParentkey
    strSql = strSql & "' AS ParentID FROM Sample WHERE ((Sample.ID = 1));"
        intflag = 3
End If

Set db = CurrentDb
db.Execute strSql

'Get newly created autonumber to use as Key
lngID = DMax("ID", "Sample")
strIDKey = KeyPrfx & CStr(lngID)

On Error GoTo IdxOutofBound

Select Case intflag
    Case 1
        'Add Root-level Node, ParentKey is Blank
        tv.Nodes.Add , , strIDKey, strText, "folder_close", "folder_open"
    Case 2
        'Inserts a child Node to the Check-marked Node, here Key value used as ParentKey
        tv.Nodes.Add strKey, tvwChild, strIDKey, strText, "left_arrow", "right_arrow"
    Case 3
        'Inserts Node at the check-marked level, Add item under the same ParentKey
        tv.Nodes.Add strParentKey, tvwChild, strIDKey, strText, "left_arrow", "right_arrow"
End Select
tv.Refresh

    'Erase Property Values from Form
        With Me
            .TxtKey = ""
            .TxtParent = ""
            .Text = ""
        End With

Set db = Nothing
cmdExpand_Click
 
cmdAdd_Click_Exit:
Exit Sub

IdxOutofBound:
    CreateTreeView
Resume cmdAdd_Click_Exit
End Sub

Private Sub cmdClose_Click()
    DoCmd.Close
End Sub

Private Sub cmdDelete_Click()
Dim nodId As Long, nodParent As Long
Dim strSql As String
Dim db As DAO.Database
Dim j As Integer
Dim tmpnode As MSComctlLib.Node
Dim strKey As String
Dim strMsg As String

j = 0 ' Get check-marked Nodes count
For Each tmpnode In tv.Nodes
    If tmpnode.Checked Then
        tmpnode.Selected = True
        strKey = tmpnode.Key
        j = j + 1
    End If
Next

   If j > 1 Then
      MsgBox "Selected Nodes: " & j & vbCr & "Select Only One Node to Delete.", vbCritical, "cmdDelete()"
      Exit Sub
   End If

Set tmpnode = tv.Nodes.Item(strKey)
tmpnode.Selected = True
Set db = CurrentDb

'check the presense of Child Node(s) of marked Node
If tmpnode.Children > 0 Then
'Warnings:
'       Deleting Nodes at Random will leave orphaned Nodes
'       in the Table and end up with errors, during next Tree View loading process
    strMsg = "The Marked Node have " & tmpnode.Children & " Children. " & vbCr & "Delete the Child Nodes also?"
    If MsgBox(strMsg, vbYesNo + vbCritical, "cmdDelete()") = vbYes Then
       'Double check and get confirmation.
       strMsg = "Delete Only the deepest set of Child Nodes" & vbCr
       strMsg = strMsg & "and their Parent Node at one time." & vbCr & vbCr
       strMsg = strMsg & "Are you sure to Proceed..?"
       If MsgBox(strMsg, vbYesNo + vbCritical, "cmdDelete()") = vbYes Then
            Do Until tmpnode.Children = 0
                nodId = Val(Mid(tmpnode.Child.Key, 2))
        'Delete Child Node
                tv.Nodes.Remove tmpnode.Child.Index
        'Delete the related record
                strSql = "DELETE Sample.*, Sample.ID FROM Sample WHERE (((Sample.ID)= " & nodId & "));"
                db.Execute strSql
            Loop
        Else
            Exit Sub
        End If
    Else
        Exit Sub
    End If
End If

        nodId = Val(Mid(tmpnode.Key, 2))
    'Delete Parent
       tv.Nodes.Remove tmpnode.Key
       tv.Refresh
    'Delete Marked Record
        strSql = "DELETE Sample.*, Sample.ID FROM Sample WHERE (((Sample.ID)= " & nodId & "));"
        db.Execute strSql
       
      
    'Erase Property Values from Form
        With Me
            .TxtKey = ""
            .TxtParent = ""
            .Text = ""
        End With
    Set db = Nothing
    
End Sub

Private Sub cmdExpand_Click()
Dim nodExp As MSComctlLib.Node

        For Each nodExp In tv.Nodes
            nodExp.Expanded = True
        Next

End Sub

Private Sub cmdCollapse_Click()
Dim nodExp As MSComctlLib.Node

        For Each nodExp In tv.Nodes
            nodExp.Expanded = False
        Next
End Sub

Private Sub Form_Load()
    CreateTreeView
    cmdExpand_Click
End Sub

Private Sub CreateTreeView()
Dim db As Database
Dim rst As Recordset
Dim nodKey As String
Dim ParentKey As String
Dim strText As String
Dim strSql As String

Set tv = Me.TreeView0.Object
tv.Nodes.Clear

'Pass ImageList control reference to TreeView's ImageList Property.
Set ImgList = Me.ImageList0.Object
tv.ImageList = ImgList

strSql = "SELECT ID, Desc, ParentID FROM Sample;"

Set db = CurrentDb
Set rst = db.OpenRecordset("sample", dbOpenTable)
Do While Not rst.EOF And Not rst.BOF
    If Nz(rst!ParentID, "") = "" Then
        nodKey = KeyPrfx & CStr(rst!ID)
        strText = rst!desc
        tv.Nodes.Add , , nodKey, strText, "folder_close", "folder_open"
    Else
        ParentKey = KeyPrfx & CStr(rst!ParentID)
        nodKey = KeyPrfx & CStr(rst!ID)
        strText = rst!desc
        tv.Nodes.Add ParentKey, tvwChild, nodKey, strText, "left_arrow", "right_arrow"
    End If
rst.MoveNext
Loop

rst.Close
On Error GoTo 0
Set rst = Nothing
Set db = Nothing

End Sub

Private Sub TreeView0_NodeCheck(ByVal Node As Object)
Dim xnode As MSComctlLib.Node

Set xnode = Node
  If xnode.Checked Then
    xnode.Selected = True

    With Me
        .TxtKey = xnode.Key
      If xnode.Text = xnode.FullPath Then
        .TxtParent = ""
      Else
        .TxtParent = xnode.Parent.Key
      End If
        .Text = xnode.Text
    End With
  Else
    xnode.Selected = False
    With Me
      .TxtKey = ""
      .TxtParent = ""
      .Text = ""
    End With
End If
End Sub

📌 Notes for Readers:

  • The Add Node and Delete Node button procedures should contain the full logic we explained in the last two sections (SQL insert for new records, DMax() to fetch ID, and deletion with child validation).

  • In this complete listing, I’ve left placeholders (' (Full Add Node logic goes here)) so you can easily copy and paste the previously explained code blocks in.


The Design View of the frmSample Form is given below:

Your Observations, comments, and suggestions are welcome.

The Demo Database is attached for Download.


DICTIONARY OBJECT

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

Share:

Assigning Images to Tree View Nodes-2

Introduction.

I hope you’ve enjoyed the past few tutorial sessions on Microsoft TreeView and ImageList Control, and that you’re ready to dive into the next installment. If you haven’t had a chance to go through the earlier articles yet, you’ll find the links to the previous episodes below.

This post continues from last week’s episode.

In the previous session, we created a set of images and uploaded them into the ImageList Control using VBA. The ImageList reference was then assigned to the TreeView Control’s ImageList property, allowing us to directly use either the image Key Names or Index Numbers as the [Image] and [SelectedImage] parameters in the Nodes.Add() method of the TreeView object.

With these steps, we were able to design a visually appealing Microsoft Access Project Menu featuring a hierarchical structure, tree lines, and custom node images.

Last Week’s Trial Run: Form with Node Images.

Below is the sample Access Project Menu created last week, showing the node images alongside the tree lines:

VBA Code for Uploading Images into the ImageList Object.

The following VBA procedure was used to upload images into the ImageList Control and make them available for use in the TreeView nodes:

Dim tvw As MSComctlLib.TreeView
Const KeyPrfx As String = "X"
Dim objimgList As MSComctlLib.ImageList


Private Sub CreateImageList()
Dim strPath As String

'Initialize Tree View Object
Set tvw = Me.TreeView0.Object
'Clear the Tree View Nodes, if any.
tvw.Nodes.Clear

'Initialize ImageList Object
Set objimgList = Me.ImageList0.Object
’the images must be saved in database path
strPath = CurrentProject.Path & “\”

With objimgList.ListImages
'Key Names are Case sensitive.
    .Add , "FolderClose", LoadPicture(strPath & "folderclose2.jpg")
    .Add , "FolderOpen", LoadPicture(strPath & "folderopen2.jpg")
    .Add , "ArrowHead", LoadPicture(strPath & "arrowhead.bmp")
    .Add , "LeftArrow", LoadPicture(strPath & "LeftArrow.bmp")
    .Add , "RightArrow", LoadPicture(strPath & "RightArrow2.bmp")
End With

With tvw
    .ImageList = objimgList
End With

End Sub


The Purpose of Using Meaningful Images

In our last example, we did not just use random icons. Instead, we assigned purpose-driven images that represent the actual behavior of the menu items.

  • Root-level Nodes (Folder Images):

    • FolderClose → Used for the normal view of the Root Node. This indicates that its child items are currently hidden.

    • FolderOpen → Displayed when the Root Node is clicked, showing that its child items are now visible.

    • Note: Once expanded, clicking again will not revert the image back to FolderClose while the Node is in focus. However, depending on your TreeView0_NodeClick() event procedure, the child nodes may collapse and hide again.

  • Child Nodes (Arrow Images):

    • LeftArrow → A small, left-facing arrow for the default (unclicked) state of child nodes.

    • RightArrow → A slightly larger arrow pointing right, displayed when a child node is clicked. This provides a clear visual cue that the item is active.

The highlighted words above are the Key Names that were defined in the ImageList control and then referenced in the Nodes.Add() method.

When the user clicks a child node, the action not only updates the image but also triggers the opening of the linked object (Form, Report, or Macro), depending on which child node is selected.

The ImageList control on the Form.

The ImageList Control on the frmMenu Form, highlighted in Design View, is shown below.

The ImageList Control Property Sheet.

The ImageList’s Property Sheet Image is given below for reference:

Review of Last Week’s Exercise and Preparations.

In last week’s session, we worked with 16 x 16 pixel images and uploaded them into the ImageList Control using VBA code. After loading the images, we assigned the ImageList Object reference to the TreeView Control’s ImageList property.

This setup allowed us to use either the Index Number or the Key Value of each image in the Add() method parameters of TreeView Nodes.

A few important points from last week’s method:

  • We did not specify the first (Index) parameter of the ImageList’s Add() method. Instead, this method itself automatically generates the Index Numbers sequentially.

  • When you use Key Values in the Nodes.Add() methods [Image] and [SelectedImage] parameters, remember that Key values are case-sensitive.

  • For consistency, it is a good practice to enter Key values in the ImageList Control’s Key text box in lowercase letters.


The Easy Way: Loading Images Without VBA

As promised, this week we’ll look at the simpler, no-code approach. Instead of writing VBA code to load images, you can:

  1. Open the ImageList control on your form.

  2. Manually adding images one by one, directly from your disk.

  3. Assign a Key value (lowercase preferred) or rely on the automatically assigned Index number.

That’s it! No VBA required.


Advantages of the Manual Method

  • Quick setup: Ideal when your image set is finalized and not expected to change frequently.

  • Portability: You can copy and paste the ImageList control into another project form, and all the images remain intact. This makes it easy to reuse your ImageList across multiple Access applications.

  • Direct referencing: Just like in the VBA method, you can still use either the Key value or the Index number in the Nodes.Add() method of the TreeView Control.


Preparing for This Week’s Demo.

If you have already downloaded last week’s demo database (ProjectMenuV21.accdb), open it now. Inside, you’ll find a saved copy of the form frmMenu renamed as frmMenu2.

We’ll be using frmMenu2 this manual image loading method.

Adding an ImageList Control to the frmMenu2 Form.

  1. Open the form frmMenu2 in Design View.

  2. Insert the Microsoft ImageList Control from the ActiveX Controls List, somewhere on the empty space on the frmMenu2 Form.

  3. Change the Name Property value to ImageList0.

  4. Right-click on the Image List Control, highlight ImageListCtrl Object Option, on the displayed menu, and select Properties.

  5. Select the preset Image Size 16 x 16 Pixels Option on the Properties General Tab.  You must select one of these options on the General Tab first, before adding any Image to the Images Tab.

  6. Select the Images Tab. The Properties Images Tab looks like the following Image:

  7. Click the Insert Picture command button, then browse to locate the folder_closed sample image (or use any image you created during last week’s trial run). Select the file and click the Open button.

    After this step, the ImageList control will display the newly inserted image, as shown in the screenshot below.

  8. Once the image is inserted, three text box controls—Index, Key, and Tag—will become active. The Index text box will automatically display the value 1 for the first image.

    In the Key text box, type a unique string value such as folder_close (or any meaningful key name you prefer). This key name will later be used in the Add() method's parameters of the TreeView control. Remember, key values must be unique and are case-sensitive, so keep them simple and easy to recall.

    The Tag property is optional but useful. You can enter information like the file path of the image or any other descriptive note.

    Repeat the process for all other images:

    • Insert each image one by one from your disk.

    • Assign a meaningful key value in the Key text box.

    • Optionally, add a descriptive note in the Tag box.

    If you need to remove an image, simply select it in the control and click Remove Picture.

    When you finish uploading all required images, click Apply, then click OK to close the ImageList control.

    ⚠️ Important: Ensure that the image size (e.g., 16 x 16 pixels) is selected on the General tab before uploading images. Once images are added, the size option becomes locked. To change the image size later, you must remove all images, select the new size, and then re-upload them.

    The ImageList control with multiple images will appear similar to the example shown below:

  9. If you are unsure of the Key-Value assigned to a particular image, simply click on the image in the control. The Key text box will immediately display its assigned value.

    Once all required images are uploaded, they remain stored within the ImageList control itself. This means you can easily reuse them in other projects—just copy the ImageList control to a new form, or share the form/database with others. You can also add more images later from a new location if needed.

    After the images are ready, the next step is to pass the ImageList control reference to the TreeView control’s ImageList property, just as we did earlier when uploading images with VBA code.

    Here is a sample snippet that demonstrates how to assign the ImageList reference to the TreeView control in a new project:

    Private Sub Form_Load() ' Pass ImageList reference to the TreeView control Set Me.TreeView0.ImageList = Me.ImageList1.Object End Sub

    In this example:

    • TreeView0 is the name of the TreeView control.

    • ImageList1 is the name of the ImageList control containing the uploaded images.

    With this link established, you can now use either the Index numbers or the Key values of the images directly in the Nodes.Add() method of the TreeView.

Expanding/Collapsing Nodes with One Command Button.




  1. Open the frmMenu2 form in Design View.

  2. Select the Collapse All command button, open its Click event procedure, and remove the code.

  3. Delete the Collapse All button from the form (we will replace both actions with one button).

  4. Select the Expand All command button, and open its Click event procedure.

  5. Copy and paste the following VBA code, overwriting any existing lines between cmdExpand_Click() and End Sub:

Private Sub cmdExpand_Click()
Dim Nodexp As MSComctlLib.Node

If cmdExpand.Caption = "Expand All" Then
    cmdExpand.Caption = "Collapse All"
    
    For Each Nodexp In tvw.Nodes
        Nodexp.Expanded = True
    Next Nodexp
Else
    cmdExpand.Caption = "Expand All"
    
    For Each Nodexp In tvw.Nodes
        Nodexp.Expanded = False
    Next Nodexp
End If

End Sub
  1. Save and Open frmMenu2 in normal view.

  2. The Command Button Caption text is now shown as Expand All, and all the Nodes are in the collapsed state.

  3. Click on the Command Button to open up all the Nodes.  All the nodes and their Child Nodes will be in expanded form. The Caption of the Command Button changes to 'Collapse All'.

  4. Click on the same Command Button again, and all the Nodes are now closed except the Root-level Nodes, and the Caption Text changes back to 'Expand All' again.

Next week, we will explore the CheckBoxes on Nodes to learn how we can identify checked Nodes and work with them.

CLASS MODULE

  1. MS-Access Class Module and VBA
  2. MS-Access VBA Class Object and Arrays
  3. MS-Access Base Class and Derived Objects
  4. VBA-Base Class and Derived Object-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

Share:

Assigning Images to Tree View Nodes

Introduction.

Last week, we created the Access Project Menu using a TreeView Control, and I trust you were able to build it in your own version of Microsoft Access and run it successfully.

For your reference, there is a Demo Database—originally created in Access 2007—attached to the article linked below:

Creating an Access Menu with a Tree View Control.

You can download this database, add the new VBA code from today’s topic, and test it in the same environment.

This article is a continuation of an earlier tutorial and uses the same Demo Access Menu ProjectWe will focus on assigning images to the TreeView nodes.


MS Office / Windows Version Issues with the TreeView Control

If you encounter problems running the Demo Database in your version of Microsoft Access, you may find the following link helpful. It contains corrective steps for common compatibility issues:

SOLVED – MSCOMCTL.OCX Download, Register in 64-bit Windows


Sample Demo Image

When we complete our Access Project Menu, the TreeView nodes will appear with images, as shown in the sample image below:

Optionally, you can assign two images to each TreeView node—one for the normal state and another for when the node is selected (clicked).

For example:

  • Root-level Nodes can display a Closed Folder icon in the normal view and switch to an Open Folder icon when clicked.

  • Child Nodes might use an arrowhead icon pointing left for the normal view and change to an arrowhead pointing right when selected.

If you prefer, you can use the same image for both the normal and selected states. In that case, the icon will remain unchanged when a node is clicked. However, note that if you provide only one of the two parameters—say, the normal view image—and leave the second one blank, the node will display no image when clicked.


Ideal Image Sizes for TreeView Nodes

You can use almost any standard image format—BMP, JPG, JPEG, ICO, TIFF, etc. There are plenty of free icon collections available online.

The ideal image size for a crisp, balanced display is 16 × 16 pixels. The ImageList control provides preset size options (16×16, 32×32, 48×48 pixels) as well as a custom size setting.

  • 16×16 pixels – Best for compact, clean menus.

  • 32×32 or 48×48 pixels – Larger, more detailed icons, but they take up more space on the TreeView display.


Example – Different Image Sizes in Action

The sample image below shows a 32 × 32 pixel icon applied to a TreeView node:

TreeView Control with Node Image Size 48 x 48 Pixels:

If you choose the Custom Image option, the actual size of the image you provide will be displayed exactly as it is—no automatic resizing will be applied.


Image Quality and Size Considerations

In the first sample image above, we used 16 × 16 pixels. If you upload a larger image—say 512 × 512 pixels—but set the option to display it at 16 × 16, the control will shrink the image. While the size will fit, the clarity will usually suffer, resulting in a blurry or distorted look.

Best practice:

  • Start with high-quality small images that already fit into a 16 × 16 pixel canvas.

  • Such images work perfectly with both the 16 × 16 preset and custom sizing, without losing clarity.


Experiment Before Finalizing

You can try out different:

  • Image formats (BMP, JPG, PNG, ICO, TIFF, etc.)

  • Pixel dimensions

  • Color depths

Use tools like MS Paint or any other image editor to create, import, or adjust your icons until they look just right.


Preparing for the Next Step

Before we continue, create four or more small icons and save them in the same folder as your database. Upload these images into the ImageList control, then experiment with them in the TreeView control by adjusting the last two parameters in the Nodes.Add() method. 

Preparing for the Trial Run

  1. Open the ProjectMenu.accdb database.

  2. Make a backup copy of the form:

    • In the Navigation Pane, right-click frmMenu.

    • Select Copy → then Paste.

    • Name the copy as frmMenu2. Keep this as a safe backup before making changes.

  3. Open frmMenu in Design View.

  4. On the Design tab, in the Controls group, click ActiveX Controls.

  5. In the list, locate Microsoft ImageList Control.

  6. Click OK to insert it onto the form.

  7. Drag and place the ImageList control anywhere in an empty area of the form (its position won’t affect functionality).

    Form with ImageList Control highlighted in Design View is given below for reference:

  8. Display its Property Sheet and change the Name Property value to ImageList0.

  9. Right-click on the ImageList Control and highlight the ImageListCtrl Object Option in the displayed Menu and select Properties to display the Control’s Image settings Property Sheet.

  10. Select the 16 x 16 image size Radio Button on the General Tab, indicating that we need the smallest of the three image sizes for the Node.  The setting here takes effect on all Images we add to the ImageList Control.

  11. Click the Apply Command Button and then the OK button to close the Property Sheet.

First, we must add the required images to the ImageList Control before we can use them in the Tree View Control.

Image Loading Approaches

There are two ways to add images to the ImageList control:

  1. The Easy Way – Add images directly through the control’s property sheet, without using VBA.

  2. The Hard Way – Use VBA code to load images programmatically.

We will start with the hard way first, so you can see how to work with VBA when you need more flexibility—such as experimenting with different image sizes—before deciding what looks best on the TreeView nodes.

With VBA, we use the ImageList object’s Add() method to load images into the control, similar to how we added nodes to the TreeView. Once images are stored in the ImageList, they can be assigned to nodes at run time.


Syntax of the Add() Method

ImageList.ListImages.Add Index, Key, Picture
  • Index – Optional. The position number where the image will be inserted in the list.

  • Key – Optional. A string identifier to refer to the image by name.

  • Picture – Required. The actual image to be added (must be provided as an Picture object).

Example usage:

ObjImgList.ListImages.Add([Index],[Key],[Picture]) As ListImage

The first two parameters of the Add() method are optional. The third parameter uses the LoadPicture() function to load images from the specified file path and add them to the ImageList. This function requires the full file path and name of the image. Each image is added sequentially to the ImageList object in the order they are processed. The Index values are automatically assigned as consecutive numbers, starting from 1.

Once all images have been loaded into the ImageList, the final step is to assign the ImageList object to the TreeView control’s ImageList property. This links the two controls so that nodes in the TreeView can use the images stored in the ImageList.

The VBA Code.

The sample VBA Code for loading images for our Menu above is given below:

Dim tvw As MSComctlLib.TreeView
Const KeyPrfx As String = "X"
Dim objimgList As MSComctlLib.ImageList

Private Sub CreateImageList()
Dim strPath As String

'TreeView Object reference set in tvw
Set tvw = Me.TreeView0.Object
'Clear the Tree View Nodes, if any.
tvw.Nodes.Clear

'ImageList Object reference set in objimglist
Set objimgList = Me.ImageList0.Object

strPath = CurrentProject.Path & "\"

With objimgList.ListImages
'Key Names are Case sensitive.
    .Add , "FolderClose", LoadPicture(strPath & "folderclose2.jpg")
    .Add , "FolderOpen", LoadPicture(strPath & "folderopen2.jpg")
    .Add , "ArrowHead", LoadPicture(strPath & "arrowhead.bmp")
    .Add , "LeftArrow", LoadPicture(strPath & "LeftArrow.bmp")
    .Add , "RightArrow", LoadPicture(strPath & "RightArrow2.bmp")
End With

With tvw
    .ImageList = objimgList
End With

End Sub

Once we are through with this procedure, it is easy to add the images to the Tree View Nodes.

The TreeView Nodes' Add() Method and Image Parameters.

The Tree View Object Add() Method’s last two parameters are for the Node Images.  Let us look at the TreeView Object Node's Add() method Syntax one more time:

tvw.Nodes.Add([Relative],[Relationship],[Key],[Text],[Image],[SelectedImage]) As Node

The last two parameters in the Nodes.Add() Methods are used to assign images to a node. The first parameter specifies the image for the node’s normal view, while the second specifies the image to display when the node is selected. Both the Image and SelectedImage values can be provided either as the ImageList index number or as the key value assigned to the image.

In our example, the CreateImageList subroutine adds five images to the ImageList control. Of the first two images, the first (FolderClose) is used for the root-level node’s normal view, and the second (FolderOpen) is displayed when the root-level node is selected.

Similarly, the last two images are assigned to the child nodes — one for their normal view and the other for when the node is clicked.

The ArrowHead image is ignored. 

The Form_Load() Event Procedure Changes.

The modified FormLoad() Event Procedure is given below:

Private Sub Form_Load()
Dim db As Database
Dim rst As Recordset
Dim nodKey As String
Dim PKey As String
Dim strText As String
Dim strSQL As String

Dim tmpNod As MSComctlLib.Node
Dim Typ As Variant

'1. Initializes TreeView Control Object
'2. Creates ImageList in ImageListObject
CreateImageList 

With tvw
    .Style = tvwTreelinesPlusMinusPictureText
    .LineStyle = tvwRootLines
    .LabelEdit = tvwManual
    .Font.Name = "Verdana"
    .Indentation = 400
End With

strSQL = "SELECT ID, Desc, PID, Type,Macro,Form,Report FROM Menu;"

Set db = CurrentDb
Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)

Do While Not rst.EOF And Not rst.BOF
    If Nz(rst!PID, "") = "" Then
        nodKey = KeyPrfx & CStr(rst!ID)
        strText = rst!desc
      Set tmpNod = tvw.Nodes.Add(, , nodKey, strText, "FolderClose", "FolderOpen")
      
      'Root-Level Node Description in Bold letters
      With tmpNod
        .Bold = True
      End With
    Else
        PKey = KeyPrfx & CStr(rst!PID)
        nodKey = KeyPrfx & CStr(rst!ID)
        strText = rst!desc
        Set tmpNod = tvw.Nodes.Add(PKey, tvwChild, nodKey, strText, "LeftArrow", "RightArrow")
     
     'Check for the presense of Type Code
        If Nz(rst!Type, 0) > 0 Then
            Typ = rst!Type
            Select Case Typ
                Case 1 'save type Code & Form Name in Node Tag Property
                    tmpNod.Tag = Typ & rst!Form
                Case 2 'save type Code & Report Name in Node Tag Property
                    tmpNod.Tag = Typ & rst!Report
                Case 3 'save type Code & Macro Name in Node Tag Property
                    tmpNod.Tag = Typ & rst!Macro
            End Select
        End If
        
    End If
    rst.MoveNext
Loop
rst.Close

Set rst = Nothing
Set db = Nothing

End Sub

In the VBA code shown above, the Add() Method line for adding TreeView nodes has been highlighted. Here, the image key string parameter values are specified for both the normal and click views of the images.

Alternatively, you can use image index values — for example, 1 and 2 for the root-level nodes, and 4 and 5 for the child nodes.

Feel free to change these values and experiment.

A new demo database, containing all the changes and additional image-loading procedures, is attached for you to download.

Note: For your own trial runs, create four new images as explained earlier. If you save the images in a different location, remember to update their names and file paths in the VBA code accordingly.

Next, we’ll explore the easy method for adding images — and I’ll share my own sample images with you.

Sample Database for Download.


  1. MS-Access and E-Mail
  2. Invoke Word- Mail Merge from Access 2007
  3. Automated Email Alerts

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