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

Showing posts with label Nodes. Show all posts
Showing posts with label Nodes. Show all posts

TreeView ImageCombo Drop-Down Access Menu

ImageCombo Drop-Down Access Menu.

In this session of the TreeView Control Tutorial, we will focus on programming the ImageComboBox Control. Our objective is to build an MS Access project drop-down menu using an ImageComboBox control. Additionally, we will use a second ImageComboBox control to display the images along with their key values from the ImageList control. Both ImageComboBox controls will draw their images from a common ImageList control, into which the images were manually uploaded from the computer during an earlier session of this tutorial series.

The sessions of the TreeView Control Tutorial covered so far are as follows:

The TreeView Control Tutorial Session Links.

  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
  5. TreeView Control Check-Mark Add, Delete Nodes

The Demo View of Both ImageComboBoxes Expanded.

The completed MS Access Project Drop-Down Menu Image is given below:

The Design View Image of the above Form is given below:

The Drop-Down ImageComboBox Source Data.

The source data for the new MS Access Project Drop-Down Menu is taken from our earlier Access Menu Project.

If you have not already done so, please download the demo database using the link provided in item 4 above. Once downloaded, you will have all the required data objects to proceed with this session.

The database includes three tables: Categories, Products, and Menu. It also contains two forms to display category and product data, along with a parameter form for filtering report data.

Additionally, we will use two Forms—frmMenu and frmMenu2—which were used in our earlier tutorial sessions.

You will also find two reports for previewing the Categories and Products data items.

There are two macros designed to display simple messages. These macros can also be used to sequence action queries for data processing, particularly when working with more complex reports. In earlier tutorial sessions, we executed these actions by selecting options from the TreeView Control 

Project Menu.

We will also need these objects here, as we are about to create a new drop-down menu using the ImageComboBox Control. The goal is to ensure that all objects can be opened through selections in the new drop-down menu, in the same way we accessed them earlier on the frmMenu2 form using the TreeView Control within this same database.

The Menu table image is given below for your reference.

Preparing for the Design of the Drop-Down Menu Form.

Open the Menu Form in Design View, and you will see two menu-related controls:

  • An ImageList control

  • An ImageComboBox control

Additionally, another ImageComboBox control has been placed on the right side of the form to display the images stored in the ImageList.

To set this up:

  1. Copy the ImageList Control

    • Open the frmMenu2 form, copy the ImageList control, and paste it onto a new form named frmMenu3Combo.

    • This ImageList control already contains images that were manually uploaded from the computer in an earlier tutorial session.

    • Open the Property Sheet: right-click the ImageList control, select ImageListCtl Object, and then choose Properties to review the images and their key names.

  2. Add the First ImageComboBox Control

    • From the ActiveX Controls group, insert a Microsoft ImageComboBox Control onto the left side of the form.

    • Rename this control to imgCombo1. This will serve as the drop-down menu.

  3. Add the Second ImageComboBox Control

    • Insert another ImageComboBox control on the right side of the form.

    • Rename this control to imgCombo2. This control displays the images and their key names from the ImageList0 control in a drop-down list.

  4. Add a Label

    • Place a label above the second ImageComboBox control.

    • Set its caption to Image List.

The Images Listed in the Image Combo Box control.

We will begin with the second control, imgCombo2, which displays the list of images from the ImageList control. Once you understand this code, creating the drop-down menu will become much easier.

The VBA code for the frmMenu3Combo form module has been divided into two parts. Let us start with the first part and examine its contents.

In the global declaration area, the main object variables are defined. The Form_Load() event procedure initializes the ImageList control on the form and assigns it to the object variable 'objImgList'. It then calls the cboImageList() subroutine, which loads the images from the ImageList control into the second ImageComboBox control (imgCombo2).

Now, let’s take a closer look at the code.

The first-part vba code, with the Form_Load() and cboImageList() subroutines listed below:

Dim imgcombo1 As MSComctlLib.ImageCombo
Dim imgCombo2 As MSComctlLib.ImageCombo
Dim objimgList As MSComctlLib.ImageList
Const KeyPrfx As String = "X"

