Home Article Index Links Newsletter

Deze pagina in het NederlandsHome > Article Index > Treeview control >

An MSForms (all VBA) treeview; How to use

This page outlines the minimum steps needed to add this treeview control to your own Excel or Word VBA project. For Access the instructions are different, those can be found in the Access download.

The container control

Open the designer window of your userform and add a frame. This is where the treeview will be built. We recommend these properties (which are of course optional):

 Recommended properties for the container frame
Recommended properties for the container frame

Your userform would look like this:

 The container frame on your userform
The container frame on your userform

If you want images in your treeview, you'll have to add another frame (we called it frmImageBox) and then add Image controls within that frame. Set the Visible property of the frame to false to avoid it showing up on your userform. Like so:

 The images frame on your userform
The images frame on your userform

If you want to add images, make sure you name the new image controls properly, as it is the name of the imagecontrol you need to pass to the cNode class to get that image displayed. An easy way to get the images is to copy the entire frame with images from our userform to yours.

Class modules

Copy the class modules clsNode and clsTreeView to your project (you can simply drag them to your project). Your project (if you started with an empty workbook) would look like this:

 Project with class modules in place

The project with class modules in place

So far, things have been simple. The next parts are a bit more compex, but nothing too hard!

Code behind your userform

For the treeview to work, your userform needs some code, in particular these elements are necessary:

That's it!

Variable declaration

Add this code to the declaration section of your userform:

'Add this to your form's declaration section
Private WithEvents mcTree As clsTreeView

That's it! No more variables needed!

Of course the name of the variable mcTree is totally up to you.

If you need another (independent) treeview on your form, simply add another frame to hold it and an additional variable in the forms declaration section (of course you name it differently than the other one) like the one shown here.

Initialisation

In the intialisation routine of your form, you need code that adds nodes to the tree and when you're done adding nodes, you need to set some properties of the treeview. Then you'll want the treeview to be displayed.

Adding an instance of the treeview to your form

Adding the instance is easy:

    'Instantiate a new instance of the treeview class and set a module level variable to hold it:
    Set mcTree = New clsTreeView

Now tell the tree class instance which frame is its container:

    With mcTree
        'The VBA treeview needs a container Frame control on the userform.
        'Just draw a frame on your form where the treeview should appear
        'Make sure the frame has no border and no caption
        'Set it to show both scroll bars. (Keepscrollbarsvisible to both)
        'Set it to the special effect "Sunken"
        'Note that node label formats such as back/fore colors and font adopt
        'the frame container's properties, so change if/as required.
        '(you can copy the frame named frmDemo from this userform )
        
        'Then pass this frame to the TreeControl of the treeview class

        Set .TreeControl = Me.frmDemo
        'Title for message boxes:
        .AppName = Me.AppName

Note that most of the code listed below is within the With mcTree ... End With structure.
 

Setting initial look

You'll want control over the look and feel of your treeview, here is some example code (this code comes immediately below the code sample show above):

        'Set some properties
        .CheckBoxes = True
        .RootButton = True
        .LabelEdit = 0 'default is 0 can be edited (like LabelEditConstants tvwAutomatic/tvwManual)
        .Indentation = 20 * 0.75 'defaults to 11.25
        .NodeHeight = 16 * 0.75 'defaults to 12
        .ShowLines = True
        'If your form has icons in an iconframe (called frmImageBox),
        'you could use icons for the expand and collapse buttons:

        Call .ExpanderImage(Me.frmImageBox.Controls("Win7Minus").Picture, Me.frmImageBox.Controls("Win7Plus1").Picture)

If your treeview needs to show images, add a frame control with Image controls inside. Lets call it frmImageBox. This is how you tell the class where the images are:

        Set .Images = Me.frmImageBox

That is just about all the plumbing you need to get started.

Adding nodes

First of all, a couple of variables are needed to add nodes:

'The root of the tree
Dim cRoot As clsNode
'A node
Dim cNode As clsNode
'An extra variable should you need to remember a certain node
Dim cExtraNode As clsNode

