Сортировка listbox vba excel
Отображает список значений и позволяет выбирать одно или несколько значений.
Комментарии
Если ListBox привязан к источнику данных, ListBox сохраняет выбранное значение в этом источнике данных.
ListBox может отображаться как список, так и как группа элементов управления OptionButton или CheckBox.
Свойство по умолчанию для ListBox — это свойство Value .
Событие по умолчанию для ListBox — событие Click .
В раскрывающийся элемент ListBox невозможно поместить текст.
Стили элемента ListBox
Вы можете выбрать любой из двух стилей представления элемента ListBox. Это выражается свойством ListStyle . Каждый из них реализует собственный способ выбора элементов в списке.
Если стиль 0, каждый элемент находится в отдельной строке; пользователь выбирает элемент, выделяя одну или несколько строк.
Если стиль 1, в начале каждой строки появляется OptionButton или CheckBox . В этом случае для выбора элемента пользователь нажимает кнопку или устанавливает флажок. Флажки отображаются только тогда, когда свойство MultiSelect является true.
События
Имя | Описание |
---|---|
Click | Возникает, когда пользователь окончательно выбирает значение для управления, которое имеет несколько возможных значений. |
Методы
Имя | Описание |
---|---|
AddItem | Для одного столбца ListBox метод AddItem добавляет элемент в список. Для многоуровневого ListBox этот метод добавляет строку в список. |
Clear | Удаляет все записи в списке в ListBox. |
RemoveItem | Удаляет строку из списка в ListBox. |
Свойства
Имя | Описание |
---|---|
BackColor | Возвращает или задает длинный, который указывает фоновый цвет объекта. Для чтения и записи. |
BorderColor | Возвращает или задает long , который указывает пограничный цвет объекта. Для чтения и записи. |
BorderStyle | Возвращает или задает набор integer , который указывает тип границы управления. Для чтения и записи. |
BoundColumn | Возвращает или задает вариант, определяя источник данных в многослойном ListBox. Для чтения и записи. |
Столбец | Возвращает или задает вариант, представляющие одно значение, столбец значений или двухмерный массив для загрузки в ListBox. Для чтения и записи. |
ColumnCount | Возвращает или задает long , представляют число столбцов, отображаемого в поле списка. Для чтения и записи. |
ColumnHeads | Возвращает или задает boolean , который указывает, отображается ли одна строка заголовков столбцов. Для чтения и записи. |
ColumnWidths | Возвращает или задает строку, которая указывает ширину каждого столбца в многослойном ListBox. Для чтения и записи. |
Enabled | Возвращает или задает boolean , который указывает, может ли управление получать фокус и реагировать на события, созданные пользователем. Для чтения и записи. |
ForeColor | Возвращает или задает длинный, который указывает цвет переднего плана объекта. Для чтения и записи. |
IMEMode | Возвращает или задает integer , который указывает режим времени работы по умолчанию редактора метода ввода (IME) для управления. Для чтения и записи. |
IntegralHeight | Возвращает или задает boolean , который указывает, отображает ли ListBox полные строки текста в списке или частичные строки. Для чтения и записи. |
Перечисление | Возвращает или задает вариант, представляющие указанную запись в ListBox. Для чтения и записи. |
ListCount | Возвращает длинный , который представляет количество записей списка в области управления. Только для чтения. |
ListIndex | Возвращает или задает вариант, представляющие выбранный в настоящее время элемент в ListBox. Для чтения и записи. |
ListStyle | Возвращает или задает набор integer , который указывает визуальное появление списка в ListBox. Для чтения и записи. |
Locked | Возвращает или задает boolean , который указывает, можно ли изменить управление. Для чтения и записи. |
MatchEntry | Возвращает или задает набор integer , который указывает, как ListBox выполняет поиск своего списка в качестве типов пользователей. Для чтения и записи. |
MouseIcon | Возвращает строку, которая представляет полное имя пути настраиваемого значка, назначенного для управления. Только для чтения. |
MousePointer | Возвращает или задает набор integer , который указывает тип указателя, отображаемого при позиционировании пользователя мыши над определенным объектом. Для чтения и записи. |
MultiSelect | Возвращает или задает набор integer , который указывает, разрешает ли объект несколько выборов. Для чтения и записи. |
Selected | Возвращает или задает boolean , который указывает состояние выбора элементов в ListBox. Для чтения и записи. |
SpecialEffect | Возвращает или задает набор integer , который указывает внешний вид объекта. Для чтения и записи. |
Text | Возвращает или задает строку, которая указывает текст в ListBox, изменяя выбранную строку в диспетчере. Для чтения и записи. |
TextAlign | Возвращает или задает набор integer , который указывает, как текст выравнивается в области управления. Для чтения и записи. |
TextColumn | Возвращает или задает вариант, который идентифицирует столбец в ListBox для отображения пользователю. Для чтения и записи. |
TopIndex | Возвращает или задает длинный , представляютельный индекс элемента списка, отображаемого в верхней позиции в списке. Для чтения и записи. |
Value (Значение) | Возвращает или задает вариант, который указывает значение в BoundColumn выбранных в настоящее время строк. Для чтения и записи. |
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
I received a question from a reader recently, who wanted to sort a Listbox using VBA. As this seemed like a common problem which many users could face, I decided to dedicate a bit of time to create a more reusable solution.
- UserForm Listboxes for custom VBA solutions
- Form Control Listboxes for worksheet based solutions
This post may seem like a lot of VBA code, but are comments inserted into the code to understand what is happening. Within the text I included my thought process, to illustrate how I approached the scenario. Whether my approach is right or wrong, it’s how I think about VBA.
- Standard order (the order the elements are added to the list box)
- Reverse order (the reverse of the standard order)
- A-Z sort
- Z-A sort
Download the workbook
Sometimes it is easier to see the solution in action. So you can download the file by clicking the link below.
Disclaimer:
Whilst I try to create safe and reliable templates and add-ins, I can (and often do) make mistakes. Please backup copies of your files before opening any templates, add-ins or using any information you find on the site. If you do find any bugs or errors, please let me know using my contact page. By using any templates, add-ins, downloads or information from the site, you agree that I will not be held liable for any type of damages, and use is entirely at your own risk.
Re-usable code
- The code which performs the main actions is contained within a standard module
- The code contained within the UserForm module intercepts the events (i.e. button clicks) then calls a macro from the standard module
- The variables used for the macros within the standard module are passed as arguments when calling the macro
- The list is re-created each time it is sorted, no matter which sort method is selected. This ensures the list is updated for any changes whenever it is sorted. The piece of reusable code which clears and re-creates the list I am calling the “resetMacro”.
Listboxes on UserForms
- a ListBox
- four buttons for the different sort options
- a close button
VBA code included in a standard module
The following is the code to include in the standard module, which performs the main actions.
Display the UserForm
The first code, will simply display the UserForm when a button is clicked.
Populate the ListBox
- when the UserForm is initialized
- when the btnStandard button is clicked
- within all the other sort macros to recreate the list.
Reverse the items in the ListBox
The following code will first call the “resetMacro” to refresh the ListBox, then sort it in reverse order.
A-Z sort the List Box
The following code will first call the “resetMacro” to refresh the ListBox, then sort it in A-Z order using the Bubble sort method.
- Using the Bubble Sort method, the last item does not need to be sorted. If every other item in the list is sorted correctly, then the last item must also be in the correct place (so that is the first -1).
- The first item in a UserForm ListBox is item 0, rather than 1. Therefore, as the list starts at zero, we can -1 from the count to ensure we loop through all the items once.
Note: When using a Form Control list box, the first list position is 1, so the Form Control VBA code further down the post only has -1, rather than -2.
Z-A sort the ListBox
The following code will first call the “resetMacro” to refresh the ListBox, then sort it in Z-A order using the Bubble sort method.
VBA code included in the UserForm code module
The following sections of code are all included within the UserForm module. The code here is primarily to call the macros in the standard module, which we covered in the section above.
The name of the ListBox in the example is lstListBox.
Initialize the UserForm
When the UserForm first opens the UserForm_Initialize code executes. In our example, when the UserForm opens it calls the UserFormList macro, passing the lstListBox as an object variable into the macro.
Clicking the btnClose Button
The close button with Unload the UserForm.
Clicking the btnStandard button
The first button calls the macro to return the list to its original order. The code UserFormList is called, passing the lstListBox as an object variable.
Clicking the btnReverse button
The second button calls the macro to reverse the order of the list. In our example, the code UserFormReverseList is called. Two arguments are passed (1) the ListBox object (2) the name of the resetMacro.
Clicking the btnAZ button
The third button calls the macro to sort the list in A-Z order. The code UserFormSortAZ is called. Two arguments are passed (1) the ListBox object (2) the name of the “resetMacro”.
Clicking btnZA button
The fourth button calls the macro to sort the list in Z-A order. The code UserFormSortZA is called. Two arguments are passed (1) the ListBox object (2) the “resetMacro”.
That now completes the code used to sort a ListBox contained within a UserForm.
Form Control Listboxes on the worksheet
The code in this section is for use with a Form Control ListBox.
- Standard sort: FormControlList “lstListBox”‘
- Reverse sort: FormControlReverse “lstListBox”, “FormControlList”‘
- A-Z sort: FormControlSortAZ “lstListBox”, “FormControlList”‘
- Z-A sort: FormControlSortZA “lstListBox”, “FormControlList”‘
VBA code included in a standard module
The following code is all included in the standard module.
Populate the ListBox
- when the btnStandard button is clicked
- within all the other sort macros to recreate the list (i.e. the “resetMacro”).
Reverse the items in the ListBox
The following code will first call the “resetMacro” to update the ListBox, then sort it in reverse order.
A-Z sort the List Box
The following code will first call the “resetMacro” to update the ListBox, then sort it in A-Z order using the Bubble sort method.
Z-A sort the List Box
The following code will first call the “resetMacro” to update the ListBox, then sort it in Z-A order using the Bubble sort method.
Conclusion
In this post, we have seen two methods to sort ListBoxes using VBA using reusable code segments. Obviously, to be useful this needs to be part of a bigger project. Feel free to take this and adapt it as you need to.
Get our FREE VBA eBook of the 30 most useful Excel VBA macros.
Automate Excel so that you can save time and stop doing the jobs a trained monkey could do.
Don’t forget:
If you’ve found this post useful, or if you have a better approach, then please leave a comment below.
Do you need help adapting this to your needs?
I’m guessing the examples in this post didn’t exactly meet your situation. We all use Excel differently, so it’s impossible to write a post that will meet everybody’s needs. By taking the time to understand the techniques and principles in this post (and elsewhere on this site) you should be able to adapt it to your needs.
- Read other blogs, or watch YouTube videos on the same topic. You will benefit much more by discovering your own solutions.
- Ask the ‘Excel Ninja’ in your office. It’s amazing what things other people know.
- Ask a question in a forum like Mr Excel, or the Microsoft Answers Community. Remember, the people on these forums are generally giving their time for free. So take care to craft your question, make sure it’s clear and concise. List all the things you’ve tried, and provide screenshots, code segments and example workbooks.
- Use Excel Rescue, who are my consultancy partner. They help by providing solutions to smaller Excel problems.
What next?
Don’t go yet, there is plenty more to learn on Excel Off The Grid. Check out the latest posts:
Поиск результатов не дал, по этому спрашиваю в отдельной теме.
Каким образом можно отсортировать по убыванию ListBox содержащий список дат?
Поиск результатов не дал, по этому спрашиваю в отдельной теме.
Каким образом можно отсортировать по убыванию ListBox содержащий список дат? keeper
Поиск результатов не дал, по этому спрашиваю в отдельной теме.
Каким образом можно отсортировать по убыванию ListBox содержащий список дат? Автор - keeper
Дата добавления - 23.01.2015 в 10:26
Добавил к себе вот такой слегка видоизмененный кусок кода
[vba]
Type QuickStack
'тип для QuickSort
Low As Long
High As Long
End Type
Sub QuickSortNonRecursive(ByRef SortArray(), Optional Descending As Boolean)
Dim i As Long, j As Long, lb As Long, ub As Long
Dim stack() As QuickStack, stackpos As Long, maxstackpos As Long, stposArrMax As Long, ppos As Long, pivot As Variant, swp
lb = LBound(SortArray)
ub = UBound(SortArray)
stposArrMax = 16
ReDim stack(stposArrMax)
stackpos = 1
maxstackpos = 1
stack(1).Low = lb
stack(1).High = ub
Do
lb = stack(stackpos).Low
ub = stack(stackpos).High
stackpos = stackpos - 1
Do
ppos = (lb + ub) \ 2
i = lb: j = ub: pivot = SortArray(ppos)
Do
While IIf(Descending, SortArray(i) > pivot, SortArray(i) < pivot): i = i + 1: Wend
While IIf(Descending, pivot > SortArray(j), pivot < SortArray(j)): j = j - 1: Wend
If i > j Then Exit Do
swp = SortArray(i): SortArray(i) = SortArray(j): SortArray(j) = swp
i = i + 1
j = j - 1
Loop While i
If i < ppos Then
stackpos = stackpos + 1
If stackpos > maxstackpos Then maxstackpos = stackpos
If stackpos > stposArrMax Then stposArrMax = stposArrMax * 2: ReDim Preserve stack(stposArrMax)
stack(stackpos).Low = i
stack(stackpos).High = ub
ub = j
Else
If j > lb Then
stackpos = stackpos + 1
If stackpos > maxstackpos Then maxstackpos = stackpos
If stackpos > stposArrMax Then stposArrMax = stposArrMax * 2: ReDim Preserve stack(stposArrMax)
stack(stackpos).Low = lb
stack(stackpos).High = j
End If
lb = i
End If
Loop While lb < ub
Loop While stackpos
End Sub
Заполняю одномерный массив датами и передаю в процедуру QuickSortNonRecursive()
Dim i, z As Integer
Dim ArrName(5) As Variant
' Заполняем массив както-так.
For z = 1 To 5
ArrName(z-1) = . дата
Next z
'Сортируем массив
Call QuickSortNonRecursive(ArrName)
i = y
'Заполняем ListBox в обратной последовательности, не обязательно, можно воспользоваться параметром Descending в процедуре
Do While i > 0
ListBox1.AddItem (CStr(ArrName(i)))
i = i - 1
Loop
Добавил к себе вот такой слегка видоизмененный кусок кода
[vba]
Type QuickStack
'тип для QuickSort
Low As Long
High As Long
End Type
Sub QuickSortNonRecursive(ByRef SortArray(), Optional Descending As Boolean)
Dim i As Long, j As Long, lb As Long, ub As Long
Dim stack() As QuickStack, stackpos As Long, maxstackpos As Long, stposArrMax As Long, ppos As Long, pivot As Variant, swp
lb = LBound(SortArray)
ub = UBound(SortArray)
stposArrMax = 16
ReDim stack(stposArrMax)
stackpos = 1
maxstackpos = 1
stack(1).Low = lb
stack(1).High = ub
Do
lb = stack(stackpos).Low
ub = stack(stackpos).High
stackpos = stackpos - 1
Do
ppos = (lb + ub) \ 2
i = lb: j = ub: pivot = SortArray(ppos)
Do
While IIf(Descending, SortArray(i) > pivot, SortArray(i) < pivot): i = i + 1: Wend
While IIf(Descending, pivot > SortArray(j), pivot < SortArray(j)): j = j - 1: Wend
If i > j Then Exit Do
swp = SortArray(i): SortArray(i) = SortArray(j): SortArray(j) = swp
i = i + 1
j = j - 1
Loop While i
If i < ppos Then
stackpos = stackpos + 1
If stackpos > maxstackpos Then maxstackpos = stackpos
If stackpos > stposArrMax Then stposArrMax = stposArrMax * 2: ReDim Preserve stack(stposArrMax)
stack(stackpos).Low = i
stack(stackpos).High = ub
ub = j
Else
If j > lb Then
stackpos = stackpos + 1
If stackpos > maxstackpos Then maxstackpos = stackpos
If stackpos > stposArrMax Then stposArrMax = stposArrMax * 2: ReDim Preserve stack(stposArrMax)
stack(stackpos).Low = lb
stack(stackpos).High = j
End If
lb = i
End If
Loop While lb < ub
Loop While stackpos
End Sub
Заполняю одномерный массив датами и передаю в процедуру QuickSortNonRecursive()
Dim i, z As Integer
Dim ArrName(5) As Variant
' Заполняем массив както-так.
For z = 1 To 5
ArrName(z-1) = . дата
Next z
'Сортируем массив
Call QuickSortNonRecursive(ArrName)
i = y
'Заполняем ListBox в обратной последовательности, не обязательно, можно воспользоваться параметром Descending в процедуре
Do While i > 0
ListBox1.AddItem (CStr(ArrName(i)))
i = i - 1
Loop
Добавил к себе вот такой слегка видоизмененный кусок кода
[vba]
Type QuickStack
'тип для QuickSort
Low As Long
High As Long
End Type
Sub QuickSortNonRecursive(ByRef SortArray(), Optional Descending As Boolean)
Dim i As Long, j As Long, lb As Long, ub As Long
Dim stack() As QuickStack, stackpos As Long, maxstackpos As Long, stposArrMax As Long, ppos As Long, pivot As Variant, swp
lb = LBound(SortArray)
ub = UBound(SortArray)
stposArrMax = 16
ReDim stack(stposArrMax)
stackpos = 1
maxstackpos = 1
stack(1).Low = lb
stack(1).High = ub
Do
lb = stack(stackpos).Low
ub = stack(stackpos).High
stackpos = stackpos - 1
Do
ppos = (lb + ub) \ 2
i = lb: j = ub: pivot = SortArray(ppos)
Do
While IIf(Descending, SortArray(i) > pivot, SortArray(i) < pivot): i = i + 1: Wend
While IIf(Descending, pivot > SortArray(j), pivot < SortArray(j)): j = j - 1: Wend
If i > j Then Exit Do
swp = SortArray(i): SortArray(i) = SortArray(j): SortArray(j) = swp
i = i + 1
j = j - 1
Loop While i
If i < ppos Then
stackpos = stackpos + 1
If stackpos > maxstackpos Then maxstackpos = stackpos
If stackpos > stposArrMax Then stposArrMax = stposArrMax * 2: ReDim Preserve stack(stposArrMax)
stack(stackpos).Low = i
stack(stackpos).High = ub
ub = j
Else
If j > lb Then
stackpos = stackpos + 1
If stackpos > maxstackpos Then maxstackpos = stackpos
If stackpos > stposArrMax Then stposArrMax = stposArrMax * 2: ReDim Preserve stack(stposArrMax)
stack(stackpos).Low = lb
stack(stackpos).High = j
End If
lb = i
End If
Loop While lb < ub
Loop While stackpos
End Sub
Заполняю одномерный массив датами и передаю в процедуру QuickSortNonRecursive()
Dim i, z As Integer
Dim ArrName(5) As Variant
' Заполняем массив както-так.
For z = 1 To 5
ArrName(z-1) = . дата
Next z
'Сортируем массив
Call QuickSortNonRecursive(ArrName)
i = y
'Заполняем ListBox в обратной последовательности, не обязательно, можно воспользоваться параметром Descending в процедуре
Do While i > 0
ListBox1.AddItem (CStr(ArrName(i)))
i = i - 1
Loop
I'd like to sort the items in my ListBox and have no clue how to do that. Can anyone help me?
Thanks in advance
Answers
Try the following.
Private Sub CommandButton3_Click()
'Sorts ListBox List
Dim i As Long
Dim j As Long
Dim temp As Variant
With Me.ListBox1
For j = 0 To ListBox1.ListCount - 2
For i = 0 To ListBox1.ListCount - 2
If .List(i) > .List(i + 1) Then
temp = .List(i)
.List(i) = .List(i + 1)
.List(i + 1) = temp
End If
Next i
Next j
End With
End Sub
All replies
Try the following.
Private Sub CommandButton3_Click()
'Sorts ListBox List
Dim i As Long
Dim j As Long
Dim temp As Variant
With Me.ListBox1
For j = 0 To ListBox1.ListCount - 2
For i = 0 To ListBox1.ListCount - 2
If .List(i) > .List(i + 1) Then
temp = .List(i)
.List(i) = .List(i + 1)
.List(i + 1) = temp
End If
Next i
Next j
End With
End Sub
Thank You OssieMac!
Would you mind looking at the question I posted earlier, which you could find at:
I was also trying to copy the entire ListBox1 into ListBox2 and could not figure out how.
Would you mind helping me?
Have answered your other question on MultiSelect.
The following code will copy the ListBox1 list to the ListBox3 list.
As a little additional information, .List is actually an array and is treated as an array when addressing the elements. As an alternative in the sort you can actually use the array properties of LBound and UBound for the first and last elements in the loop like the example below. Note that because UBound is actually the index number of the last item, only need to subtract 1 for the sort. (The reason for the sort loop being one less than the total number of elements is because the code continually compares to the next element so need to stop at second last element because the last loop then compares the second last element with the last element.)
Private Sub CommandButton4_Click()
'Sorts ListBox List (Addressing .List as an array)
Dim i As Long
Dim j As Long
Dim temp As Variant
With Me.ListBox1
For j = LBound(.List) To UBound(.List) - 1
For i = LBound(.List) To UBound(.List) - 1
If .List(i) > .List(i + 1) Then
temp = .List(i)
.List(i) = .List(i + 1)
.List(i + 1) = temp
End If
Next i
Next j
End With
End Sub
Hi OssieMac ~
and thank you for a very useful - and quick - bit of code!
This was the best and simplest code I found.
Since I needed a sort without regard to case, I found that if I substituted
"If UCase(.List(i)) > UCase(.List(i + 1)) Then"
for
"If .List(i) > .List(i + 1) Then"
then the resulting listbox is in non-case-sensitive alphabetical order.
Just thought I'd pass it along for others.
~ Jere
Hello here an update for a multi column listbox.
Sub SortListBox()
Dim i As Long, j As Long, x As Long, sTemp As String
With Me.ListBox1
For j = LBound(.List) To UBound(.List) - 1 Step 1
For i = LBound(.List) To UBound(.List) - 1 Step 1
If .List(i) > .List(i + 1) Then
For x = 0 To (.ColumnCount - 1) Step 1
sTemp = .List(i, x)
.List(i, x) = .List(i + 1, x)
.List(i + 1, x) = sTemp
Next x
End If
Next i
Next j
End With
End Sub
Can anyone explain what the variable "j" is for in the above code snippets? As far as I can tell it is redundant.
The 2 nested loops are required to complete the sort. Without the j loop the data will only be partially sorted and some of the elements can still be out of sorted order.
The code actually goes through the array and rearranges the data using the i variable for as many times as there are elements in the array less one element. Reason for less one element is that it always needs to compare to the next element and can't compare to an element that does not exist after the last element.
Brilliant, thank you. I was trying to make this work with a 2 column listbox and couldn't get it right. I thought that might have been the issue, but a quick change based on your explanation has fixed it. Very relieved.
Like a picture is worth a 1000 words, the same can be said for using an example to explain the code. Therefore, I thought that it might be worthwhile to post a code example that displays what I said about the sorting.
A MsgBox displays the initial array elements.
For each of the j loops there a MsgBox that displays the updated array elements after the i loop.
Note that initially 5 is the first element and it moves to the last position on the first i loop. This is because each time it is moved to the next position, on the next iteration of the i loop, it is greater than the following element and gets moved down again and therefore at the last element position after the first run of the i loop. However, because 1 is the smallest number, it takes all 4 loops to get to the first position.
Note that the List property of a ComboBox is in fact an array and Lbound and Ubound functions can be used with it just as with any other array.
Sub SortArray()
Dim arrSamp()
Dim i As Long
Dim j As Long
Dim temp As Variant
Dim c As Long
Dim strMsge As String
arrSamp() = Array(5, 2, 4, 3, 1)
strMsge = "Before any sorting" & vbCrLf
For c = 0 To 4
strMsge = strMsge & arrSamp(c) & vbCrLf
Next c
MsgBox strMsge
For j = LBound(arrSamp) To UBound(arrSamp) - 1
For i = LBound(arrSamp) To UBound(arrSamp) - 1
If arrSamp(i) > arrSamp(i + 1) Then
temp = arrSamp(i)
arrSamp(i) = arrSamp(i + 1)
arrSamp(i + 1) = temp
End If
Next i
strMsge = ""
For c = 0 To 4
strMsge = strMsge & arrSamp(c) & vbCrLf
Next c
MsgBox strMsge
Next j
«VBA Excel ListBox Multiselect»
Привязка диапазона данных к ListBox.
Добавление, удаление пунктов списка.
Сортировка списка и множественный выбор элементов.
ListBox или «окно со списком» – это один из элементов управления, который может быть расположен на форме для предоставления пользователю возможности выбора одного или нескольких элементов (пунктов) из предоставленного множества (списка) вариантов …
- Через свойство RowSource (источник строк) в список загружается определенный диапазон (колонка ячеек). В этом случае добавление новых пунктов в список или удаление существующих из списка в процессе выполнения макросов VBA не возможно… (по крайней мере, до момента присвоения свойству RowSource значения пустой строки).
- Через методы AddItem и RemoteItem (добавление или удаление пунктов списка)… Повторю, что для такой возможности, свойство RowSource должно иметь пустое значение.
Привязка к списку диапазона значений через свойство RowSource
Считаю, что для удобства реальной работы со списками на листах Excel (добавление новых значений в ячейки соответствующих колонок или удаление существующих) необходимо использовать функцию для автоматического определения номера последней заполненной строки в указанном столбце…
Метод Find объектов класса Range (рекомендую заглянуть в его справку) очень помогает в этом вопросе….
И так, функция может выглядеть, например, следующим образом….
Function GetLastRowFromColumn(numColumn As Integer) As Integer
GetLastRowFromColumn = Columns(numColumn).Cells.Find("*", , , , xlByRows, xlPrevious).Row
End Function
Как видите, единственным параметром она получает номер колонки (правда, для простоты я оставил всего один лист в книге, а иначе бы лист тоже пришлось бы указать как параметр), а возвращает номер строки той ячейки, которую вернул метод Find…
Тогда обработчики событий щелчков мышью по радиокнопкам будут выглядеть так…
Private Sub OptionButton1_Click()
lastrow = GetLastRowFromColumn(1)
If OptionButton1 Then Me.ListBox1.RowSource = "=A1:A" & lastrow
End Sub
Private Sub OptionButton2_Click()
lastrow = GetLastRowFromColumn(2)
If OptionButton2 Then Me.ListBox1.RowSource = "=B1:B" & lastrow
End Sub
Private Sub OptionButton3_Click()
lastrow = GetLastRowFromColumn(3)
If OptionButton3 Then Me.ListBox1.RowSource = "=C1:C" & lastrow
End Sub
Можно было бы и еще упростить (до одной строки в процедуре),
Me.ListBox1.RowSource = "=A1:A" & GetLastRowFromColumn(1)
но считаю, что наличие переменной lastrow помогает просматривать ее значение при отладке, а это сэкономленное время…. которое дороже, чем уменьшение объема кода…
В общем, первая радиокнопка помещает в список диапазон из колонки А (используя свойство RowSource), а вторая и третья, соответственно, из колонок В и С…
Множественный выбор
Основное свойство элемента ListBox – это List… индексированный список значений… (As Variant) Поэтому к любому элементу списка можно обратиться по индексу… ,например List(idx)…
И так же важно второе индексированное свойство Selected(idx), которое представляет собой массив логических величин, показывающий, выделен ли конкретный элемент списка пользователем или нет…
Private Sub CommandButton1_Click()
Dim n As Integer, s As String
s = ""
For n = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(n) Then
s = s & Me.ListBox1.List(n) & vbLf
End If
Next n
If s = "" Then
MsgBox "Нет выбранных пунктов", 0, "Выбранные пункты списка"
Else
MsgBox s, 0, "Выбранные пункты списка"
End If
Сортировка списка
А вот для сортировки списка нам придется отказаться от свойства RowSource , т.к. изменение порядка элементов списка будет противоречить привязанному диапазону. VBA справедливо заругается…
Вот процедура сортировки объекта ListBox (который передается в виде параметра As Object)
Sub mySort(aL As Object)
Dim locList() As Variant, siz As Long
'Сортирует список ListBox (свойство .List - как массив Variant)
Dim j As Long
siz = UBound(aL.List)
ReDim locList(UBound(aL.List))
For j = 0 To siz
locList(j) = .List(j)
Next j
.RowSource = ""
.Clear
mySortArray locList
For j = 0 To siz
.AddItem (locList(j))
Next j
End With
End Sub
Как видите, сначала создаем массив locList() нужной размерности и заполняем его элементами списка…
Затем отвязываем список от диапазона (aL.RowSource = "") и очищаем его (aL.Clear) …
А полученный массив сортируем обычным образом (любым из алгоритмов сортировки).
Все. Осталось загрузить отсортированный массив в список, используя метод AddItem, конечно же, в цикле…
Для возможности множественного выбора элементов списка, не забудьте задать свойство
ListBox1.MultiSelect = fmMultiSelectMulti
…
…
Все…
Читайте также: