VBA to Populate Excel Userform Treeview from MS SQL

bhalbach

Board Regular
Joined
Mar 15, 2018
Messages
221
Office Version
  1. 2016
Platform
  1. Windows
I can not seem to figure this out, can someone assist please.

I have a userfrom in excel that has a treeview, I am trying to populate the treeview with a recordset from ms sql using ADO.

I have managed to populate the Parent Nodes but have not been able to figure out how to populate the child nodes. Everything with the connection to the database and getting a recordset returned seems to be working as I do get the parent nodes to populate.

I am a rookie in vba and have been able to eventually figure things out with google and youtube, but I am stuck on this one...cant find much online related to what I am trying to do.

I have tried the following code and I get a error " Error number = 2147257114 Invalid object"

This is the first time I have tried using treeview.

All assistance would be greatly appreciated.

VBA Code:
    Me.TreeView1.Nodes.Clear
    
    'load Treeview
    Do While Not rs.EOF
    
        Me.TreeView1.Nodes.Add = rs.Fields.Item("BidItemNo")
        Me.TreeView1.Nodes.Add rs.Fields.Item("BidItemNo"), tvwChild, rs.Fields.Item("BidItemDescription"), rs.Fields.Item("BidItemDescription")

        
    rs.MoveNext
    Loop
 
VBA Code:
Sub FillRecordSet(ByRef rcrdSet As recordSetType, sConStr As String, txtEstimateNo As String)
    Dim n As Node
    Dim Conn1 As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim rs As ADODB.Recordset
    Dim sql As String
    Dim testVar as Variant

    Set Conn1 = New ADODB.Connection
    Set cmd = New ADODB.Command
    Set rs = New ADODB.Recordset

    Conn1.ConnectionString = sConStr
    Conn1.Open

    cmd.ActiveConnection = Conn1

    'On Error GoTo ErrorHandler
    
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "spGetTeeviewData"
    cmd.Parameters.Refresh
    cmd.NamedParameters = True
    cmd.Parameters("@EstimateID").Value = txtEstimateNo

    Set rs = cmd.Execute
   
    'load Treeview
    Do While Not rs.EOF
        If rs.Fields.Item("BidItemNo") = rcrdSet.BidItemCode And _
          rs.Fields.Item("BidItemDescription") = rcrdSet.BidItemDescription Then
          
            If rcrdSet.ActivityCode <> "" Then
            
                If rs.Fields.Item("ActivityCode") = rcrdSet.ActivityCode And _
                  rs.Fields.Item("ActivityDescription") = rcrdSet.ActivityItemDescription Then
                    testVar = rs.Fields.Item("ActivityItemQuantity")
                    If Not IsNull(testVar) then
                        rcrdSet.ActivityItemQuantity = rs.Fields.Item("ActivityItemQuantity")
                    End If
                    testVar = rs.Fields.Item("ActivityItemUOM")
                    If Not IsNull(testVar) then
                        rcrdSet.ActivityItemQuantity = rs.Fields.Item("ActivityItemUOM")
                    End If
                    rcrdSet.BidItemQuantity = rs.Fields.Item("BidItemQuantity")
                    rcrdSet.BidItemUOM = rs.Fields.Item("BidItemUOM")
                    rcrdSet.TakeOffQuantity = rs.Fields.Item("TakeOffQuantity")
                    Exit Do
                End If
            
            Else
                rcrdSet.BidItemQuantity = rs.Fields.Item("BidItemQuantity")
                rcrdSet.BidItemUOM = rs.Fields.Item("BidItemUOM")
                rcrdSet.TakeOffQuantity = rs.Fields.Item("TakeOffQuantity")
                Exit Do
            End If
            
        End If
        rs.MoveNext
    Loop
    On Error GoTo 0

    Conn1.CommitTrans
    Conn1.Close

    Set Conn1 = Nothing
    Set rs = Nothing
End Sub
 
Upvote 0

Excel Facts

