MS Forms Tree View Slow Loading Issue (1 Viewer)

Pac-Man

Active member
Local time
Today, 10:26
Joined
Apr 14, 2020
Messages
416
Hi,

I want to use MS Forms tree view for one of my folder and used span folder option to populate the tblFileFolder using demo shared by @MajP at Hierarchical Data, Recursion, Tree-Views, and a Custom Class to Assis. No of records in the table are 3000. I am then using TreeViewRecordLoader Class to generate my MS Forms tree view which add nodes from the table recursively due to which it takes about a minute or so and during which it seems that access got stuck. Is it possible to load the tree view faster instead of adding one by one node or is there any other way to speed up the tree view generation?

I posted this question in the original thread by @MajP and was suggested to start new thread (which I should have done in the first place).

The file structure is now already stored in the table and is not being done again. That was a one time process for my case. Now the time is taken in loading the tree. Light load option was suggested which seems better option but it was for TreeView control and unfortunately not available for MS Forms Tree view.

Best Regards
 
Last edited:

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 13:26
Joined
May 7, 2009
Messages
19,243
Is it possible to load the tree view faster instead of adding one by one node or is there any other way to speed up the tree view generation?
you need to add it one by one. contrast to a List or Listview you just set the List to an Array and that's it.
 

Edgar_

Active member
Local time
Today, 00:26
Joined
Jul 8, 2023
Messages
430
Have you tested this approach?

It just adds all nodes as orphans and then it gives them parents. It's not recursion, but it'd be good to know if it loads faster.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
So everyone knows what we are talking about there are two Treeviews that I know of that work in Access.
The most common is the ActiveX Treeview located in the MS CommonControls 6.0
The other was made by JKP and can be found here towards the bottom.
The JKP version is home made using MS Forms controls native to VBA. It is an extremely impressive amount of vba.
The advantage of the native MS Forms version is that it overcomes a lot of portability issues of using Active X.
Most of the methods and properties mirror the Active X control so it is relatively easy to build/convert a JKP treeview without learning the class methods and properties.


Let me explain the logic for the light load that I coded into my class that uses the ActiveX control.
Instead of fully populating the Tree with all the nodes, I only populate the top level visible nodes. For each visible node I also only load one child node and for each child node a single child node (recursivel)
In my demo in the below thread, I load a Treeview with 10K records and it loads instantaneously:

When the tree loads the following nodes are loaded and only one child (no sub nodes).
Large1.png



The reason for the child node is that is how you get the Plus Sign. If there was only the 9 visible nodes, none of these nodes would appear expandable.

Assume you Click on Linda Powlowski. Additional nodes get loaded. The rest of linda's "child" nodes, and again one child node for each loaded child.

Large2.png


So originally Mallie was already loaded. It then loads Charlotte and the rest of Linda's child nodes.

So yes this same functionality could be added to the MSForms Class I built. Did this take me a long time to figure out? Yes. But since the two "controls" mirror each other I should be able to figure it out a lot faster. So when I get time I will see if I can add it. I always planned to write a complete helper class for this, but never got around.

Here is some of the light load logic. It only differs from the full load in that there is no loop to recurse all children. It recurses a single child only.
Code:
Public Sub addLiteBranch(parentIDValue As Variant, identifier)
  On Error GoTo errLable
  Dim strCriteria As String
  Dim bk As String
  Dim currentID As Variant
  Dim currentText As String
  Dim currentNode As Node
  Dim currentImage As String
  Dim ParentNode As Node
  Dim strKey As String
  Dim rsTree As DAO.Recordset
  Set rsTree = Me.Recordset
  strCriteria = Parent_ID_Field & " = '" & parentIDValue & "'"
 
  'Since it is not a root node must determine the parent node.  All node keys are "ID " & the primary key
  Set ParentNode = Me.Nodes(parentIDValue)
  rsTree.FindFirst (strCriteria)
  'Only going to get the top node
  If Not rsTree.NoMatch Then
    currentID = rsTree.Fields(ID_Field)
    currentText = rsTree.Fields(Node_Text_Field)
    identifier = rsTree.Fields(Identifier_Field)
   Set currentNode = Me.Nodes.Add(ParentNode, tvwChild, currentID, currentText)
   currentNode.Tag = identifier
   If mLoadImages Then
     currentImage = Nz(rsTree.Fields(Image_Name_Field), "")
     If currentImage <> "" Then currentNode.Image = currentImage
   End If
   bk = rsTree.Bookmark
   Call addLiteBranch(currentID, identifier)
    rsTree.Bookmark = bk
    rsTree.FindNext (strCriteria)
  End If
  Exit Sub