Private Sub Form_Load()

Set objimgList = Me.ImageList0.Object

cboImageList 'load imagelist-combo

'CreateMenu 'Create Drop-Down Menu
 
End Sub

Private Sub cboImageList()
Dim j As Integer
Dim strText As String

Set imgCombo2 = Me.ImageCombo2.Object
imgCombo2.ImageList = objimgList

For j = 1 To objimgList.ListImages.Count
    strText = objimgList.ListImages(j).Key
    imgCombo2.ComboItems.Add , , strText,j,,j
Next
    imgCombo2.ComboItems(1).Selected = True
End Sub

VBA Code Review.

In the global declaration area, we have defined the following variables:

  • imgCombo1 – the ImageComboBox control used for the project menu.

  • imgCombo2 – the ImageComboBox control used for displaying images from the ImageList control.

  • objImgList – an object variable representing the ImageList control on the form.

  • KeyPrfx – a constant variable assigned the character "X".

Within the Form_Load() event procedure, the objImgList variable is initialized with the ImageList control on the form using the following statement:

Set objImgList = Me.ImageList0.Object

This allows all pre-loaded images in the ImageList control to be accessed through the objImgList object.

Next, the procedure calls the cboImageList() subroutine, which adds all the images to the imgCombo1 control.

For now, the call to the CreateMenu() subroutine has been commented out.

Inside the cboImageList() subroutine, two variables are declared.

Next, the following statement assigns the second ImageComboBox control on the form to the object variable imgCombo2:

Set imgCombo2 = Me.ImageCombo2.Object

Similar to the TreeView control, the imgCombo2 control includes an ImageList property that links with the ImageList control. This allows the ImageComboBox to access the ImageList Properties. The statement below establishes that link:

imgCombo2.ImageList = objImgList

After this, a 'For…Next loop' is executed to iterate through the collection of images contained in the ImageList control. Each image is then processed and added to the imgCombo2 drop-down list.

The first item from the ImageList has its key value ("form_close") stored in the variable strText. In this example, we are using the Key value of the ImageList item as the text (or description) for the corresponding image in the ImageComboBox control.

Since no descriptive text is available, other than the Key, it is the most suitable option. The Tag property, on the other hand, is left empty because its purpose is different later when working with the drop-down menu.

The next statement is an important one that we need to examine closely: the Add method of the ImageComboBox control. This method is used to add items (with images) to the ImageComboBox list.

The general syntax of the statement is as follows:

imgCombo2.ComboItems.Add [Index],[Key],[Text],[Image],[SelImage],[Indentation]

All the parameters of the Add() method are optional. For our initial test run of this control, we will supply values only for the [Text], [Image], and [Indentation] parameters.

After previewing the result of this first test run (the image list view), we will discontinue using the [Indentation] parameter for this ImageCombo control, since it is not required for our intended design.

Note: We will need the Indentation property when creating the drop-down menu. This will allow the menu items to visually resemble Root Nodes and Child Nodes, just as they appear in the TreeView control.

At that stage, we will also make use of the [Key] parameter—assigning it the same value as the Text parameter—so that we can reliably access a specific menu item’s Tag property value.  

Image List with incrementing Indentation Param Setting.

The result of the first test run, displaying the image list in imgCombo2, appears as shown in the illustration above. This output is achieved by applying incremental values to the Indentation property for each item.

From this trial run, the effect of indentation is clearly visible: each successive item is shifted slightly to the right, one step further than the previous one. This feature is useful for positioning our project menu items so they visually resemble Root-Level and Child Nodes, similar to the TreeView Control structure. 

After the strText value ("form_close"), The first variable j refers to the ImageList’s index. The [SelImage] parameter is skipped in our test, and the next occurrence of j is used to set the Indentation level for each list item when displayed in the ComboBox.

For the initial test run, after reviewing the output, you may remove all parameters that come after the image index, as they are not required.

The next statement is:

