Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
DiscussionsAccessExcelInfoPathOutlookPowerPointPublisherWord
DirectoryUser Groups
Related Topics
Outlook ExpressInternet ExplorerWindowsMS Server ProductsMore Topics ...

MS Office Forum / Word / Programming / September 2007

Tip: Looking for answers? Try searching our database.

Customized ComboBox

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Greg Maxey - 08 Sep 2007 12:00 GMT
I have been playing around with some code to allow a user to type in their
own data in a combobox and then make that entry permanently a part of the
combobox list (i.e., whenever the form is called in the future) .

My idea (which may be a stupid one) is to store the user defined entries as
variables in the document.  Here is the code:

Private Sub UserForm_Initialize() '
Dim oVar As Word.Variable
Dim oVars As Word.Variables
Set oVars = ActiveDocument.Variables
With Me.ComboBox1
 .AddItem "Greg"
 .AddItem "Susan"
 For Each oVar In oVars
  If InStr(oVar.Name, "AI") = 1 Then
   .AddItem oVar.Value
 End If
Next oVar
SortList
End With
End Sub

Sub SortList()
Dim myArray() As String
Dim i As Long
Dim lngCount As Long
lngCount = Me.ComboBox1.ListCount
ReDim myArray(lngCount)
For i = 0 To Me.ComboBox1.ListCount - 1
 myArray(i) = Me.ComboBox1.List(i)
Next i
Me.ComboBox1.Clear
WordBasic.SortArray myArray
Me.ComboBox1.List = myArray
End Sub

Private Sub CommandButton1_Click()
Dim i As Long
Dim bNewItem As Boolean
Dim oVar As Word.Variable
Dim oVars As Word.Variables
Dim lngCount As Long
bNewItem = True
With Me.ComboBox1
 For i = 0 To .ListCount - 1
   If .Value = .List(i) Then
     bNewItem = False
     Exit For
   End If
 Next i
 If bNewItem Then
   .AddItem .Value
   Set oVars = ActiveDocument.Variables
     For Each oVar In oVars
       If InStr(oVar.Name, "AI") = 1 Then lngCount = lngCount + 1
     Next oVar
     oVars.Add "AI" & lngCount + 1, .Value
 End If
End With
SortList
MsgBox Me.Combobox1.Value
Me.hide
End Sub

It seems to be working but I was wondering if I am driving a tack with a
sledge hammer here.  Does anyone know of a more efficient method of doing
this?  I also have a question about the SortList routine.  At first I tried:

Sub SortList()
Dim myArray
myArray = Me.ComboBox1.List
Me.ComboBox1.Clear
WordBasic.SortArray myArray
Me.ComboBox1.List = myArray
End Sub

I didn't get any errors, but the list isn't sorted either.

I then added a few message boxes and I am seeing some behaviour that I
really don't understand.  When I step through this code the first message
box correctly reports the number of items I expect to be in the array.
However, the next line generates a run time error 9 "subscript out of range"

Since the code above doesn't generate an error and does repopulate the
combobox with an "unsorted" list, it seems that the values in the array are
valid so I don't see why and error occurs in the following code.  Maybe
someone can tell me why?

Sub SortList()
Dim myArray
myArray = Me.ComboBox1.List
Me.ComboBox1.Clear
WordBasic.SortArray myArray
MsgBox UBound(myArray)
MsgBox myArray(UBound(myArray))
Me.ComboBox1.List = myArray
End Sub

Signature

Greg Maxey/Word MVP
See:
http://gregmaxey.mvps.org/word_tips.htm
For some helpful tips using Word.

Helmut Weber - 09 Sep 2007 12:15 GMT
Hi Greg,

nothing wrong with storing some values
in doc-variables, I think.

The strange thing I came across is
that assigning a list to a variant
creates a 2 dimensional array!

All I could find was a small hint there by David Sisson
http://tinyurl.com/yoelvj

Never heard about that before. But its true.

Private Sub CommandButton3_Click()
Dim myArray
myArray = Me.ComboBox1.List
' MsgBox myArray(1) ' no way
' MsgBox myArray(2) ' no way
MsgBox myArray(1, 0) ' !!!
MsgBox myArray(2, 0) ' !!!
End Sub

Don't ask me how to sort a 2 dimensional array
using wordbasic. I usually do the sorting myself,
using very much frowned on bubble sort,
but it is reliable and entirely under my control.

Viel Spass!
(Lot of fun.)

Signature

Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"

Jay Freedman - 09 Sep 2007 14:22 GMT
Hi Helmut,

I hadn't thought about it before, but the dimension of the array does
make sense when you know that the .List of a combobox or listbox can
have multiple columns. That means the .List must be two-dimensional.
In the usual case when you assign a one-dimensional list to it, the
second dimension is defined as "0 to 0", but it's still there. Then
when you assign the .List to a Variant variable, the second dimension
is just carried along.