errLable:
  MsgBox Err.Number & " " & Err.Description & " In addBranch"
  If MsgBox("Do you want to exit the loop?", vbYesNo, "Error In Loop") = vbYes Then
     Exit Sub
   Else
     Resume Next
   End If
End Sub

More importanly when you click on a node it does the same
Code:
Private Sub mTVW_Expand(ByVal Node As MSComctlLib.Node)
 'Flush out any remaining nodes in this expanded level and liteload child level
 'This procedure is associated with a light load. Occurs when you expand the branch
  On Error GoTo errlbl
  Dim strCriteria As String
  Dim bk As String
  Dim currentID As Variant
  Dim currentText As String
  Dim currentNode As Node
  Dim ParentNode As Node
  Dim currentIdentifier As String
  Dim currentImage As String
  Dim rsTree As DAO.Recordset
  'Debug.Print Node.Text & " " & "Selected Node"
  If Node.Children > 1 Then Exit Sub ' node has already been expanded
  Set rsTree = Me.Recordset
  strCriteria = Parent_ID_Field & " = '" & Node.key & "'"
  rsTree.FindFirst (strCriteria)
  Debug.Print strCriteria
  If rsTree.NoMatch Then
  '  MsgBox "There is no record with a Parent ID of " & Node.key
  End If
 
  Do Until rsTree.NoMatch
   currentID = rsTree.Fields(ID_Field)
   Debug.Print currentID & " current"
   currentText = rsTree.Fields(Node_Text_Field)
   currentIdentifier = rsTree.Fields(Identifier_Field)
   If Node.Child.key = currentID Then
     Node.Child.Tag = currentIdentifier
     RaiseEvent ExpandedBranch(Node.Child)
   Else
     'If you are light loaded and drag drop then you will get a duplicated key error
     Set currentNode = mTVW.Nodes.Add(Node.key, tvwChild, currentID, currentText)
     currentNode.Tag = currentIdentifier
     If mLoadImages Then
       currentImage = Nz(rsTree.Fields(Image_Name_Field), "")
       If currentImage <> "" Then currentNode.Image = currentImage
     End If
     RaiseEvent ExpandedBranch(currentNode)
     bk = rsTree.Bookmark
     Call addLiteBranch(currentID, currentIdentifier)
   End If
   rsTree.Bookmark = bk
   rsTree.FindNext (strCriteria)
  Loop
  Exit Sub
errlbl:
  If Not Err.Number = 35602 Then 'this is a duplicate key caused by drag drop and light loaded
    MsgBox Err.Number & " " & Err.Description & " Key: " & currentID & " In Treeview Expand."
  End If
End Sub

So it may be as simple as trying to incorporate these methods into my MS Forms wrapper class. But there may be additional dependencies that need to be coded.
 

Pac-Man

Active member
Local time
Today, 10:26
Joined
Apr 14, 2020
Messages
416
It just adds all nodes as orphans and then it gives them parents. It's not recursion, but it'd be good to know if it loads faster.
Thanks for reply. I couldn't check that out since I was away from PC on which the project is located. I am quite sure that it will take more time to load the TV as the time is being taken in the loop which iteratively add one by one nodes. Since the approach you referred run the loop once to add all the nodes, and then again to add the parent.

So everyone knows what we are talking about there are two Treeviews that I know of that work in Access.
The most common is the ActiveX Treeview located in the MS CommonControls 6.0
The other was made by JKP and can be found here towards the bottom.
The JKP version is home made using MS Forms controls native to VBA. It is an extremely impressive amount of vba.
The advantage of the native MS Forms version is that it overcomes a lot of portability issues of using Active X.
Most of the methods and properties mirror the Active X control so it is relatively easy to build/convert a JKP treeview without learning the class methods and properties.


