UBound relationship to Listbox.List

G

Greg Maxey

I am seeing results that I don't understand when using UBound related to a
ListBox.List method.

I have a 3 column 3 row listbox populated in a userform. When I click a
command button it runs the following code that puts the contents of the
listbox into an array. The part I don't understand is why Msgbox
UBound(myArray, 2) is returning 9. Thanks.

Private Sub CommandButton_Click()
Dim myArray() As Variant
Dim i As Long
Dim j As Long
MsgBox Me.ListBox2.ColumnCount 'Returns 3 as expected
MsgBox Me.ListBox2.ListCount 'Returns 3 as expected

myArray() = Me.ListBox2.List
MsgBox UBound(myArray, 1) 'Returns 2 as expected
MsgBox UBound(myArray, 2) 'Reuturns 9!! Why? I expect 2.
For i = 0 To UBound(myArray, 1)
For j = 0 To UBound(myArray, 2)
MsgBox myArray(i, j) 'As a result, this line will throw and error if j >
2
Next j
Next i
 
P

Pablo Cardellino

Hi, Greg,

wouldn't be possible the highest of the two subscripts of the array to be 9,
somehow?

I know very little VBA, but in Javascript that is an expected situation, so
I thought it could be happening with your program.

Regards,

Pablo Cardellino
Florianópolis, SC
Brazil
 
D

Doug Robbins - Word MVP

Hi Greg,

The OptionBase of the Array is zero so the addresses of the elements are

0,0 0,1 0.2
1,0 1,1 1,2
2,0 2,1 2,2

Which is why myarray(i, j) gives an error for j>2.

You don't actually tell us what is in the list box, so cannot really comment
on why

UBound(myArray, 1) 'Returns 2 as expected
and UBound(myArray, 2) 'Reuturns 9 whjch is not expected.

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP
 
G

Greg Maxey

Pablo,

I don't know. The listbox is contains three columns (0-2) and three rows
(0-2). It would seem that if I used:

myArray() = .Listbox1.List

The array would be demensioned as myArrray(2, 2) so
Msgbox UBound(myArray, 1) would return 2. It does.
and
Msgbox UBound(myArray, 2) would return 2. It doesn't. It returns 9
 
G

Greg Maxey

Doug,

Yes. I understand why myarray(i, j) gives an error for j>2.

What I don't understand is why Msgbox UBound(myArray, 2) returns 9

Me.ListBox2 is a three column x three row listbox. It seems that setting

myArray() = Me.Listbox2.List

would create an array demension myArray(2, 2)

So MsgBox UBound(myArray, 1) would return 2. It does and
MsgBox UBound(myArray, 2) would return 2. It doesn't it returns 9.
 
T

Tony Jollans

Hi Greg,

ColumnCount retruns the number of columns defined for the ListBox as per its
properties - the number of columns displayed.

UBound(myArray, 2) returns the number of columns of data actually there in
the array - in the listbox.

The two may be different.

As Doug says, you don't tell us what is actually in the list box but there
are apparently nine columns - how have you set it up?
 
G

Greg Maxey

Tony,

There is a lot of code involved here and while I still don't understand why,
it appears that the cause of the unexpectedly high UBound value is due to
the method I used to construct the ListBox. I have found an alternate
method which works and returns the expected UBound value. I will try to
illustrate and explain both and maybe you can see the issue and determine
the cause.

I have a document that contains a 5 row x 3 column table of data. I have a
userform that has three multi-column (3) listboxes and three command
buttons. I use the following code to initialize the userform:

Private Sub UserForm_Initialize()
Dim myArray() As Variant
Dim oDoc As Document
Dim i As Integer
Dim j As Integer
Dim myitem As Range
Dim m As Long
Dim n As Long
Application.ScreenUpdating = False
Set oDoc = ThisDocument
i = oDoc.Tables(1).Rows.Count
j = oDoc.Tables(1).Columns.Count
ListBox1.ColumnCount = j
'Hide las two columns
ListBox1.ColumnWidths = "40;0;0"
ReDim myArray(i, j)
For n = 0 To j - 1
For m = 0 To i - 1
Set myitem = oDoc.Tables(1).Cell(m + 1, n + 1).Range
myitem.End = myitem.End - 1
myArray(m, n) = myitem.Text
Next m
Next n
ListBox1.List() = myArray
ListBox1.MultiSelect = fmMultiSelectMulti
ListBox2.ColumnCount = j
ListBox2.ColumnWidths = "40;40;40"
ListBox3.ColumnCount = j
ListBox3.ColumnWidths = "40;40;40"
End Sub

As you can see, the intialize event simply populates ListBox1 with the
values in the table. Listbox1 is a multi-select listbox. After a user
selects one or more entries in ListBox1 they press the commandButton1 which
is used to populate ListBoxes2 and 3 with the selections made in ListBox1.
The following code is used to populate ListBox2 and ListBox3. In this code
I used the two different methods that I mentioned above.