imgCombo2.ComboItems(1).Selected = True

This selects the first item in the ComboBox. When the ComboBox item is selected using Code, the ImageCombo control Change() event is triggered. However, when an item is selected manually on the form, this event is not fired. To address this, the Update() event is used; it ignores manual updates and instead attempts to invoke the event explicitly through code.

Save the form frmMenu3Combo and open it in Normal View.  Expand the second ImageList ComboBox control and view the result.  Remove the commas and the variable < j > at the end, after the first variable < j >, retained for the ImageList index number.

The VBA Code of the Project Drop-Down Menu.

Now, let us move on to the second part of the form module VBA code, where we will learn how to create the Access Drop-Down Menu. In this section, we will also see how to open Forms, Reports, and Macros by selecting an item from the ComboBox control.

The second part of the VBA code consists of two main procedures:

  1. CreateMenu() – a subroutine that builds the project drop-down menu by adding menu items to the ImageComboBox control.

  2. ImageCombo1_Click() – the event procedure that responds when a user selects a menu option, triggering the opening of the corresponding Access object.

The code for these procedures is shown below:

Private Sub CreateMenu()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim strSQL As String
Dim strKey As String
Dim strText As String
Dim typ As Integer

Set imgcombo1 = Me.ImageCombo1.Object
imgcombo1.ImageList = objimgList

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 Len(Trim(Nz(rst!PID, ""))) = 0 Then
        strKey = KeyPrfx & CStr(rst!ID)
        strText = rst!Desc
        imgcombo1.ComboItems.Add , strKey, strText, 1, 2, 1 ' image index 1,2([image],[selectedimage])
        'imgcombo1.ComboItems.Add , strKey, strText, "folder_close", "folder_open", 1
    Else
        strKey = KeyPrfx & CStr(rst!ID)
        strText = rst!Desc
        imgcombo1.ComboItems.Add , strKey, strText, 4, 5, 4 'last param is spacing
        'imgcombo1.ComboItems.Add , strKey, strText, "left_arrow", "right_arrow", 4
     
        'Check for the presense of Type Code
        If Nz(rst!Type, 0) > 0 Then
                typ = rst!Type
                With imgcombo1.ComboItems
            Select Case typ
                'save type Code & Form/Report/Macro Name in Tag Property
                Case 1
                    .Item(strKey).Tag = typ & rst!Form
                Case 2
                    .Item(strKey).Tag = typ & rst!Report
                Case 3
                    .Item(strKey).Tag = typ & rst!Macro
            End Select
                End With
        End If
        
    End If
    rst.MoveNext
Loop
rst.Close
imgcombo1.ComboItems.Item(1).Selected = True
End Sub

Private Sub ImageCombo1_Click()
Dim strObject As String
Dim strTag As String
Dim typ As Integer

strTag = ImageCombo1.SelectedItem.Tag
typ = Val(strTag)
strObject = Mid(strTag, 2)

Select Case typ
    Case 1
        DoCmd.OpenForm strObject, acNormal
    Case 2
        DoCmd.OpenReport strObject, acViewPreview
    Case 3
        DoCmd.RunMacro strObject
End Select

End Sub

Before diving into the VBA code, take a moment to review the Table Image (the third image from the top of this page), especially if you have not already done so in the earlier session on Access Project Menu creation.

The table fields are defined as follows:

  • ID – An AutoNumber field that provides a unique identifier for each record.

  • Desc – Contains either the object type group names (Forms, Reports, Macros) or the actual object names of forms, reports, and macros.

  • PID (Parent ID) – Empty for the object group names (Forms, Reports, Macros). These empty PID values ensure that the group names appear at the leftmost position in the ImageComboBox drop-down menu, with one-character space indentation. All other items (child objects) are indented by four character spaces.

This indentation technique makes the menu items visually resemble Root-Level and Child-Level Nodes, similar to the structure in a TreeView control—except that the connecting Tree Lines will not be displayed.


In the ImageComboBox control, the selected item’s image is positioned at the leftmost side. The Group items (such as Forms, Reports, Macros) appear with a one-character indentation, while the child items under each group are indented by four character spaces.