Next we'll start by building the rootnode:

        ' add a Root node with main and expanded icons and make it bold
        Set cRoot = .AddRoot("Root", "Root Node", "FolderClosed", "FolderOpen")
        cRoot.Bold = True

Note that the tree can have more than one rootnode, there is a special RootNodes collection to which you automatically add new roots by calling the AddRoot method.

As you can see, we assume there are two icons in the image frame called FolderClosed and FolderOpen respectively.

Now we want to add children to the root. This is the code from our demo form:

        'Add branches with child nodes to the root:
        'Keys are optional but if using them they must be unique,
        'attempting to add a node with a duplicate key will cause a runtime error.
        '(below we will include unique keys with all the nodes)
        Set cNode = cRoot.AddChild("1", "1 A", "FLGNETH")
        cNode.Bold = True
        
        'Add a 2nd branch to the root:
        Set cNode = cRoot.AddChild("2", "2 B", "FLGSWED")
        cNode.Bold = True
        'If you want to add more child branches to a branch later on, use a variable to store the branch.
        Set cExtraNode = cNode.AddChild("2.1", "2.1  level 2", "NOTE03", "NOTE04")  ' include an expanded icon
        cExtraNode.Expanded = False   ' this node will initially be collapsed,
                                      ' its child node controls will be created when expanded


        'To add a branches to a branch, make sure you set a variable to its 'main' or parent branch when created
        'Then use the Branch's AddChild method, here to create multiple levels

        Set cNode = cNode.AddChild("2.2", "2.2  level 2", "NOTE03", "NOTE04")    ' include an expanded icon
        Set cNode = cNode.AddChild("2.2.1", "2.2.1  level 3", "OpenBook")
        Set cNode = cNode.AddChild("2.2.1.1", "2.2.1.1  level 4", "Scroll")
        Set cNode = cNode.AddChild("2.2.1.1.1 ", "2.2.1.1.1   level 5", "GreenTick")

        'Now add another branch to the branch we stored earlier
        cExtraNode.AddChild "2.1.1", "2.1.1  level 3", "OpenBook"

        'Add a 3rd branch to the root, with a child node
        Set cNode = cRoot.AddChild("3", "3 C", "FLGUK")
        cNode.Bold = True
        cNode.AddChild "3.1", "3.1  level 2", "Scroll"

        ' and add a 4th branch to the root
        Set cNode = cRoot.AddChild("4", "4 D", "FLGUSA02")
        cNode.Bold = True
        cNode.Caption = "4 D  +" & mlCntChildren

        ' add a bunch of child nodes to the 4th branch
        For i = 1 To mlCntChildren  ' 15
            Set cExtraNode = cNode.AddChild("4." & i, "  4.1 " & Right$("000" & i, 4), "Scroll")
            '  add some alternate row colour formats
            If i Mod 2 Then
                cExtraNode.BackColor = RGB(255, 255, 220) ' pale yellow
                cExtraNode.ForeColor = RGB(180, 0, 0)     ' dark red font
            End If
        Next

Display the tree

Displaying the tree is as simple as calling one method:

    'Fill the tree
    .Refresh

Termination

When the form goes out of scope (i.e. out of memory) you need to remove the treeview from memory:

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Make sure all objects are destroyed
    If Not mcTree Is Nothing Then
        mcTree.TerminateTree
    End If
End Sub

Feedback

We've worked hard to create a reliable and performant treeview. If you encounter bugs, please let us know so we can work on them. Better yet: if you have fixed a bug you found, send us your updated code so we can add the fixes you made.

In any case, comments (and compliments) are welcome!

 


 


Comments

Showing last 8 comments of 268 in total (Show All Comments):

 


Comment by: Adelina Trandafir (20-12-2020 13:52:00) deeplink to this comment

Let me start by wishing you a Merry Xmas and a happy New Year! :)

