Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

treeview control in a form 1

Status
Not open for further replies.

bfamo

Technical User
Feb 16, 2006
132
NO
Instead of showing my data in a simple Report, I want to create a more interactive way to look at the data. I have been looking at the Data Access Pages with its treeview. In order to customise this interface I have been reading about implementing a treeview in a form instead.

The basic idea (and this is just to set an example that is easy to understand) is as follows:

|- John
|- Jennifer
|- David
|-Ford Mustang
|-Ferrari 360 Moderna
-Year: Cost:
-Engine: 0-60Mph:
|- Shane
|- Victoria

As you can see I want to list all the cars that the members in my "car club" has got. On the third level in the treeview i want a comlete list of all the cars specifications.

This article gave some good info on the subject:
thread705-987920
VBSlammer says that the TreeView control can be found in the "Microsoft Windows Common Controls 6.0" library. I've been looking at my librarys in VB and I can't find it.

Could anyone give me some advice on how to start out building this treeview? What do I want to start of with etc etc. I'm new to the treeview control, so any tips would be
greatly appreciated!

Thanks
 
Try Microsoft Treeview Control 6.0(sp4) or 5.0(sp2), this control must be installed on any users of your databases computer. So the MSComctlLib is the .dll with the control.

Treeview is not a bound control so you will have to build and edit it through code. The concept here is to add nodes and children to nodes to build the tree. If you want to use images, I suggest adding the imagelist control. In the properties of the treeview is custom, use this to set the appearance of the tree, including the imagelist, if you so desire.

Now to building the tree.
The recordset that you use will probably be a query. You want to define it so you get a table of all the values that will be displayed on the tree.
i.e. Name Car Spec
Open the recordset as a snapshot, its faster.

Adding nodes is as easy as addNode(). The key is to specify the parent and define the new node. Nodes without parents are root nodes. So Name would have no parent, while car would have a name parent and spec would have a car parent.

The plan to build the tree is go record by record looking for changes in the fields. So say you define variables for curName, curCar, curSpec. Then test to see if the current record is the same or different from the cur[Variable]. If so add the new value to the tree.

Without going into too much detail, that kind of sums it up.
 
You may have to register it if you do not see it. Go to Tools> ActiveXControls> Register

And search for MSCOMCTL.OCX
After doing that you may be done, but also check your references for Microsoft Common Contols (6.0). If not do the same drill here.

Next query this site for Treeview using the advanced search feature. I have posted a lot of code on this subject, and there are some good links to sites with more code.
 
Besides querying this site, just go to Google and type in "Treeview Access". You will come up with a lot of code out there that is already written.
Here is one that is close to what you want.

This is little wierd how it is set up, the form is hidden and I can not find anywhere it is loaded. However, you can just grab the code, and build your own form. I have a lot of code too, if you get stuck on a feature you want to add. Some features I have;
drag and drop
sort tree
Multiple Icons
Collapse tree
expand tree
find in tree
open record of selected node
delete node
reorder node

Here is one thing wierd about the Treeview that caused me hours of pain. Each node has a Key property. This is a logical place to put a unique ID, so that if you click on that node you know which record to associate it too. The key is a string field. I tried to convert my IDs to strings, but always got an error. Have no idea why, but the first character of the key must be alphabetic. So

myNode.key = cstr(rs.fields("intPersonID")) will error
but
myNode.key = "ID" & cstr(rs.fields("intPersonID"))
will work

even this errors
myNode.key = "1234" errors
but not myNode.key = "A1234"

The "Tag" property is another useful field for ID information.
 
good, now the library is in place.

I'll start working with it on monday, and then I'll search the forums for more details. Thanks so much both of you, all I needed was a quick info.

I will post later on if I get stuck ;)

 
Hello again you guys.

After some searching and reading on the net, I had a look at the database that Zameer Abdulla refered to. This was basically just what I was looking for, so I made som modification to the code. However, I'm left with one problem before it sholud work as I have planned.

I get the error message "run time error 35602: key is not unique in collection"

I've been reading about trouble with unique keys in the treeview control, and to be honest I still don't understand what it's all about.

VB highlights this line of code in debug mode:

.Nodes.Add relative:=strNode1Text, _
relationship:=tvwChild, _
Key:=strNode2Text, _
Text:=strVisibleText

Can anyone se the problem here?

Here is the rest of the code:

Private Sub Form_Load()


Dim varFillTreeTilsynshistorikk As Variant

DoCmd.RunCommand acCmdSizeToFitForm
Me![txtValgtProd].Value = Null
varFillTreeTilsynshistorikk = TreeTilsynshistorikk_Fill()

End Sub

Function TreeTilsynshistorikk_Fill()
'Created by Helen Feddema 2-10-2002
'Last modified 4-23-2002

'============================================================
'Modified from a procedure generated by the Access 97
'Treeview Control Wizard

'PURPOSE: Fill the ActiveX Treeview Control 'tvwBooks' with
'author and book information
'ACCEPTS: Nothing
'RETURNS: Nothing
'CALLED FROM: Form Load event
'============================================================



Dim strMessage As String
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim intVBMsg As Integer
Dim strQuery1 As String
Dim strQuery2 As String
Dim nod As Object
Dim strNode1Text As String
Dim strNode2Text As String
Dim strVisibleText As String