The PID field plays an important role in this arrangement.

  • If the PID field value is empty, the record is treated as a Group Name (e.g., Forms, Reports, Macros).

  • If the PID field contains a value, the record is treated as an Access Object Name, which must be opened when the user clicks it. These items are displayed as child members of their respective groups.

Although the actual key values in the PID field are not significant in this context, we need the field to determine the hierarchy. Alternatively, the Type field can also serve this purpose.

The Type field contains the object type codes:

  • 1 – Form

  • 2 – Report

  • 3 – Macro

Based on this code, the next three fields—Form, Report, and Macro—store the actual object names. For clarity in design, these names have been kept in separate fields, though they could also be stored in a single column.

The Type Code and Object Name pair (say 2rptCategories) will be saved in the ImageComboBox’s Tag Property.

The CreateMenu() Subroutine.

Now, let’s move on to the VBA code of the CreateMenu() subroutine.

At the start of the procedure, the Database and other working variables are declared.

  1. The imgCombo1 object variable is initialized with the Me.ImageCombo1 control on the form.

  2. The 'imgCombo1.ImageList' property is then assigned the reference of the objImgList object, enabling direct access to the ImageList’s Index numbers and Key values.

  3. The Menu table is opened as a recordset using an SQL string.

  4. For each record, the PID field is checked:

    • If PID is empty, the record is treated as an object group name (e.g., Forms, Reports, Macros).

    • In this case, the ID value is prefixed with the constant "X" and stored in the variable strKey, while the Desc field value is stored in strText.

  5. The Add() method of the ImageComboBox control is then called, and the first item is added to the drop-down menu.


imgcombo1.ComboItems.Add , strKey, strText, 1, 2, 1

The first parameter (Index) is omitted—Access assigns it automatically.

  • Key: strKey contains the ID value prefixed with the constant X (e.g., X1).

  • Text: strText holds the Desc field value.

  • Image / SelImage: 1 is the index (or "folder_close" key) of the first ImageList image; 2 is the index (or "folder_open" key) of the second image.

  • Indentation: 1 Indents the item one level.

Example:

' Add a group item (e.g., "Forms") imgCombo1.ComboItems.Add , strKey, strText, 1, 2, 1 ' …or with image keys: ' imgCombo1.ComboItems.Add , strKey, strText, "folder_close", "folder_open", 1

Note: To confirm image index order, refer to the ImageCombo2 display you created earlier. If you like, you can also prepend the image index to the Text (not the Key) for clarity—for example: "1 form_close", "2 form_open".

If the PID field value is non-zero, then the record represents an actual menu option (not a group header). In this case, the item is added under the Else clause.

The process is similar to how we added the group items earlier, but with a few differences:

  • For the [Image] and [SelImage] parameters, we use the ImageList item index values 4 and 5.

  • The Indentation parameter is set to 4 character spaces, so that these items appear as child members under their respective group headings.

Example:

' Add a child item (e.g., an actual Form, Report, or Macro) imgCombo1.ComboItems.Add , strKey, strText, 4, 5, 4 

This ensures that the group names (e.g., Forms, Reports, Macros) stay at the root level, and their associated objects are properly indented beneath them, visually simulating a TreeView hierarchy in the ImageComboBox.

Within the ImageCombo item’s Add() method, under the Else clause, we also need to store the Access Object Name along with its Type Code in the item’s Tag property.

For example:

' Save object details (Form Name + Type Code) in the Tag property ImageCombo1.ComboItems.Item(strKey).Tag = "frmData Entry;1"

Here:

  • "frmData Entry" is the object name (in this case, a form).

  • 1 is the Type Code, which identifies it as a form (2 = report, 3 = macro).

When the user selects this item from the drop-down menu, the ImageComboBox Click() Event fires. In this event procedure:

  1. The Tag property value of the selected item is retrieved.

  2. The value is split into the object name and the Type Code.

  3. The Type Code is checked:

    • If it equals 1, the item is a form, and the form name is opened using:

    DoCmd.OpenForm "frmData Entry"