Let me explain the logic for the light load that I coded into my class that uses the ActiveX control.
Instead of fully populating the Tree with all the nodes, I only populate the top level visible nodes. For each visible node I also only load one child node and for each child node a single child node (recursivel)
In my demo in the below thread, I load a Treeview with 10K records and it loads instantaneously:

When the tree loads the following nodes are loaded and only one child (no sub nodes).
View attachment 113528


The reason for the child node is that is how you get the Plus Sign. If there was only the 9 visible nodes, none of these nodes would appear expandable.

Assume you Click on Linda Powlowski. Additional nodes get loaded. The rest of linda's "child" nodes, and again one child node for each loaded child.

View attachment 113529

So originally Mallie was already loaded. It then loads Charlotte and the rest of Linda's child nodes.

So yes this same functionality could be added to the MSForms Class I built. Did this take me a long time to figure out? Yes. But since the two "controls" mirror each other I should be able to figure it out a lot faster. So when I get time I will see if I can add it. I always planned to write a complete helper class for this, but never got around.

Here is some of the light load logic. It only differs from the full load in that there is no loop to recurse all children. It recurses a single child only.
Code:
Public Sub addLiteBranch(parentIDValue As Variant, identifier)
  On Error GoTo errLable
  Dim strCriteria As String
  Dim bk As String
  Dim currentID As Variant
  Dim currentText As String
  Dim currentNode As Node
  Dim currentImage As String
  Dim ParentNode As Node
  Dim strKey As String
  Dim rsTree As DAO.Recordset
  Set rsTree = Me.Recordset
  strCriteria = Parent_ID_Field & " = '" & parentIDValue & "'"

  'Since it is not a root node must determine the parent node.  All node keys are "ID " & the primary key
  Set ParentNode = Me.Nodes(parentIDValue)
  rsTree.FindFirst (strCriteria)
  'Only going to get the top node
  If Not rsTree.NoMatch Then
    currentID = rsTree.Fields(ID_Field)
    currentText = rsTree.Fields(Node_Text_Field)
    identifier = rsTree.Fields(Identifier_Field)
   Set currentNode = Me.Nodes.Add(ParentNode, tvwChild, currentID, currentText)
   currentNode.Tag = identifier
   If mLoadImages Then
     currentImage = Nz(rsTree.Fields(Image_Name_Field), "")
     If currentImage <> "" Then currentNode.Image = currentImage
   End If
   bk = rsTree.Bookmark
   Call addLiteBranch(currentID, identifier)
    rsTree.Bookmark = bk
    rsTree.FindNext (strCriteria)
  End If
  Exit Sub
errLable:
  MsgBox Err.Number & " " & Err.Description & " In addBranch"
  If MsgBox("Do you want to exit the loop?", vbYesNo, "Error In Loop") = vbYes Then
     Exit Sub
   Else
     Resume Next
   End If
End Sub

More importanly when you click on a node it does the same
Code:
Private Sub mTVW_Expand(ByVal Node As MSComctlLib.Node)
'Flush out any remaining nodes in this expanded level and liteload child level
'This procedure is associated with a light load. Occurs when you expand the branch
  On Error GoTo errlbl
  Dim strCriteria As String
  Dim bk As String
  Dim currentID As Variant
  Dim currentText As String
  Dim currentNode As Node
  Dim ParentNode As Node
  Dim currentIdentifier As String
  Dim currentImage As String
  Dim rsTree As DAO.Recordset
  'Debug.Print Node.Text & " " & "Selected Node"
  If Node.Children > 1 Then Exit Sub ' node has already been expanded
  Set rsTree = Me.Recordset
  strCriteria = Parent_ID_Field & " = '" & Node.key & "'"
  rsTree.FindFirst (strCriteria)
  Debug.Print strCriteria
  If rsTree.NoMatch Then
  '  MsgBox "There is no record with a Parent ID of " & Node.key
  End If

  Do Until rsTree.NoMatch
   currentID = rsTree.Fields(ID_Field)
   Debug.Print currentID & " current"
   currentText = rsTree.Fields(Node_Text_Field)
   currentIdentifier = rsTree.Fields(Identifier_Field)
   If Node.Child.key = currentID Then
     Node.Child.Tag = currentIdentifier
     RaiseEvent ExpandedBranch(Node.Child)
   Else
     'If you are light loaded and drag drop then you will get a duplicated key error
     Set currentNode = mTVW.Nodes.Add(Node.key, tvwChild, currentID, currentText)
     currentNode.Tag = currentIdentifier
     If mLoadImages Then
       currentImage = Nz(rsTree.Fields(Image_Name_Field), "")
       If currentImage <> "" Then currentNode.Image = currentImage
     End If
     RaiseEvent ExpandedBranch(currentNode)
     bk = rsTree.Bookmark
     Call addLiteBranch(currentID, currentIdentifier)
   End If
   rsTree.Bookmark = bk
   rsTree.FindNext (strCriteria)
  Loop
  Exit Sub