Set dbs = CurrentDb()
strQuery1 = "QryTilsInsTree"
strQuery2 = "QryTilsInsProdTree"

With Me![TreeTilsynshistorikk]
'Fill Level 1
Set rst = dbs.OpenRecordset(strQuery1, dbOpenForwardOnly)

'Add a node object for each record in the "QryTilsInsTree" table/query.
'The Key argument concatenates the level number and the LastNameFirst
'field of the Level 1 query, to create a unique key value for the node.
'The Text argument is the text displayed as a Level 1 node in the
'TreeView control

Do Until rst.EOF
strNode1Text = StrConv("Level1" & rst![Initialer], _
vbLowerCase)
Set nod = .Nodes.Add(Key:=strNode1Text, _
Text:=rst![Initialer])
'Expand the entire node
nod.Expanded = True
rst.MoveNext
Loop
rst.Close

'Fill Level 2
Set rst = dbs.OpenRecordset(strQuery2, dbOpenForwardOnly)

'Add a node object for each record in the "QryTilsInsProdTree"
'table/query.
'The value of the Relative argument matches the Key argument value
'for the Level 1 node this Level 2 node belongs to.
'The Relationship argument takes a named constant, tvwChild,
'indicating that the Level 2 node becomes a child node of the
'Level 1 node named in the Relative argument.
'The Key argument concatenates the level number and the Title
'field of the Level 2 query, to create a unique key value for the node.
'The Text argument is the text displayed as a Level 2 node in the
'TreeView control

Do Until rst.EOF
strNode1Text = StrConv("Level1" & rst![Initialer], vbLowerCase)
strNode2Text = StrConv("Level2" & rst![Navn], vbLowerCase)
strVisibleText = rst![Navn]
.Nodes.Add relative:=strNode1Text, _
relationship:=tvwChild, _
Key:=strNode2Text, _
Text:=strVisibleText
rst.MoveNext
Loop
rst.Close

End With
dbs.Close


End Function


Private Sub TreeTilsynshistorikk_NodeClick(ByVal Node As Object)
'Created by Helen Feddema 2-10-2002
'Last modified 4-23-2002



Dim frm As Access.Form

Set frm = Me![subProdInformasjon].Form

'Make the subform with book information visible if a book title is
'selected, and invisible if an author name is selected.
If Left(Node.Key, 6) = "level2" Then
Me![txtValgtProd].Value = Node.Text
frm.RecordSource = "QryTilsProdInfoTree"
frm.Visible = True
Else
frm.Visible = False
End If



End Sub
 
The problem here is that Navn is probably not unique. Even if the Initialer parent is different, the Navn has to be unique
ie
init1
navn1 'first instance
init2
navn1 'same key

Try using

init1
init1navn1
init2
init2navn1

 
I agree most likely not unique. Add these in your code to see what is happening

debug.print "Text1" & strNode1Text
debug.print "Text2" & strNode2Text
debug.print ""
.Nodes.Add relative:=strNode1Text, _
relationship:=tvwChild, _
Key:=strNode2Text, _
Text:=strVisibleTex
 
Yes, It was not unique, and I now know why.
MajP, I tried the debug.print and that worked just fine.
What does it do?

Looks like I have to get further into the control, so that I understand more of whats happening. My intentions was to build a tree from scratch, but when I found the perfect example the road became much shorter.

Thanks!
 
Its one of your best debugging tools along with the Message Box. It prints the result to the "Immediate" window. VBA has a pretty robust debugging capability tools. Look under "Debug". If you are not using these now, you should.
 
Yeah I'll have a look into that Debug tool. I started using VBA in access a couple months ago, så every tip is greatly appreciated!

Thanks! ;)
 
If you plan on coding in VBA, spend the time and do yourself a favor and read about these debug tools. The debug.print and the Msg box are really not part of the "debugging" package, but just very flexible functions for that purpose.
The fact that you got a treeview to work without knowing these tools is pretty impressive, I could not do it.
I see on this site all the time where someone hangs a page of code and then asks "why is this not working?" No debug.print, no toggle points, no debugging. I have to ask where did you learn to write code. I learned in Pascal and Java, and only wished it was as easy to debug as VBA.
 
The technique MajP described is called a trace. Using a feedback tool to understand the state of the code. You can use this code to put both values on the same line seperated by a tab.

debug.print val1, val2

Another little trick I have learned that may be helpful is in error handling.
Code:
function doSomething()
on error goto err_somethingWentWrong
     <implementation code> 
     exit function
err_somethingWentWrong:
     msgbox "fe.ds " & error$
     exit function
     resume
end function
The message box uses a code that combines the module with procedure for searching. The "fe" represents frmEntry and "ds" represents the doSomething. So if the program does error, the message helps identify the location.

An error in code will automatically jump down to the error handler and display the msgbox. The developer can use a <ctrl><break> to stop the code at the msgbox line. If you right click on the resume line and select Set Next Statement, the active line will move to the resume statement. Using the F8 or debug/stepinto will then jump the active line up to the line of code that caused the error. The Exit Function is so you can OK the message box, the code exits and you take your chances it doesn't crash the system.

Hope this helps
 
I error check the same way. I also include in my Message box,

err.number & ": " & error
Sometimes the number can be helpful when looking up errors in a reference.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top