This same logic will later be extended for Reports and Macros, using their respective Type Codes.

With this, all the records from the Menu Table are successfully added to the ImageComboBox control.

The statement:

imgCombo1.ComboItems.Item(1).Selected = True

sets the first item as the default selection in the ImageComboBox. When this line of code executes, the Change() event is triggered; however, selecting an item directly in Form View does not fire the Change event.

Note: Before running the form to test the drop-down menu, make sure to remove the comment symbol from the CreateMenu call in the Form_Load() event procedure. This line was commented out earlier during trial runs when we were testing image display in the ImageCombo2 control.

The ImageCombo1_Click() event fires whenever the user selects an item from the drop-down menu. In this procedure, the selected item’s Tag property is parsed to retrieve the Type Code and the Object Name, and the corresponding Access object is opened using:

DoCmd.ObjectType ObjectName

Finally, for your reference and practice, the Demo Database (ProjectMenuV221.accdb) download Link is given below.

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

Assigning Image Icons to TreeView Nodes.

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 Project. We 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 a left-pointing arrowhead icon in the normal view and change to a right-pointing arrowhead when the node is in the selected mode.

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—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 in 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 is effective in 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 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 together 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 TreeView Nodes.

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

The TreeView Object Add() Method’s last two parameters are for the Node Images.  Let us examine 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 MS Word Mail Merge from Access 2007
  3. Automated Email Alerts

Share:

Microsoft TreeView Control Tutorial

A. TreeView Control Tutorial.

The Microsoft TreeView Control, part of the Microsoft Windows Common Controls library, is a powerful component for displaying related data in a hierarchical node structure. It can represent information such as index entries and subentries, folder structures similar to the left pane of Windows Explorer, or any collection of related items, complete with tree lines, checkboxes, and graphical icons.

In addition to the TreeView Control, we will also use the ListView and ImageList controls, which are part of the Microsoft Windows Common Controls ActiveX library, to enhance functionality and visual presentation within Microsoft Access applications.

In the coming weeks, we will explore how to design, build, and customize a TreeView Control from scratch. As a preview of the concepts and implementations we will cover, I will also share several TreeView demonstration images illustrating the final results we will be working toward.

B. Sample Demo Images.

      Nodes in the Collapsed state.

  1. The Sample Demo TreeView Image with all Nodes in Collapsed form.

     Nodes in the Expanded View.

  2. The above TreeView Control Nodes are in the expanded view.

    With Arrowhead Image Icons.

  3. The TreeView Sample Display, with arrowhead Image Icons displayed to the left of each Node Text.

    Folder Images for Root-Level Nodes, others with arrowheads.

  4. Next, we will examine a TreeView display integrated with related data presented in a subform. The root-level nodes are visually enhanced with two graphical states: a closed folder icon in the default state and an open folder icon when selected. Selecting a root-level node not only changes its icon but also automatically expands the node to display its associated child nodes.

    The subform dynamically updates to display information related to the selected root-level node. In addition, selecting specific child nodes can trigger the display of another form, which is normally kept in a hidden state to present additional related details. 

    TreeView and ListView Controls.

  5. In the next form layout, there are two panels. The left panel contains the TreeView control, which displays nodes representing product categories. When a category node is clicked, the right panel—comprising the ListView control—updates to display the related product items, along with their quantities and list prices in separate columns.

C. Creating Sample Data for Trial Run.

Let us try out the TreeView Control with some sample data shown below, based on the first two images displayed at the beginning of this Page.

The sample data table contains three fields:

  1. ID – An AutoNumber field that generates unique ID numbers. AutoNumber is used here for convenience, but regardless of the type, each record in the table must have a unique ID value. If the ID is numeric, it must be converted to a string (with at least one alphabetical character) before adding it to the TreeView control.

  2. Description (Desc) – Contains the node descriptions. The entries in this column are logically related to one another.

  3. ParentID – A numeric field that identifies the parent node for each record. This value should also be converted to a string before using it in the TreeView control.

