I am completely new to Access and Databases (and limited ability with VB6 as well) but don't let that put you off.
I am using VB6 and Access 2002
I have downloaded the tutorial suggested in the FAQ's and run it in a practise project and got it all to work as should be.
I have now tried to put this code into my project, which is making a Code Library for myself.
The first thing I am trying to accomplish is to load the list in the attached image under the title tvwNodes into an array, to then use to name the Nodes in my treeview (tvwCode)
I have the following code where I get an error after all the 6 records have been added to the array
..however in this case (based on my interpretation of your data) you don't need that, you need to do something else instead.
What you need to do is store the value for tvwNodes in every row, as currently VBA Excel etc do not have "parent" nodes.
You seem to have made a common error, which is to assume that the order or records actually means something (or will be returned in that order next time), which is not the case - a table is a group (or Set) of records, not an ordered list. If the database decides to, it can give you those records in a completely random order each time.
For several rows tvwNodes is Null (not just an empty string, but no value at all), which causes problems if not used properly.
Ok, this I follow, thanks.
Originally Posted by si_the_geek
The simplest way to fix this is to append an empty string to the value (other methods are discussed in the FAQ article about it), eg:
[code]tvw_Nodes(UBound(tvw_Nodes)) = rs.Fields("tvwNodes") & ""
Again, I think I follow this, but just to understand what you have said here,
when loading the array elements from the database, on each loop add an empty string to the row contents.
Surley this would increase the size of the array elements? Or do you intend this, and then when using the array use something like If Not = "" then ....
Originally Posted by si_the_geek
however in this case (based on my interpretation of your data) you don't need that, you need to do something else instead.
What you need to do is store the value for tvwNodes in every row, as currently VBA Excel etc do not have "parent" nodes.
I have attached a picture in the document below to show what I am tring to achieve. This has been coded, but with a fixed number of nodes. I am trying to make it dynamic, so the user (me) can add a new node at any time.
Originally Posted by si_the_geek
You seem to have made a common error, which is to assume that the order or records actually means something (or will be returned in that order next time), which is not the case - a table is a group (or Set) of records, not an ordered list. If the database decides to, it can give you those records in a completely random order each time.
An interesting point, which obviously I didnt know. So If I wanted the nodes to be loaded A-Z then I would have to sort the array elements first would I?
If somebody helps you, take time to RATE the post. I do.
"FAILURE IS NOT AN OPTION. It comes bundled with the software."
Below are some of the threads that have helped me along the way:
Again, I think I follow this, but just to understand what you have said here, when loading the array elements from the database, on each loop add an empty string to the row contents.
Surley this would increase the size of the array elements? Or do you intend this, and then when using the array use something like If Not = "" then ....
It doesn't increase the size, as you what you are appending doesn't have any length - it's just a cunning trick to convert a Null into an empty string ("") which VB is happy with, while not having any effect on non-Null values.
You could use the IsNull function instead as also shown in the article in the Database FAQs, but this method is simpler and quicker.
So If I wanted the nodes to be loaded A-Z then I would have to sort the array elements first would I?
You could, but it is easier (and faster) to ask the database to sort it for you.. to do that, you need to use an SQL statement instead of just a table name. To do that, replace line 9 of your code above with this:
Code:
Dim strSQL as String
strSQL = "SELECT * FROM tbl_Nodes ORDER BY tvwNodes, tvwChildNodes"
rs.Open strSQL, cn, adOpenKeyset, adLockPessimistic, adCmdText
(while the strSQL variable isn't strictly necessary, it is useful for finding bugs!)
It doesn't increase the size, as you what you are appending doesn't have any length - it's just a cunning trick to convert a Null into an empty string ("") which VB is happy with, while not having any effect on non-Null values.
You could use the IsNull function instead as also shown in the article in the Database FAQs, but this method is simpler and quicker.
I have changed the two parts of the code you suggested, adding the empty string to the end and the sql statement to sort the array.
When I now do this, I get 13 empty elements in the array before I get to the actual elements I am after.
You could go for a different database design to stop the duplication of data (eg: having one table for nodes, one for child nodes, and one for grand-child nodes)), but it would add more complexity to the database work - so you may want to avoid that!
That's not the way I'm afraid, you need to add each child node to the listview separately. Is there a reason for using the tvw_Nodes array, rather than adding items directly to the listview?
Probably the easiest way is to store the "previous" text of tvwNodes and tvwChildNodes in strings, and store the added nodes as separate variables. Then within the loop:
If the tvwNodes value for the current record is different, and a new "parent" node which you store to your variable (and reset the value of the tvwChildNodes "previous" string).
Then the same for the tvwChildNodes field (except you need to add the node to the current parent), and finally (if it isn't blank) add the tvwgrandchild node to the child node.
Is there a reason for using the tvw_Nodes array, rather than adding items directly to the listview?
No, not really. It's just because I don't know any other way to do it, so I assumed it was this way.
From what you are saying, it would be easier to add directly to the listview.
I don't usually ask this, but could you rustle up a quick demo sometime please, as I have been struggling with this for quite some time.
I'm guessing that the Key (the value of CStr(lngNodeParent)) is already in use, as the Child version does similar things & doesn't use different numbers. Keys need to be unique (as they can be used to return items), so this is not allowed.
We need to make sure that the numbers are unique, and to do that I think your can just add the following after line 24 of my code (untested I'm afraid!):
Code:
If lngNodeParent <= lngNodeChild Then lngNodeParent = lngNodeChild + 1
..and this after line 32:
Code:
If lngNodeChild <= lngNodeParent Then lngNodeChild = lngNodeParent + 1
I just looked at the help for that error and it clearly says that numeric-only keys (even if they are converted to strings) are not valid - you need to append an character too, eg:
I just looked at the help for that error and it clearly says that numeric-only keys (even if they are converted to strings) are not valid - you need to append an character too, eg:
Re: [RESOLVED] Loading from DB into array / treeview
The "Close" part is the image parameter, which (from the help) specifies "The index of an image in an associated ImageList control".
I presume you either haven't associated the ImageList, or you don't have an image in it which can be referenced using "Close".
ps: there's no need for a PM on the same day as the latest reply in a thread, as I tend to leave a couple of threads open if I'm not sure of the answer & need to check them out in more depth.