Excel motto
Not everything I do at work revolves around Excel. Only the fun parts.
VBA Code:
Sub FillRecordSet(ByRef rcrdSet As recordSetType, sConStr As String, txtEstimateNo As String)
    Dim n As Node
    Dim Conn1 As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim rs As ADODB.Recordset
    Dim sql As String
    Dim testVar as Variant

    Set Conn1 = New ADODB.Connection
    Set cmd = New ADODB.Command
    Set rs = New ADODB.Recordset

    Conn1.ConnectionString = sConStr
    Conn1.Open

    cmd.ActiveConnection = Conn1

    'On Error GoTo ErrorHandler
   
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "spGetTeeviewData"
    cmd.Parameters.Refresh
    cmd.NamedParameters = True
    cmd.Parameters("@EstimateID").Value = txtEstimateNo

    Set rs = cmd.Execute
  
    'load Treeview
    Do While Not rs.EOF
        If rs.Fields.Item("BidItemNo") = rcrdSet.BidItemCode And _
          rs.Fields.Item("BidItemDescription") = rcrdSet.BidItemDescription Then
         
            If rcrdSet.ActivityCode <> "" Then
           
                If rs.Fields.Item("ActivityCode") = rcrdSet.ActivityCode And _
                  rs.Fields.Item("ActivityDescription") = rcrdSet.ActivityItemDescription Then
                    testVar = rs.Fields.Item("ActivityItemQuantity")
                    If Not IsNull(testVar) then
                        rcrdSet.ActivityItemQuantity = rs.Fields.Item("ActivityItemQuantity")
                    End If
                    testVar = rs.Fields.Item("ActivityItemUOM")
                    If Not IsNull(testVar) then
                        rcrdSet.ActivityItemQuantity = rs.Fields.Item("ActivityItemUOM")
                    End If
                    rcrdSet.BidItemQuantity = rs.Fields.Item("BidItemQuantity")
                    rcrdSet.BidItemUOM = rs.Fields.Item("BidItemUOM")
                    rcrdSet.TakeOffQuantity = rs.Fields.Item("TakeOffQuantity")
                    Exit Do
                End If
           
            Else
                rcrdSet.BidItemQuantity = rs.Fields.Item("BidItemQuantity")
                rcrdSet.BidItemUOM = rs.Fields.Item("BidItemUOM")
                rcrdSet.TakeOffQuantity = rs.Fields.Item("TakeOffQuantity")
                Exit Do
            End If
           
        End If
        rs.MoveNext
    Loop
    On Error GoTo 0

    Conn1.CommitTrans
    Conn1.Close

    Set Conn1 = Nothing
    Set rs = Nothing
End Sub
No errors now, but the Activity Activity Quantity value is the value that should be in ActivityUOM, except for one node..... when I click 1 ActivityItem Node, the last ActivityItem on the Tree, it is correctly filled with ActivityQuantity. In this instance the ActivityUOM is Null in the recordset

The ActivityUOM is blank in all cases.

It is really weird...
 
Upvote 0
You've lost me with that explanation. However, you can hopefully have enough to go on to step through the code in debug mode if necessary to try to figure out how to fix it.
 
Upvote 0
You've lost me with that explanation. However, you can hopefully have enough to go on to step through the code in debug mode if necessary to try to figure out how to fix it.
I think I have found it...just some copy paste that was referencing the wrong recordset field.

I will give it a good work out and see what happens....

Thank you so much,
 
Upvote 0
You've lost me with that explanation. However, you can hopefully have enough to go on to step through the code in debug mode if necessary to try to figure out how to fix it.

This is working great. I have unfortunately run into something else...

I am in need of the BidItemID and the ActivityItemID that is in the recordset that comes from the database that is used to fill the treeview values...so I can do an insert based off the selected node in the treeview.

When the treeview is being filled, can the Tag be populated with the BidItemID & ActivityItemID maybe separated by a comma and then I can extract them from the tag and use them in my insert back to the same table that the recordset originally came from?
 