To build the hierarchy, we need to understand how the description values relate to one another. Based on these relationships, appropriate values are entered into the ParentID field.

For example, the logical hierarchy could represent:

  • Authors → Publishers → Bookstores where the books are sold.

  • Members of a family tree.

  • Product categories → Products → Stock → Price.

This related information may not always exist in a single column or table—it could be spread across multiple columns or even different tables.

The ParentID field plays a crucial role in defining the hierarchical arrangement of nodes. If the ParentID field is empty, the record is treated as a root-level node. A child node must always have its ParentID Field populated with the parent record ID.

A root-level node can have one or more child nodes, and a child node can, in turn, have its own child nodes, creating multiple hierarchy levels.

We will first load the sample data into a TreeView control to view its initial arrangement. Then, by filling in the ParentID field with related IDs, we can reorganize the nodes into the desired logical order.

D. Windows Common Controls Library File.

  1. First, open an existing database or create a new one.
  2. Press ALT + F11 to open the VBA editor, then choose References… from the Tools menu.
  3. In the list of available references, look for Microsoft Windows Common Controls and select it.

    • If the file is not listed, click Browse… and locate MSCOMCTL.OCX in the Windows system directory.

    • In Windows 7 (64-bit), you will typically find it in the SysWOW64 folder.

    • Once selected, click OK to close the References dialog.

  4. Create a Table with the following structure:

    Right-click to open the Large Image in a New Window.

  5. Name the Table as Sample and save it.

  6. Add about twelve records in the Table, as shown in the data view Image above. 

    E. Creating TreeView Control on Form

  7. Create a New blank Form.

  8. Click on the ActiveX Controls button from the Controls Group, find the Microsoft TreeView Control, then select it.

  9. Click OK to insert a TreeView control on the Form.

  10. Drag the TreeView control slightly down and to the right to leave some space along the top and left edges.

    Next, use the bottom-right sizing handle to stretch the control toward the right and downward, enlarging it to match the proportions shown in the sample image below.

  11. Display the control's Property Sheet and change its Name Property Value to TreeView0.

  12. Display the VBA Editing Window of the Form.

  13. F. Access VBA Code.

  14. Copy and paste the following VBA Code into the Module, overwriting the existing lines of code there:
    Option Compare Database
    Option Explicit
    
    Dim tv As MSComctlLib.TreeView
    Const KeyPrfx As String = "X"
    
    Private Sub Form_Load()
    Dim db As Database
    Dim rst As Recordset
    Dim strSQL As String
    Dim nodKey As String
    Dim ParentKey As String
    Dim strText As String
    
    Set tv = Me.TreeView0.Object
    
    strSQL = "SELECT ID, Desc, ParentID FROM Sample;"
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)
    
    Do While Not rst.EOF And Not rst.BOF
        If Nz(rst!ParentID, "") = "" Then
            nodKey = KeyPrfx & CStr(rst!ID)
            strText = rst!Desc
            ‘Add the TreeView Root Level Nodes
            tv.Nodes.Add , , nodKey, strText
        
        Else
            ParentKey = KeyPrfx & CStr(rst!ParentID)
            nodKey = KeyPrfx & CStr(rst!ID)
            strText = rst!Desc
            ‘Add the Record as Child Node
            tv.Nodes.Add ParentKey, tvwChild, nodKey, strText 
            
        End If
        rst.MoveNext
    Loop
    rst.Close
    
    Set rst = Nothing
    Set db = Nothing
    
    End Sub
    
    
  15. Save the Form with the name frmSample, but don’t close the VBA Window.

    G. VBA Code Review – Line by Line

    Let’s take a quick look at the VBA code and understand what it does.

    In the Global Declaration area of the Form module:

    • tv is declared as a TreeView object.

    • KeyPrfx is declared as a String constant with the value "X".

    The TreeView Node’s Key must always be a string and must contain at least one non-numeric character. Since our sample table’s key values are purely numeric, we convert them to strings and prefix them with the letter "X".

    • Example: 1"X1"

    • Simply converting a numeric value to a string (without an alphabet) will not be accepted as a valid Node key.

    Note: If the Node Key and Parent Key are already in alphabetic or alphanumeric form, conversion is unnecessary. All Node keys must still be unique.


    In the Form_Load() event procedure:

    1. Database and Recordset objects are declared, along with four string variables.

    2. The statement:

      Set tv = Me.TreeView0.Object

      assigns the TreeView0 control on the form to the object variable tv.

    3. OpenRecordset() Opens the sample table records using the SQL string strSQL.

    4. The Do While...Loop ensures the recordset is processed only if it is not empty; otherwise, the loop exits and the procedure ends.


    Determining Node Type

    • If the ParentID field is empty, the record becomes a Root-level Node.

      • A Root Node needs only a unique Key and Text (from the ID and Desc fields).

    • If the ParentID field has a value, then the record becomes a Child Node of either a Root Node or of an upper-level Child Node.


    Building the Node Key & Text.

    • nodKey is created by converting the ID field to a string and prefixing it with "X". Example: ID = 1nodKey = "X1".

    • strText stores the Desc field value. This keeps the Nodes.Add() parameters short and readable, especially when field references are long.


    Adding the Node

    The statement:

    tv.Nodes.Add(...)

    calls the Add() method of the TreeView’s Nodes collection to insert the node into TreeView0 on frmSample.


    Syntax of Add() method:

    tv.Nodes.Add([Relative], [Relationship], [Key], [Text], [Image], [SelectedImage]) As Node
    • All six parameters are optional.

    • Calling it without parameters adds an empty Root Node (a blank tree line).

    Requirements:

    • Root Node: Needs only Key and Text.

    • Child Node: Requires both [Relative] and [Relationship].

      • Omitting either adds it as a Root Node (no error occurs).

      • [Relative] is the Node Key of the existing parent (from ParentID).

      • [Relationship] is the constant tvwChild (value 4), identifying it as a child of the parent node.