errlbl:
  If Not Err.Number = 35602 Then 'this is a duplicate key caused by drag drop and light loaded
    MsgBox Err.Number & " " & Err.Description & " Key: " & currentID & " In Treeview Expand."
  End If
End Sub

So it may be as simple as trying to incorporate these methods into my MS Forms wrapper class. But there may be additional dependencies that need to be coded.
Thanks a lot for such a detailed reply. I will try to follow the TV coms control light load approach for MS Form method. If successful, I will post it here.

Regards
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
Went through my files and I see I started a demo for a JKP light load. I remember there is no event in that class equivalent to "Expand" which happens as you expect when expand a nodes branch. This would be required to do the light load like I described. I see I tried to add a custom event to mimic this. Not sure if I was unsuccessful or lost interest.

Code:
Friend Sub NodeClick(ByRef oCtl As MSForms.Control, ByRef cnode As clsNode)
'-------------------------------------------------------------------------
' Procedure : NodeClick
' Company   : JKP Application Development Services (c)
' Author    : Jan Karel Pieterse (www.jkp-ads.com)
' Created   : 15-01-2013
' Purpose   : Handles clicks on the treeview. Called from clsNode
'-------------------------------------------------------------------------
   ' PT also called from checkbox (label) click event in clsNode
    Dim bFlag As Boolean
    Dim lngViewable As Long
    Dim cLastChild As clsNode

    If oCtl.Name Like "Exp*" Then
        bFlag = Not ActiveNode Is cnode
        If bFlag Then
            Set ActiveNode = cnode
        End If

        BuildRoot False

        If cnode.Expanded Then
            If Not cnode.ChildNodes Is Nothing Then
                Set cLastChild = cnode.ChildNodes(cnode.ChildNodes.Count)
                If Not NodeIsVisible(cLastChild, lngViewable) Then
                   If lngViewable > cnode.ChildNodes.Count Then
                        ScrollToView cLastChild, Top1Bottom2:=2
                    Else
                        ScrollToView cnode, Top1Bottom2:=1
                    End If
                End If
            End If
            '------------------------------------------------------- MajP add ------------------------------------------------------------------
            NodeExpanded cnode
        End If
        If bFlag Then
            RaiseEvent Click(cnode)
        End If
        
    ElseIf oCtl.Name Like "CheckBox*" Then   ' PT
        ' RaiseEvent for the checkbox moved to clsNode
        RaiseEvent NodeCheck(cnode)

    ElseIf oCtl.Name Like "Node*" Then
        If Not ActiveNode Is cnode Then
            Set ActiveNode = cnode
        Else
            SetActiveNodeColor
        End If
        RaiseEvent Click(cnode)
    End If

End Sub

I added that line where it checks the click. So that line calls this function that raises the expanded event.

Code:
Public Function NodeExpanded(cnode As clsNode)
  RaiseEvent NodeExpanded(cnode)
End Function

So if this event I added works then should be able to recreate the light load idea. If not, I not sure what if any solution exists.
 

Pac-Man