Last edited:
Upvote 0
That seems reasonable. I added a Me.Tag line in the code below. You will have to check to make sure the field names are correct.
VBA Code:
Sub ProcName()
Dim n As Node
Dim Conn1 As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim sql As String
Dim keyBidItem As String
Dim keyActivity As String
Dim keyResource As String
Dim keyNewlevel As String
Dim nodeText As String

    With Me.TreeView1
      .Appearance = ccFlat
      .CheckBoxes = False
      .LineStyle = tvwRootLines
      .Nodes.Clear
    End With

    Set Conn1 = New ADODB.Connection
    Set cmd = New ADODB.Command
    Set rs = New ADODB.Recordset

    Conn1.ConnectionString = SQLConStr
    Conn1.Open

    cmd.ActiveConnection = Conn1

    'On Error GoTo ErrorHandler
    
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "spGetTeeviewData"
    cmd.Parameters.Refresh
    cmd.NamedParameters = True
    cmd.Parameters("@EstimateID").Value = Me.txtEstimateNo.Value

    Set rs = cmd.Execute
   
    Me.Tag = rs.Fields.Item("BidItemID") & "," & rs.Fields.Item("ActivityItemID")
    Me.TreeView1.Nodes.Clear
    Me.TreeView1.Nodes.Add , , "root1", Me.txtContractTitle.Value
   
    'load Treeview
    Do While Not rs.EOF
        keyBidItem = "BIN" & rs.Fields.Item("BidItemNo")
        nodeText = rs.Fields.Item("BidItemNo") & " - " & rs.Fields.Item("BidItemDescription")
        If Not NodeExists(keyBidItem) Then
            Me.TreeView1.Nodes.Add "root1", tvwChild, keyBidItem, nodeText
        End If
        
        keyActivity = keyBidItem & "AC" & rs.Fields.Item("ActivityCode")
        nodeText = rs.Fields.Item("ActivityCode") & " : " & rs.Fields.Item("ActivityDescription")
        'Check for null
        If nodeText <> " : " Then
            Me.TreeView1.Nodes.Add keyBidItem, tvwChild, keyActivity, nodeText
        End If
        
'        keyResource = keyActivity & "RC" & rs.Fields.Item("ResourceCode")
'        nodeText = rs.Fields.Item("ResourceCode") & " : " & rs.Fields.Item("ResourceDescription")
'        If nodeText <> " : " Then
'        Me.TreeView1.Nodes.Add keyActivity, tvwChild, keyResource, nodeText
'        End If
'
'        keyNewlevel = keyResource & "NLC" & rs.Fields.Item("NewLevelCode")
'        nodeText = rs.Fields.Item("NewLevelCode") & " : " & rs.Fields.Item("NewLevelDescription")
'        If nodeText <> " : " Then
'        Me.TreeView1.Nodes.Add keyResource, tvwChild, keyNewlevel, nodeText
'        End If
        
        rs.MoveNext
    Loop
   
    'Optional if you want to have all nodes expanded when the form displays
    For Each n In Me.TreeView1.Nodes
        n.Expanded = True
    Next n
    
    On Error GoTo 0


    Conn1.Close

    Set Conn1 = Nothing
    Set rs = Nothing

    Exit Sub

ErrorHandler:

End Sub

Function NodeExists(nText As String) As Boolean
    Dim n As Node
    For Each n In Me.TreeView1.Nodes
        If InStr(1, n.Key, nText) > 0 Then
            NodeExists = True
            Exit Function
        End If
    Next
    NodeExists = False
End Function

Private Sub CommandButton1_Click()

    Call ProcName

End Sub

Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    Dim sCode As String
    Dim sDesc As String
    Dim a As Variant
    Dim rSetTemp As recordSetType
    Dim bFillText As Boolean
    
    Select Case NodeLevel(Node)
        Case 1  'Node is at BidItem level, so populate BitItem objects
            a = Split(Node.Text, " - ")  'Creates array based on " : " as the separation string. Since the node text should only have one of them, a 2 item array should be formed
            rSetTemp.BidItemCode = a(0)
            rSetTemp.BidItemDescription = a(1)
            rSetTemp.ActivityCode = ""
            rSetTemp.ActivityItemDescription = ""
            FillRecordSet rSetTemp, SQLConStr, Me.txtEstimateNo.Text
            bFillText = True
        Case 2  'Node is at Activity level, so populate Activity objects
            a = Split(Node.Text, " : ")  'Creates array based on " : " as the separation string. Since the node text should only have one of them, a 2 item array should be formed
            rSetTemp.ActivityCode = a(0)
            rSetTemp.ActivityItemDescription = a(1)
            a = Split(Node.Parent.Text, " - ")
            rSetTemp.BidItemCode = a(0)
            rSetTemp.BidItemDescription = a(1)
            FillRecordSet rSetTemp, SQLConStr, Me.txtEstimateNo.Text
            bFillText = True
    End Select
    If bFillText Then
        TextBox35.Text = rSetTemp.BidItemCode
        Label163.Caption = rSetTemp.BidItemDescription
        TextBox49.Text = rSetTemp.ActivityCode
        TextBox48.Text = rSetTemp.ActivityItemDescription
        Label168.Caption = rSetTemp.BidItemQuantity
        Label165.Caption = rSetTemp.BidItemUOM
        TextBox47.Text = rSetTemp.ActivityItemQuantity
        TextBox46.Text = rSetTemp.ActivityItemUOM
    End If