To sort a two-dimensional array, you have to pick one of the columns
to sort (usually the first) and use that element of each row in the
swap comparisons of the sorting algorithm.

--
Regards,
Jay Freedman
Microsoft Word MVP        FAQ: http://word.mvps.org
Email cannot be acknowledged; please post all follow-ups to the
newsgroup so all may benefit.

>Hi Greg,
>
[quoted text clipped - 26 lines]
>Viel Spass!
>(Lot of fun.)
Greg Maxey - 09 Sep 2007 14:48 GMT
Jay, Helmut

Yes, after looking at Jonathan West's article on SortArray I think I
understand why .List doesn't work with the WordBasic.SortArray method.
Looking at the VBA help, .List returns a variant two dimensional array.  As
Jonathan explains, SortArray doesn't work with variants.

I did figure out a way to use .List in my code with the Bubble Sort
Algorithm.  Thanks.

Private Sub UserForm_Initialize() '
Dim oVar As Word.Variable
Dim oVars As Word.Variables
Set oVars = ActiveDocument.Variables
With Me.ComboBox1
 .AddItem "Greg"
 .AddItem "Susan"
 .AddItem "Doria"
 For Each oVar In oVars
   If InStr(oVar.Name, "AI") = 1 Then
     .AddItem oVar.Value
   End If
 Next oVar
 'SortList
 Me.ComboBox1.List = BubbleSort(Me.ComboBox1.List)
End With
End Sub

Function BubbleSort(TempArray As Variant) As Variant
Dim Temp As Variant
Dim i As Integer
Dim bolExchange As Integer
Do
 bolExchange = False
 'Loop through each element in the array.
 For i = LBound(TempArray) To UBound(TempArray) - 1
   'If element > next element then exchange the two elements.
   If LCase(TempArray(i, 0)) > LCase(TempArray(i + 1, 0)) Then
     bolExchange = True
     Temp = TempArray(i, 0)
     TempArray(i, 0) = TempArray(i + 1, 0)
     TempArray(i + 1, 0) = Temp
   End If
 Next i
Loop While bolExchange
BubbleSort = TempArray
End Function

Signature

Greg Maxey/Word MVP
See:
http://gregmaxey.mvps.org/word_tips.htm
For some helpful tips using Word.

> Hi Helmut,
>
[quoted text clipped - 40 lines]
>> Viel Spass!
>> (Lot of fun.)
Helmut Weber - 09 Sep 2007 21:34 GMT
Hi Jay,

>the .List of a combobox or listbox can have multiple columns.

sure.

But if it has only one column,
why then create a two dimensional array?

Does a 2 column listbox create a 3 dimensional array?

I could try it out myself, but I'm kind of exhausted
and may be you just happen to know.

Signature

Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"

Greg Maxey - 09 Sep 2007 23:05 GMT
Helmut, Jay

The help file says the row and column are required in the .List syntax.
Syntax
object.List( row, column ) [= Variant]

The List property syntax has these parts:

     Part Description
     object Required. A valid object.
     row Required. An integer with a range from 0 to one less than the
number of entries in the list.
     column Required. An integer with a range from 0 to one less than the
number of columns.
     Variant Optional. The contents of the specified entry in the ListBox
or ComboBox.

So even though you can use a one dimensional array and .List to populate a
combobox.  The value returned by .List is two dimensional:

Private Sub UserForm_Initialize()
Dim myArray() As String
Dim i as Long
Dim myArray1
myArray = Split("A|B|C|D|E", "|")
Me.ComboBox1.List = myArray 'Populate the combobox with a one dimensional
array
myArray1 = Me.ComboBox1.List 'Get the value of the list
For i = LBound(myArray) To UBound(myArray)
 MsgBox myArray1(i, 0) 'If you don't use the , 0 then you get a subscript
out of range error.
Next i
End Sub

The help also says to:  Use List to copy an entire two-dimensional array of
values to a control. Use AddItem to load a one-dimensional array or to load
an individual element.,

Still, I alwasy use .List to load a one one-dimensional array.  E.g.,

Private Sub UserForm_Initialize()
Dim myArray() As String
myArray = Split("A|B|C|D|E", "|")
Me.ComboBox1.List = myArray
End Sub

Other than stepping through each member of the the array I don't see how
.AddItem could be used to load a one dimensional array.

Private Sub UserForm_Initialize()
Dim myArray() As String
Dim i As Long
myArray = Split("A|B|C|D|E", "|")
For i = LBound(myArray) To UBound(myArray)
 Me.ComboBox1.AddItem myArray(i)
Next i
End Sub

Am I missing something?

Signature