Active member
Local time
Today, 10:26
Joined
Apr 14, 2020
Messages
416
Went through my files and I see I started a demo for a JKP light load. I remember there is no event in that class equivalent to "Expand" which happens as you expect when expand a nodes branch. This would be required to do the light load like I described. I see I tried to add a custom event to mimic this. Not sure if I was unsuccessful or lost interest.

Code:
Friend Sub NodeClick(ByRef oCtl As MSForms.Control, ByRef cnode As clsNode)
'-------------------------------------------------------------------------
' Procedure : NodeClick
' Company   : JKP Application Development Services (c)
' Author    : Jan Karel Pieterse (www.jkp-ads.com)
' Created   : 15-01-2013
' Purpose   : Handles clicks on the treeview. Called from clsNode
'-------------------------------------------------------------------------
   ' PT also called from checkbox (label) click event in clsNode
    Dim bFlag As Boolean
    Dim lngViewable As Long
    Dim cLastChild As clsNode

    If oCtl.Name Like "Exp*" Then
        bFlag = Not ActiveNode Is cnode
        If bFlag Then
            Set ActiveNode = cnode
        End If

        BuildRoot False

        If cnode.Expanded Then
            If Not cnode.ChildNodes Is Nothing Then
                Set cLastChild = cnode.ChildNodes(cnode.ChildNodes.Count)
                If Not NodeIsVisible(cLastChild, lngViewable) Then
                   If lngViewable > cnode.ChildNodes.Count Then
                        ScrollToView cLastChild, Top1Bottom2:=2
                    Else
                        ScrollToView cnode, Top1Bottom2:=1
                    End If
                End If
            End If
            '------------------------------------------------------- MajP add ------------------------------------------------------------------
            NodeExpanded cnode
        End If
        If bFlag Then
            RaiseEvent Click(cnode)
        End If
       
    ElseIf oCtl.Name Like "CheckBox*" Then   ' PT
        ' RaiseEvent for the checkbox moved to clsNode
        RaiseEvent NodeCheck(cnode)

    ElseIf oCtl.Name Like "Node*" Then
        If Not ActiveNode Is cnode Then
            Set ActiveNode = cnode
        Else
            SetActiveNodeColor
        End If
        RaiseEvent Click(cnode)
    End If

End Sub

I added that line where it checks the click. So that line calls this function that raises the expanded event.

Code:
Public Function NodeExpanded(cnode As clsNode)
  RaiseEvent NodeExpanded(cnode)
End Function

So if this event I added works then should be able to recreate the light load idea. If not, I not sure what if any solution exists.

Thanks it will give a headstart.
 

Pac-Man

Active member
Local time
Today, 10:26
Joined
Apr 14, 2020
Messages
416
I am using tree view loader class to load the tree view from the table. If I am not incorrect, I have to add procedures in tree view loader class for light load.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
Yes, but as I explained it is a multi step process.
You need to add a loadlightbranch which will add just the one level of child nodes on load. But then you have to trap the expanded event to start flushing out the lower level (one level deep). This means your class also needs a reference to the recordset which you would have to persist in the class. I tested the expand event that I added so I know I can do this. I just need some time. Unfortunately it is Tax time so got to unfortunately take care of that first and then I am on travel. Might be a while before I can dig in, but already started. Basically if I am going to do this, I will end up doing a complete "wrapper class" like I have for the ActiveX.
 

Pac-Man

Active member
Local time
Today, 10:26
Joined
Apr 14, 2020
Messages
416
Yes, but as I explained it is a multi step process.
You need to add a loadlightbranch which will add just the one level of child nodes on load. But then you have to trap the expanded event to start flushing out the lower level (one level deep). This means your class also needs a reference to the recordset which you would have to persist in the class. I tested the expand event that I added so I know I can do this. I just need some time. Unfortunately it is Tax time so got to unfortunately take care of that first and then I am on travel. Might be a while before I can dig in, but already started. Basically if I am going to do this, I will end up doing a complete "wrapper class" like I have for the ActiveX.
Thanks a lot. Meanwhile I'll try myself too.
 

Edgar_