I have 2 questions this time, for when you have the time:
1) Is it possible to set the node height individually, not as a property for the whole tree?
2) Is it possible to set the Control.Enabled=False at the creation of the tree, rather than after?
3) This is the big one: can you point me in the right direction as to have another column in each node? - I know that probably this is something difficult and may exist in a payed version, but i was trying to hone my skills in VBA (pointless - I know) and to adapt your code a little (I love doing that). The second column doesn't have to be selectable or anything, I just need a way to present data in tabular form and i hate formating the text every time.
4) BONUS QUESTION: Is there a way to insert some sort of node separator line?

Thank you so much for your work and for all your answers!

Adelina, a VBA freak.

P.S. There were only 2 questions at the beginning, but then i remembered I have more :D


Comment by: Peter Thornton (20-12-2020 18:36:00) deeplink to this comment

Hi Adelina,

Thanks, and let me return the same good wishes to you:)

#1 Not impossible but a lot of work to implement variable node heights. With all same heights it's simple to calculate the vertical position of each visible (ie expanded) node, as required after collapse/expand and scrolling, also for 'ScrollToView'.

#2 Simply mcTree.TreeControl.Enabled = False. In Excel & Word you could disable the Frame control at design, and enable it when you want during run-time

#3 That's actually easier than #1, still quite a lot of work though. I haven't looked into it but from memory I might have been sent example, a long time ago.

However if you have a column of data and with nodes under the same parent each with similar data, consider moving all the sibling 'leaf' nodes into a multi-column List to give something overall like an 'Explorer' type control. FYI The 'PRO' Treeview and ListGrid are designed to work as a pair like that.

#4 Similar to #1 but even more complicated!


Comment by: Adelina Trandafir (8-1-2021 11:34:00) deeplink to this comment

Happy new year and hopefully a healthy one too :P
I have an easier question this time: is it possible to make the rows in the tree have 0 (zero) space between them? Thank you and i hope you're doing fine

Your friend and follower,
Adelina T.


Comment by: Peter Thornton (9-1-2021 14:17:00) deeplink to this comment

Hi Adelina,

Thanks, and the same to you:)

With the demo run the form, increase the font sise to about 12 and decrease NodeHeight to 10 (not high enough to display the full font height). Run demo2, expect now to see the NodeHeight has automatically increased to accommodate the larger Font size.

If you select the coloured nodes under node-4D there shouldn't be any gaps or spaces vertically between the nodes.

It is possible to avoid gaps in all scenarios but a bit of work to adapt the treeview code. FWIW that's all handled in the 'pro' version and no gaps with any combination of font-size & NodeHeight, also height is automatically sized for icons.


Comment by: Adelina Trandafir (17-1-2021 11:22:00) deeplink to this comment

Thanks a lot for everything. You are right with the pro version and i want it, especially since i want to pay you for everything, but i can't find the price tag anywhere on the site.
:)


Comment by: Peter Thornton (17-1-2021 13:32:00) deeplink to this comment

Hi Adelina,

There are enquiry links on the main Treeview page, just below the screenshot of the ListGrid. However I have emailed you off-line with details.


Comment by: Peter Poppe (21-1-2021 04:51:00) deeplink to this comment

Is there a way to expand a node branch? The node has the node has an expanded property but when you set this to true nothing happens except the + becomes an -. The tree has an ExpandedNode property, but the same happens. I do not want to expand the entire branch just open it one level. Thanks.


Comment by: Jan Karel Pieterse (21-1-2021 10:04:00) deeplink to this comment

Hi Peter,

After changing a property of a node (or the tree as a whole), you must call the Refresh method of the treeview class instance to display the change. You can first have your code make all the property changes and then use a refresh at the end to have them all come into effect.


Have a question, comment or suggestion? Then please use this form.

If your question is not directly related to this web page, but rather a more general "How do I do this" Excel question, then I advise you to ask your question here: www.eileenslounge.com.

Please enter your name (required):

Your e-mail address (optional, will only be used to inform you when your comment is published or to respond to your question directly):

Your request or comment (max 2000 characters):

To post VBA code in your comment, use [VB] tags, like this: [VB]Code goes here[/VB].

I give permission to process this data and display my name and my comment on this website accoring to our Privacy Policy.