The other Constant values for the Relationship Argument are used to position the Child Nodes to a specific location.  Constant Values are as follows:

tvwFirst = 0,  places as the first Node, at the level of the relative Node.

tvwLast = 1,  places as the last Node, at the level of the relative Node.

tvwNext = 2,  places the Node after a specified Node.

tvwPrevious = 3, places the Node immediately preceding the specified Node.

Note: You can experiment with different values in the Relationship argument and run the code in Debug Mode, keeping the VBA editor and the form in Normal View side by side. Observe how the nodes are arranged during each iteration of the code. This will help you understand the effect of each relationship type.

This is useful when editing the TreeView—such as deleting an item, inserting another item in its place, or adding a new node at a specific location.

A node referenced in the [Relative] argument must already exist in the Nodes collection before you can add a child node to it. Otherwise, it will generate an error.

The process continues until all records in the recordset have been processed.

Note: You may need to review the VBA code again after running the demo to reinforce your understanding.

H. The First Trial Run.

Open the Form in Normal View.  The Trial Run result looks like the Image given below.

It doesn’t look much different from a regular list box at the moment. This is because we have not yet assigned any values in the ParentID field in our sample table. To arrange items hierarchically in the TreeView control, we must define relationships between the rows in the table.

I. Understanding the Relationship Between Records

Open the sample table and examine how the records relate to each other.

We will keep the Database item as a root node. The database object also contains several top-level objects—Application, DBEngine, Workspaces collection, and Databases collection—which we have not included here.

Next, we have the Tables group item with ID value 2.

In the following records, we see the Table, Fields collection, and Field item, which are related to the Tables group. Our goal is to place the Table, Fields, and Field records under the parent node Tables (ID value 2).

In this hierarchy, the Tables record is the parent node, and the Table, Fields, and Field records are the child nodes.

J. Updating the ParentID Field

To achieve this structure, we need to update the ParentID field value 2 for the Table, Fields, and Field records (the node key of Tables).