Active member
Local time
Today, 00:26
Joined
Jul 8, 2023
Messages
430
I am quite sure that it will take more time to load the TV as the time is being taken in the loop which iteratively add one by one nodes. Since the approach you referred run the loop once to add all the nodes, and then again to add the parent.
It would have been an interesting experiment because the code is very short and simple to adapt, here's a more declarative approach:

Java:
'// #############################################################################################
'// Email: edgarfreelancing@gmail.com
'// Last update: 24/03/2024
'//
'// Description:
'// Populates a TreeView control with hierarchical data from a Recordset without recursion.
'//
'// Parameters:
'// rs: Recordset containing hierarchical data.
'// tvw: TreeView control to populate (Microsoft treeview is preferred)
'// primaryKeyName: Name of the primary key field in the Recordset.
'// nodeText: Name of the field in the Recordset to be displayed as node text.
'// parentFieldName: Name of the field in the Recordset containing parent node IDs.
'//
'// Example usage:
'// PopulateTreeView myRS, Me.MyTreeViewControl.Object, "EmployeeID", "FullName", "SupervisorID"
'// #############################################################################################

Public Sub PopulateTreeView(rs As Recordset, tvw As TreeView, primaryKeyName As String, nodeText As String, parentFieldName As String)

    ' 1st step: add all nodes
    Do While Not rs.EOF
        tvw.Nodes.Add , , "k" & rs.Fields(primaryKeyName).Value, rs.Fields(nodeText).Value
        rs.MoveNext
    Loop
 
    ' 2nd step: assign parents to all nodes
    rs.MoveFirst
    Do While Not rs.EOF
        If rs.Fields(parentFieldName).Value <> 0 Then
            Set tvw.Nodes("k" & rs.Fields(primaryKeyName).Value).Parent = tvw.Nodes("k" & rs.Fields(parentFieldName).Value)
        End If
        rs.MoveNext
    Loop
End Sub
 
Last edited:

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
@Pac-Man
I figured out the light load. See demo. It appears to be extremely fast in the test case of 10k nodes.

This is part of what I am calling the JKP_Loader. I tried to incorporate this into a similar wrapper as what I did for the Active X, but ran into issues. This loader is not quite as user friendly as the complete wrapper class and does not provide all the functions. The wrapper class is something I hope to build and you can see the start in here..

The Demo has 10k records and loads near instantaneously. There are some things I think I can do to make this even faster. I am still loading more than I think I need, but not sure if that is an easy fix. I believe there was a reason I did it this way originally.

It would have been an interesting experiment because the code is very short and simple to adapt, here's a more declarative approach:
I ran a few tests and it is hard to compare a standard full load to this version of the full load. I think your version is more unstable. Either way both cases are bad for any large tree. I could get the 10k to load in about 45 seconds to a minute for 10k. I tried your version and sometimes it ran as fast or slightly faster, other times much slower, and often it crashed. I think the problem is that these trees are unstable with too much visible nodes and they get unpredictable. This method is good for small trees, and I have used it for some simple demos.

Bottom line the light load is order of magnitude faster simply because you are not loading everything. The tree does not get unstable. Now this also depends on the shape of the tree. A tree with lots of levels and few nodes per level is far faster than a tree with few levels and lots of nodes per level using the light load.

I do think in general the ActiveX loads faster than the JKP MSFORMS version.
 

Attachments

  • JKP TreeView Wrapper Demo V2.accdb
    4.1 MB · Views: 26

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
So how fast are 10k records loaded? (or actually not-loaded)
From the top of the Form it said it took .16 seconds. It created the 100 visible nodes, and an additional 250 nodes not shown (350 total). These are what give you the Expanders. The total controls represents the lines, puls sign, and box to fake a tree. This is why it is critical to do a light load IMO. Everything you see is created in a MS Forms control.

speed.png
 

Pac-Man

Active member
Local time
Today, 10:26
Joined
Apr 14, 2020
Messages
416
@Pac-Man
I figured out the light load. See demo. It appears to be extremely fast in the test case of 10k nodes.