End Sub

Private Function NodeLevel(Node As MSComctlLib.Node) As Integer
    Dim withoutSlashes As Integer
    Dim withSlashes As Integer
    
    withSlashes = Len(Node.FullPath)
    withoutSlashes = Len(Replace(Node.FullPath, "\", ""))
    NodeLevel = withSlashes - withoutSlashes
End Function
To get the information back, you could use the following:
VBA Code:
    Dim tagArray as Variant
    tagArray = Split(Me.Tag, ",")
    TableLocationForInsertingBidItemIDBackIn = tagArray(0)
    TableLocationForInsertingActivityItemIDBackIn = tagArray(1)
You will have to put the actual table cell for the TableLocation lines above to set the cell values to the ItemIDs.
 
Upvote 0
That seems reasonable. I added a Me.Tag line in the code below. You will have to check to make sure the field names are correct.
VBA Code:
Sub ProcName()
Dim n As Node
Dim Conn1 As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim sql As String
Dim keyBidItem As String
Dim keyActivity As String
Dim keyResource As String
Dim keyNewlevel As String
Dim nodeText As String

    With Me.TreeView1
      .Appearance = ccFlat
      .CheckBoxes = False
      .LineStyle = tvwRootLines
      .Nodes.Clear
    End With

    Set Conn1 = New ADODB.Connection
    Set cmd = New ADODB.Command
    Set rs = New ADODB.Recordset

    Conn1.ConnectionString = SQLConStr
    Conn1.Open

    cmd.ActiveConnection = Conn1

    'On Error GoTo ErrorHandler
   
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "spGetTeeviewData"
    cmd.Parameters.Refresh
    cmd.NamedParameters = True
    cmd.Parameters("@EstimateID").Value = Me.txtEstimateNo.Value

    Set rs = cmd.Execute
  
    Me.Tag = rs.Fields.Item("BidItemID") & "," & rs.Fields.Item("ActivityItemID")
    Me.TreeView1.Nodes.Clear
    Me.TreeView1.Nodes.Add , , "root1", Me.txtContractTitle.Value
  
    'load Treeview
    Do While Not rs.EOF
        keyBidItem = "BIN" & rs.Fields.Item("BidItemNo")
        nodeText = rs.Fields.Item("BidItemNo") & " - " & rs.Fields.Item("BidItemDescription")
        If Not NodeExists(keyBidItem) Then
            Me.TreeView1.Nodes.Add "root1", tvwChild, keyBidItem, nodeText
        End If
       
        keyActivity = keyBidItem & "AC" & rs.Fields.Item("ActivityCode")
        nodeText = rs.Fields.Item("ActivityCode") & " : " & rs.Fields.Item("ActivityDescription")
        'Check for null
        If nodeText <> " : " Then
            Me.TreeView1.Nodes.Add keyBidItem, tvwChild, keyActivity, nodeText
        End If
       
'        keyResource = keyActivity & "RC" & rs.Fields.Item("ResourceCode")
'        nodeText = rs.Fields.Item("ResourceCode") & " : " & rs.Fields.Item("ResourceDescription")
'        If nodeText <> " : " Then
'        Me.TreeView1.Nodes.Add keyActivity, tvwChild, keyResource, nodeText
'        End If
'
'        keyNewlevel = keyResource & "NLC" & rs.Fields.Item("NewLevelCode")
'        nodeText = rs.Fields.Item("NewLevelCode") & " : " & rs.Fields.Item("NewLevelDescription")
'        If nodeText <> " : " Then
'        Me.TreeView1.Nodes.Add keyResource, tvwChild, keyNewlevel, nodeText
'        End If
       
        rs.MoveNext
    Loop
  
    'Optional if you want to have all nodes expanded when the form displays
    For Each n In Me.TreeView1.Nodes
        n.Expanded = True
    Next n
   
    On Error GoTo 0


    Conn1.Close

    Set Conn1 = Nothing
    Set rs = Nothing

    Exit Sub

ErrorHandler:

End Sub

Function NodeExists(nText As String) As Boolean
    Dim n As Node
    For Each n In Me.TreeView1.Nodes
        If InStr(1, n.Key, nText) > 0 Then
            NodeExists = True
            Exit Function
        End If
    Next
    NodeExists = False
End Function

Private Sub CommandButton1_Click()

    Call ProcName

End Sub

Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    Dim sCode As String
    Dim sDesc As String
    Dim a As Variant
    Dim rSetTemp As recordSetType
    Dim bFillText As Boolean
   
    Select Case NodeLevel(Node)
        Case 1  'Node is at BidItem level, so populate BitItem objects
            a = Split(Node.Text, " - ")  'Creates array based on " : " as the separation string. Since the node text should only have one of them, a 2 item array should be formed
            rSetTemp.BidItemCode = a(0)
            rSetTemp.BidItemDescription = a(1)
            rSetTemp.ActivityCode = ""
            rSetTemp.ActivityItemDescription = ""
            FillRecordSet rSetTemp, SQLConStr, Me.txtEstimateNo.Text
            bFillText = True
        Case 2  'Node is at Activity level, so populate Activity objects
            a = Split(Node.Text, " : ")  'Creates array based on " : " as the separation string. Since the node text should only have one of them, a 2 item array should be formed
            rSetTemp.ActivityCode = a(0)
            rSetTemp.ActivityItemDescription = a(1)
            a = Split(Node.Parent.Text, " - ")
            rSetTemp.BidItemCode = a(0)
            rSetTemp.BidItemDescription = a(1)
            FillRecordSet rSetTemp, SQLConStr, Me.txtEstimateNo.Text
            bFillText = True
    End Select
    If bFillText Then
        TextBox35.Text = rSetTemp.BidItemCode
        Label163.Caption = rSetTemp.BidItemDescription
        TextBox49.Text = rSetTemp.ActivityCode
        TextBox48.Text = rSetTemp.ActivityItemDescription
        Label168.Caption = rSetTemp.BidItemQuantity
        Label165.Caption = rSetTemp.BidItemUOM
        TextBox47.Text = rSetTemp.ActivityItemQuantity
        TextBox46.Text = rSetTemp.ActivityItemUOM
    End If
End Sub

Private Function NodeLevel(Node As MSComctlLib.Node) As Integer
    Dim withoutSlashes As Integer
    Dim withSlashes As Integer
   
    withSlashes = Len(Node.FullPath)
    withoutSlashes = Len(Replace(Node.FullPath, "\", ""))
    NodeLevel = withSlashes - withoutSlashes
End Function
To get the information back, you could use the following:
VBA Code:
    Dim tagArray as Variant
    tagArray = Split(Me.Tag, ",")
    TableLocationForInsertingBidItemIDBackIn = tagArray(0)
    TableLocationForInsertingActivityItemIDBackIn = tagArray(1)
You will have to put the actual table cell for the TableLocation lines above to set the cell values to the ItemIDs.

I'm guessing something like this will return the tag values?

VBA Code:
cmd.Parameters("@BidItemID").Value = frmEstimate_Main.TreeView1.SelectedItem.Tag(tagArray(0))
cmd.Parameters("@ActivityID").Value = frmEstimate_Main.TreeView1.SelectedItem.Tag(tagArray(1))
 
Upvote 0
That seems reasonable. I added a Me.Tag line in the code below. You will have to check to make sure the field names are correct.
VBA Code:
Sub ProcName()
Dim n As Node
Dim Conn1 As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim sql As String
Dim keyBidItem As String
Dim keyActivity As String
Dim keyResource As String
Dim keyNewlevel As String
Dim nodeText As String

    With Me.TreeView1
      .Appearance = ccFlat
      .CheckBoxes = False
      .LineStyle = tvwRootLines
      .Nodes.Clear
    End With

    Set Conn1 = New ADODB.Connection
    Set cmd = New ADODB.Command
    Set rs = New ADODB.Recordset

    Conn1.ConnectionString = SQLConStr
    Conn1.Open

    cmd.ActiveConnection = Conn1

    'On Error GoTo ErrorHandler
   
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "spGetTeeviewData"
    cmd.Parameters.Refresh
    cmd.NamedParameters = True
    cmd.Parameters("@EstimateID").Value = Me.txtEstimateNo.Value

    Set rs = cmd.Execute
  
    Me.Tag = rs.Fields.Item("BidItemID") & "," & rs.Fields.Item("ActivityItemID")
    Me.TreeView1.Nodes.Clear
    Me.TreeView1.Nodes.Add , , "root1", Me.txtContractTitle.Value
  
    'load Treeview
    Do While Not rs.EOF
        keyBidItem = "BIN" & rs.Fields.Item("BidItemNo")
        nodeText = rs.Fields.Item("BidItemNo") & " - " & rs.Fields.Item("BidItemDescription")
        If Not NodeExists(keyBidItem) Then
            Me.TreeView1.Nodes.Add "root1", tvwChild, keyBidItem, nodeText
        End If
       
        keyActivity = keyBidItem & "AC" & rs.Fields.Item("ActivityCode")
        nodeText = rs.Fields.Item("ActivityCode") & " : " & rs.Fields.Item("ActivityDescription")
        'Check for null
        If nodeText <> " : " Then
            Me.TreeView1.Nodes.Add keyBidItem, tvwChild, keyActivity, nodeText
        End If
       
'        keyResource = keyActivity & "RC" & rs.Fields.Item("ResourceCode")
'        nodeText = rs.Fields.Item("ResourceCode") & " : " & rs.Fields.Item("ResourceDescription")
'        If nodeText <> " : " Then
'        Me.TreeView1.Nodes.Add keyActivity, tvwChild, keyResource, nodeText
'        End If
'
'        keyNewlevel = keyResource & "NLC" & rs.Fields.Item("NewLevelCode")
'        nodeText = rs.Fields.Item("NewLevelCode") & " : " & rs.Fields.Item("NewLevelDescription")
'        If nodeText <> " : " Then
'        Me.TreeView1.Nodes.Add keyResource, tvwChild, keyNewlevel, nodeText
'        End If
       
        rs.MoveNext
    Loop
  
    'Optional if you want to have all nodes expanded when the form displays
    For Each n In Me.TreeView1.Nodes
        n.Expanded = True
    Next n
   
    On Error GoTo 0


    Conn1.Close

    Set Conn1 = Nothing
    Set rs = Nothing

    Exit Sub

ErrorHandler:

End Sub

Function NodeExists(nText As String) As Boolean
    Dim n As Node
    For Each n In Me.TreeView1.Nodes
        If InStr(1, n.Key, nText) > 0 Then
            NodeExists = True
            Exit Function
        End If
    Next
    NodeExists = False
End Function

Private Sub CommandButton1_Click()

    Call ProcName

End Sub

Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    Dim sCode As String
    Dim sDesc As String
    Dim a As Variant
    Dim rSetTemp As recordSetType
    Dim bFillText As Boolean
   
    Select Case NodeLevel(Node)
        Case 1  'Node is at BidItem level, so populate BitItem objects
            a = Split(Node.Text, " - ")  'Creates array based on " : " as the separation string. Since the node text should only have one of them, a 2 item array should be formed
            rSetTemp.BidItemCode = a(0)
            rSetTemp.BidItemDescription = a(1)
            rSetTemp.ActivityCode = ""
            rSetTemp.ActivityItemDescription = ""
            FillRecordSet rSetTemp, SQLConStr, Me.txtEstimateNo.Text
            bFillText = True
        Case 2  'Node is at Activity level, so populate Activity objects
            a = Split(Node.Text, " : ")  'Creates array based on " : " as the separation string. Since the node text should only have one of them, a 2 item array should be formed
            rSetTemp.ActivityCode = a(0)
            rSetTemp.ActivityItemDescription = a(1)
            a = Split(Node.Parent.Text, " - ")
            rSetTemp.BidItemCode = a(0)
            rSetTemp.BidItemDescription = a(1)
            FillRecordSet rSetTemp, SQLConStr, Me.txtEstimateNo.Text
            bFillText = True
    End Select
    If bFillText Then
        TextBox35.Text = rSetTemp.BidItemCode
        Label163.Caption = rSetTemp.BidItemDescription
        TextBox49.Text = rSetTemp.ActivityCode
        TextBox48.Text = rSetTemp.ActivityItemDescription
        Label168.Caption = rSetTemp.BidItemQuantity
        Label165.Caption = rSetTemp.BidItemUOM
        TextBox47.Text = rSetTemp.ActivityItemQuantity
        TextBox46.Text = rSetTemp.ActivityItemUOM
    End If
End Sub

Private Function NodeLevel(Node As MSComctlLib.Node) As Integer
    Dim withoutSlashes As Integer
    Dim withSlashes As Integer
   
    withSlashes = Len(Node.FullPath)
    withoutSlashes = Len(Replace(Node.FullPath, "\", ""))
    NodeLevel = withSlashes - withoutSlashes
End Function
To get the information back, you could use the following:
VBA Code:
    Dim tagArray as Variant
    tagArray = Split(Me.Tag, ",")
    TableLocationForInsertingBidItemIDBackIn = tagArray(0)
    TableLocationForInsertingActivityItemIDBackIn = tagArray(1)
You will have to put the actual table cell for the TableLocation lines above to set the cell values to the ItemIDs.

Obviously I am in over my head on this.

I select the node on the treeview1, then I call a userform that has a listviewLibraryActivityList. On the listviewLibraryActivityList I use the checkbox to select the item I want. I then click a command button on the form with the listviewLibraryActivityList that has code to insert (with a stored procedure) to the data base table. I can get this to insert with the attached code to the data base table but it inserts all items of the listviewLibraryActivityList.

I still have to extract the BidItemNo and BidItemDescription from the concatenated values in the treeview as well...I think I can do this to your code to get the BidItemNo...
Me.Tag = rs.Fields.Item("BidItemID") & "," & rs.Fields.Item("ActivityID") & "," & rs.Fields.Item("BidItemNo")
and get it from the tagArray(2)

And I haven't figured out how to get the tagarray values to insert either.

VBA Code:
Private Sub cmdAddSelectedActivities_Click()

Dim X As Integer
Dim Conn1 As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim sql As String
Dim tagArray As Variant
    tagArray = Split(Me.Tag, ",")

    Set Conn1 = New ADODB.Connection
    Set cmd = New ADODB.Command
    
    Conn1.ConnectionString = SQLConStr
    Conn1.Open
    
    cmd.ActiveConnection = Conn1

    Conn1.BeginTrans

    On Error GoTo ErrorHandler
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "spInsertEstimateActivityItem"
    cmd.Parameters.Refresh
    cmd.NamedParameters = True

    For X = 1 To Me.listviewLibraryActivityList.ListItems.Count
    If Me.listviewLibraryActivityList.ListItems(X).Checked = True Then
        Me.listviewLibraryActivityList.ListItems(X).Selected = True
    Else
        Me.listviewLibraryActivityList.ListItems(X).Selected = False
    
        
        cmd.Parameters("@EstimateID").Value = frmEstimate_Main.txtEstimateNo.Value
        'cmd.Parameters("@BidItemID").Value = Me.TreeView1.SelectedItem.Tag = tagArray(0)
        cmd.Parameters("@BidItemID").Value = frmEstimate_Main.txtEstimateNo.Value
        cmd.Parameters("@BidItemNo").Value = Me.listviewLibraryActivityList.ListItems(X)
        'cmd.Parameters("@ActivityID").Value = Me.TreeView1.SelectedItem.Tag = tagArray(1)
        cmd.Parameters("@ActivityID").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityCode").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityItemQuantity").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityItemUOM").Value = Me.listviewLibraryActivityList.ListItems(X)
        
    End If
    
    Me.listviewLibraryActivityList.ListItems(X).Checked = False
    Set rs = cmd.Execute
    
    Next X
    
    On Error GoTo 0

    Conn1.CommitTrans
    Conn1.Close
    
    Set Conn1 = Nothing
    Set rs = Nothing

    Exit Sub
    
ErrorHandler:
    MsgBox "Error number = " & (Err.Number - vbObjectError) & vbNewLine & Err.Description
    Conn1.RollbackTrans
    Conn1.Close
    
End Sub
 
Upvote 0
Do all of these fill in the record as expected?
VBA Code:
        cmd.Parameters("@EstimateID").Value = frmEstimate_Main.txtEstimateNo.Value
        cmd.Parameters("@BidItemID").Value = frmEstimate_Main.txtEstimateNo.Value
        cmd.Parameters("@BidItemNo").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityID").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityCode").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityItemQuantity").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityItemUOM").Value = Me.listviewLibraryActivityList.ListItems(X)
One thing I see with the tag lines is that you have two '='. Does it work with just this?
VBA Code:
cmd.Parameters("@BidItemID").Value = tagArray(0)
You can also put a breakpoint (F9) on this line, and when the code pauses, put the cursor over tagArray(0), and it will show you its value. Is it what you expected?
 
Upvote 0
Do all of these fill in the record as expected?
VBA Code:
        cmd.Parameters("@EstimateID").Value = frmEstimate_Main.txtEstimateNo.Value
        cmd.Parameters("@BidItemID").Value = frmEstimate_Main.txtEstimateNo.Value
        cmd.Parameters("@BidItemNo").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityID").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityCode").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityItemQuantity").Value = Me.listviewLibraryActivityList.ListItems(X)
        cmd.Parameters("@ActivityItemUOM").Value = Me.listviewLibraryActivityList.ListItems(X)
One thing I see with the tag lines is that you have two '='. Does it work with just this?
VBA Code:
cmd.Parameters("@BidItemID").Value = tagArray(0)
You can also put a breakpoint (F9) on this line, and when the code pauses, put the cursor over tagArray(0), and it will show you its value. Is it what you expected?

The tagArray seems to be populating correctly.

What is seems like is when I select a node on the tree, then I click the cmdbutton to call the userform that has the listview on it...the treeview node becomes unselected.
I then check an item off on the listviewLibraryActivityList (on separate form) and click a cmdbutton, the code does not error out.
The results that I am getting seem to be coming from the first BidItem tag in the treeview regardless of which Node was selected.
I am also getting all the listview items inserted to the database, not just the checked one on the listview. With the same tag values. Should be only the selected ones in the listview with the same tag values.

VBA Code:
    For X = 1 To Me.listviewLibraryActivityList.ListItems.Count
    If Me.listviewLibraryActivityList.ListItems(X).Checked = True Then
        Me.listviewLibraryActivityList.ListItems(X).Selected = True
    Else
        Me.listviewLibraryActivityList.ListItems(X).Selected = False
    
        
        cmd.Parameters("@EstimateID").Value = UserForm2.txtEstimateNo.Value 'works
        cmd.Parameters("@BidItemID").Value = tagArray(0) 'works
        cmd.Parameters("@BidItemNo").Value = tagArray(1) 'works
        cmd.Parameters("@ActivityID").Value = Me.listviewLibraryActivityList.ListItems(X) 'this work and brings the first column index(0) value of the listview
        cmd.Parameters("@ActivityCode").Value = Me.listviewLibraryActivityList.ListItems(X) 'should be 2nd column index(1) of listview
        cmd.Parameters("@ActivityItemUOM").Value = Me.listviewLibraryActivityList.ListItems(X) 'should be 3rd column index(2)
        
    End If
    
    Me.listviewLibraryActivityList.ListItems(X).Checked = False
    Set rs = cmd.Execute
    
    Next X
 
Upvote 0

Forum statistics

Threads
1,217,412
Messages
6,136,470
Members
450,015
Latest member
excel_beta_345User

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top