Method 1 (the one that ultimately works without the unexpected UBound
return)iuses an array and the ListBox.List method. I first cycle through
the list members of ListBox1 to see how many items are selected. I ReDim
the array. I cycle through the list members of ListBox1 again and add the
selected data to the array. And finally, build ListBox2 using the .List
method.

Method 2 (the one that later presents the unexpected UBound return) uses the
..AddItem and .List methods to build ListBox3

Private Sub CommandButton1_Click()
Dim i As Long
Dim x As Long
Dim y As Long
Dim arrTest() As Variant
Me.ListBox2.Clear
Me.ListBox3.Clear
'Populate Listbox2. Method 1
x = -1
'Determine number of elements needed in array
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i) Then
x = x + 1
End If
Next i
'Size the array
ReDim arrTest(x, Me.ListBox1.ColumnCount - 1)
'Build the array
x = 0
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i) Then
For y = 0 To Me.ListBox1.ColumnCount - 1
arrTest(x, y) = ListBox1.List(i, y)
Next y
x = x + 1
End If
Next i
'Populate the listbox
Me.ListBox2.List = arrTest()
'************************************************
'Poplulate ListBox3. Method 2
'Cylcle through each item in the listindex
x = 0
For i = 0 To Me.ListBox1.ListCount - 1
'If the item is selected add it to ListBox2
If Me.ListBox1.Selected(i) Then
With ListBox3
.AddItem
.List(x, 0) = ListBox1.List(i, 0)
.List(x, 1) = ListBox1.List(i, 1)
.List(x, 2) = ListBox1.List(i, 2)
End With
x = x + 1
End If
Next i
'Cycle through each item in the list and clear the selection.
For i = 0 To Me.ListBox1.ListCount - 1
Me.ListBox1.Selected(i) = False
Next i
End Sub

After ListBoxs 2 and 3 are populated. commandButton2 is used to build two
tables in the document populated with the data shown in ListBoxes 2 and 3.
Here is the code for doing that. The comments with the expectations are
based on a user selecting 3 items from ListBox1:

Private Sub CommandButton2_Click()
Dim myArray() As Variant
Dim oRng As Word.Range
Dim oTbl As Word.Table
Dim i As Long
Dim j As Long
'Build table 1
Set oRng = ActiveDocument.Bookmarks("oTbl2").Range
oRng.Select
MsgBox Me.ListBox2.ColumnCount 'Returns 3 as expected
MsgBox Me.ListBox2.ListCount 'Returns 3 as expected
myArray() = Me.ListBox2.List
MsgBox UBound(myArray, 1) 'Returns 2 as expected
MsgBox UBound(myArray, 2) 'Reuturns 2 as expected
For i = 0 To UBound(myArray, 1)
For j = 0 To UBound(myArray, 2)
On Error GoTo Err_Handler
'MsgBox myArray(i, j) 'As a result, this line will throw and error if j
ReEntry:
Next j
Next i
Set oTbl = ActiveDocument.Tables.Add(Selection.Range, _
Me.ListBox2.ListCount, Me.ListBox2.ColumnCount)
For i = 0 To oTbl.Columns.Count - 1
For j = 0 To oTbl.Rows.Count - 1
oTbl.Cell(j + 1, i + 1).Range.Text = myArray(j, i)
Next j
Next i
Erase myArray()
'Build table 2
Set oRng = ActiveDocument.Bookmarks("oTbl3").Range
oRng.Select
MsgBox Me.ListBox3.ColumnCount 'Returns 3 as expected
MsgBox Me.ListBox3.ListCount 'Returns 3 as expected
myArray() = Me.ListBox3.List
MsgBox UBound(myArray, 1) 'Returns 2 as expected
MsgBox UBound(myArray, 2) 'Reuturns 9!! Why? I expect 2.
For i = 0 To UBound(myArray, 1)
For j = 0 To UBound(myArray, 2)
On Error GoTo Err_Handler2
'MsgBox myArray(i, j) 'As a result, this line will throw and error if j
ReEntry2:
Next j
Next i
Set oTbl = ActiveDocument.Tables.Add(Selection.Range, _
Me.ListBox3.ListCount, Me.ListBox3.ColumnCount)
For i = 0 To oTbl.Columns.Count - 1
For j = 0 To oTbl.Rows.Count - 1
oTbl.Cell(j + 1, i + 1).Range.Text = myArray(j, i)
Next j
Next i
Me.Hide
Exit Sub
Err_Handler:
'MsgBox "Error processing j. j = " & j
Resume ReEntry
Err_Handler2:
'MsgBox "Error processing j. j = " & j
Resume ReEntry2
End Sub

The question remains why does Msgbox UBound(myArray, 2) return 9 when method
2 is used to construct ListBox3?

Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top