This is part of what I am calling the JKP_Loader. I tried to incorporate this into a similar wrapper as what I did for the Active X, but ran into issues. This loader is not quite as user friendly as the complete wrapper class and does not provide all the functions. The wrapper class is something I hope to build and you can see the start in here..

The Demo has 10k records and loads near instantaneously. There are some things I think I can do to make this even faster. I am still loading more than I think I need, but not sure if that is an easy fix. I believe there was a reason I did it this way originally.


I ran a few tests and it is hard to compare a standard full load to this version of the full load. I think your version is more unstable. Either way both cases are bad for any large tree. I could get the 10k to load in about 45 seconds to a minute for 10k. I tried your version and sometimes it ran as fast or slightly faster, other times much slower, and often it crashed. I think the problem is that these trees are unstable with too much visible nodes and they get unpredictable. This method is good for small trees, and I have used it for some simple demos.

Bottom line the light load is order of magnitude faster simply because you are not loading everything. The tree does not get unstable. Now this also depends on the shape of the tree. A tree with lots of levels and few nodes per level is far faster than a tree with few levels and lots of nodes per level using the light load.

I do think in general the ActiveX loads faster than the JKP MSFORMS version.
Thanks a lot @MajP for your time and effort you put into it. I am on Eid holidays and don't have PC to check till next Monday. I'll check it and inform you as soon as I check. If it works so much fast for 10k records then it will work for my case faster. Thanks again and God bless you.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
No problem. I was always planning to get around to doing this. This approach is a game-changer for large trees in either the active x or JKP MSForms version.
 

Edgar_

Active member
Local time
Today, 00:26
Joined
Jul 8, 2023
Messages
430
I think your version is more unstable. Either way both cases are bad for any large tree. I could get the 10k to load in about 45 seconds to a minute for 10k. I tried your version and sometimes it ran as fast or slightly faster, other times much slower, and often it crashed.
Thanks for the testing, I'm wondering if I could test for a certain parent depth before the parent assignment "pass". Maybe that could help avoid the instability of the control when too many nodes are loaded.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
Thanks for the testing, I'm wondering if I could test for a certain parent depth before the parent assignment "pass". Maybe that could help avoid the instability of the control when too many nodes are loaded.
Maybe, but It is a waste of time. The light load concept is so many orders of magnitude faster on a large tree. You can probably figure out a non recursive lite load concept and I would put my efforts into that. It should be relatively simple. My class is probably more complicated than needed because it is persisting the recordset.

1. Render the parent nodes
2. Loop the parent nodes and add one child node
When you expand a node
trap the expand method
3. Add the rest of the child nodes to the expanded node and one child per child node.


Are you able to keep the tree from updating? The big problem I found with that your version start screen updating. I tried to turn this off, but could not. I thought you could hide the nodes, but that seems to be a read only property. Not sure what good that is. I tried to keep the node from expanding.

In the demo you can go through the 3 choices. Lite Load, Full Recursive, and your 2 pass version. I think the full recursive version is still going to be faster than the two pass because the nodes are not expanded and few nodes are rendered to the screen. My full version loads in about a minute, but I am unable to successfully load yours most of the time.
 

Edgar_

Active member
Local time
Today, 00:26
Joined
Jul 8, 2023
Messages
430
Are you able to keep the tree from updating
If I set the linestyle property of the treeview to tvwRootLines and set the expanded property to false to all nodes after they're loaded, you can. But they're still loaded, so...
In my testing, I vaguely recall there was another property to show it collapsed, but I'm not sure if I'm confusing it with another thing.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
@Edgar. In post 17 I noticed I forgot to post the demo with the comparison. I will not be at my computer until next week and will post then.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 01:26
Joined
May 21, 2018
Messages
8,529
@Edgar,
Here is the comparison.
speed.png


Pick Change Tree Demo.
The three buttons are the Lite Load, a recursive full load, and then the two pass non-recursive method. The latter two may or may not complete and crash the db. It may not be a completely fair test so you may want to modify the 2 pass method to not update the screen. Regardless, if you do not want to use a recursive load then you could code a non-recursive lite load.
 

Attachments

  • TreeviewLoadTest.accdb
    1.6 MB · Views: 29

Users who are viewing this thread

Top Bottom