Greg Maxey/Word MVP
See:
http://gregmaxey.mvps.org/word_tips.htm
For some helpful tips using Word.

> Hi Jay,
>
[quoted text clipped - 9 lines]
> I could try it out myself, but I'm kind of exhausted
> and may be you just happen to know.
Doug Robbins - Word MVP - 10 Sep 2007 04:24 GMT
Hi Greg,

Take a look at the sorting routines in the Training Tracker Template that I
sent to you on 26 January this year.

Signature

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

> Helmut, Jay
>
[quoted text clipped - 69 lines]
>> I could try it out myself, but I'm kind of exhausted
>> and may be you just happen to know.
Greg Maxey - 10 Sep 2007 12:46 GMT
Thanks Doug.  Have you ever located a sample source document for use with
this template.  The coding examples are excellent, but sometimes difficult
to follow since I can't step through the process without the sourcedocument.

Signature

Greg Maxey/Word MVP
See:
http://gregmaxey.mvps.org/word_tips.htm
For some helpful tips using Word.

> Hi Greg,
>
[quoted text clipped - 80 lines]
>>> I could try it out myself, but I'm kind of exhausted
>>> and may be you just happen to know.
Jay Freedman - 10 Sep 2007 04:28 GMT
>Am I missing something?

No, you're not -- it's just the Help writers giving some bogus advice.

I wouldn't consider using .AddItem just because the data was a
one-dimensional list. Compared to assigning an array to the .List
property, it's extra work. I would use it when adding a single entry,
for example when using a combo box and the user has typed an entry
that doesn't exist in the list yet.

On the other hand, since .AddItem can't handle multiple columns in one
step, you have to use .List (or .Column, which does a transpose of the
rows and columns) in that case, or else do a lot of extra work to
stuff in the extra columns after the first.

Cheers,
Jay

>Helmut, Jay
>
[quoted text clipped - 55 lines]
>
>Am I missing something?

--
Regards,
Jay Freedman
Microsoft Word MVP        FAQ: http://word.mvps.org
Email cannot be acknowledged; please post all follow-ups to the newsgroup so all may benefit.
Jay Freedman - 10 Sep 2007 04:19 GMT
>Hi Jay,
>
[quoted text clipped - 9 lines]
>I could try it out myself, but I'm kind of exhausted
>and may be you just happen to know.

No 3-dimensional array, it's always 2-dimensional. If you store a
1-dimensional array of values in it, the result is a 2-dimensional
array where the only valid index of the second dimension is 0. This
'looks' like a 1-dimensional array, but it can't be addressed with
only one index -- the ,0 is required.

The 'why' is that it was easier for the creators of VBA to treat all
lists as 2-dimensional; they didn't have to write extra code to handle
the special 1-dimensional case. Instead, they stuck us with the job.

Cheers,
Jay

--
Regards,
Jay Freedman
Microsoft Word MVP        FAQ: http://word.mvps.org
Email cannot be acknowledged; please post all follow-ups to the newsgroup so all may benefit.
Jonathan West - 10 Sep 2007 10:38 GMT
> Hi Helmut,
>
> I hadn't thought about it before, but the dimension of the array does
> make sense when you know that the .List of a combobox or listbox can
> have multiple columns. That means the .List must be two-dimensional.

Exactly. When  1-col listbox whose list property is assigned to a Variant
containing an array, the array created is 2-dimensional, but with only one
column. In other words, a 5-item listbox will be converted to items (0, 0)
to (4, 0) of an array.

> In the usual case when you assign a one-dimensional list to it, the
> second dimension is defined as "0 to 0", but it's still there. Then
> when you assign the .List to a Variant variable, the second dimension
> is just carried along.

Strictly speaking, when assigning an array to a List property of a listbox,
what happens is that the program is clever enough to decide that a 1-d array
can be treated as a 2-d array with 1 column. If you assign the List property
immediately back to another array, you will get a 2-D array of one column.

> To sort a two-dimensional array, you have to pick one of the columns
> to sort (usually the first) and use that element of each row in the
> swap comparisons of the sorting algorithm.

There are plenty of sorting algorithms available on the net. Just plug VB
Quicksort into a search engine.

Signature

Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup

Ian Bayly - 14 Sep 2007 03:01 GMT
A bit late in the thread but a sort technique I have used which is
particularly useful when sorting complex list box contents, is to write the
list contents out as temporary text file and read back in using MS ODBC text
driver.
This will accept standard SQL queries and is great where sort involves a
date (although displayed as string)  for example.

Cheers

Ian B

>I have been playing around with some code to allow a user to type in their
>own data in a combobox and then make that entry permanently a part of the
[quoted text clipped - 96 lines]
> Me.ComboBox1.List = myArray
> End Sub

Rate this thread:






 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.