Update only these records, then close the table. Once completed, your records should look like the example shown in the image below.

Now, open frmSample in Form View and check the TreeView control.
At first glance, the display will look exactly the same as before—no visible changes.
However, the updates you made are already in effect; they’re just not reflected visually yet.


K. The TreeView Control Property Sheet. 

The TreeView control has its own Property Sheet, and these settings influence how the control appears. We’ll adjust one of these properties before returning to the TreeView to see the change.

  1. Switch frmSample to Design View.

    1. Right-click the TreeView control.

    2. From the shortcut menu, highlight TreeCtrl_Object and select Properties.

    3. The Property Sheet will now appear, as shown below.

    4. The Settings on this Property Sheet change the appearance of the TreeView Display.

      The top-left Property Style has already selected Option 7 (tvwTreeLinesPlusMinusPictureText), the maximum features available.

    5. Change the LineStyle Property Value = 1 (tvwRootLines) and click the Apply button, then click OK to close the Property Sheet.

      L. Running After the LineStyle Property Change

    6. Save the form and open it in Normal View.
      You’ll now see the tree lines displayed correctly.

    7. The Tables node now shows a plus (+) sign to its left, indicating that it has one or more child nodes at the next level, which are currently collapsed.

      • Click the plus (+) sign to expand the node and reveal all child nodes sharing the same ParentID.

      • Click the minus (–) sign to collapse them again, hiding the child nodes and changing the symbol back to a plus (+).

      When expanded, the display will resemble the image shown below:

      Updating the ParentID for Other Records.

      Next, we will establish the parent–child relationships for the remaining records.

      1. Forms and Controls

        • Update the ParentID field of the Form, Controls, and Control records with the Forms item's ID value (Node-Key).

        • This ensures that these records will appear under the Forms node as its child nodes in the TreeView.

      2. Reports and Controls

        • Similarly, update the ParentID field of the Report and Control records with the Reports record’s ID value (Node-Key).

        • This positions them under the Reports node as its child nodes.

    8. Once the updates are complete, your Sample Table should match the ParentID values shown in the illustration below:

      After applying the above changes, open the form and expand all the nodes in the TreeView. The display should now resemble the image shown below, with every parent node and its corresponding child nodes fully visible.

      All child nodes related to the root-level nodes—Tables, Forms, and Reports—are grouped under their respective parent nodes. However, a child node may also have a parent, a grandparent, or even a great-grandparent node, depending on the hierarchy.

      N. Arranging All Objects in a Logical Hierarchical Order
      Let’s take the first root-level node, Tables, as an example. Logically:

      • Field (record ID 5) is directly related to the Fields collection (record ID 4).

      • The Fields collection is related to the Table.

      • The table is part of the Tables collection.

      This means that each item in the group (record numbers 5 through 2) is related to the step above it in the hierarchy.

      Next, we will position these child nodes under their respective parent nodes in the correct order and see how the arrangement appears in the TreeView control.

    9. Open your Sample Table and change the ParentID values of the Tables related to Child Records as shown below:

    10. The record Field with ID 5 has Field (record ID 4) as its parent. Therefore, update the record with ID 5's ParentID field value to 4.

      Similarly:

      • Record 4 (Field) has record 3 (Table) as its parent, so we set its ParentID to 3.

      • Record 3 (Table) has record 2 (Tables) as its parent, so we set its ParentID to 2.

      Note: The records do not have to appear next to each other in the table to establish this hierarchy.

      After making these changes, save the table and open frmSample to view the results. Your TreeView display should now resemble the image shown below, with all nodes expanded.

    The Child Node of a Root-level Node can be a Parent Node to its own Child or Children.  This way, it can go several steps down the tree.

    Change the other two groups of Child Node's ParentID field values.  When you do that correctly, it will look like the image given above.

    Download TreeView Demo Database.


    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:

PRESENTATION: ACCESS USER GROUPS (EUROPE)

Translate

PageRank

Post Feed


Search

Popular Posts

Blog Archive

Powered by Blogger.

Labels

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