Я создал новый Workbook
и новый UserForm
с ListBox
, TextBox
и CommandButton
с именами по умолчанию для этого примера.
Option Explicit
____________________________________________________________________________________
Private Sub CommandButton1_Click()
Dim NextBlankRow As Long
Dim TargetRange As Range
Dim ListBoxItem As Long
Dim SelectedItemsArray As Variant
Dim ArrayElementCounter As Long
ArrayElementCounter = 0
With Me.ListBox1
ReDim SelectedItemsArray(0 To .ListCount - 1)
For ListBoxItem = 0 To .ListCount - 1
If .Selected(ListBoxItem) Then
SelectedItemsArray(ArrayElementCounter) = .List(ListBoxItem)
ArrayElementCounter = ArrayElementCounter + 1
End If
Next ListBoxItem
End With
ReDim Preserve SelectedItemsArray(0 To ArrayElementCounter - 1)
With ThisWorkbook.Sheets("Sheet1")
NextBlankRow = .Cells(Rows.Count, 3).End(xlUp).Row + 1
Set TargetRange = .Range("C" & NextBlankRow & ":C" & NextBlankRow + UBound(SelectedItemsArray))
End With
Dim TargetCell As Range
ArrayElementCounter = 0
For Each TargetCell In TargetRange
TargetCell.Value = Me.TextBox1.Value
TargetCell.Offset(0, 2).Value = SelectedItemsArray(ArrayElementCounter)
ArrayElementCounter = ArrayElementCounter + 1
Next TargetCell
End Sub
____________________________________________________________________________________
Private Sub UserForm_Initialize()
Dim ListBoxItemArray As Variant
ListBoxItemArray = Array("Listbox Item 1", "Listbox Item 2", "Listbox Item 3")
Dim ItemToAdd As Long
For ItemToAdd = LBound(ListBoxItemArray) To UBound(ListBoxItemArray)
Me.ListBox1.AddItem (ListBoxItemArray(ItemToAdd))
Next ItemToAdd
End Sub
Вот скриншоты входов и выходов:
Данные, выбранные / введенные в UserForm
[![Screenshot of UserForm with selected listbox items and textbox text[1]](https://i.stack.imgur.com/S5k6o.png)
Вывод на рабочий лист
![Screenshot of output to the worksheet](https://i.stack.imgur.com/F4ikj.png)
Объяснение:
Private Sub UserForm_Initialize()
событие заполняет ListBox
для целей моего примера - вы можете игнорировать это, когда дело доходит до вашего кода, но я счел необходимым указать, как я заполнил ListBox Items
и какими значениями.
Код события Private Sub CommandButton1_Click()
разбит на 4 основных раздела (начиная с объявления переменных):
With Me.LisBox1...End With
Очень Первое, что мы здесь делаем, это устанавливаем размер массива с помощью оператора ReDim
. Для UpperBound
или предела массива установлено свойство ListCount
минус 1, что возвращает 1 меньше количества элементов в ListBox
. Это гарантирует, что наш массив достаточно большой, чтобы вместить все значения элементов списка, если они все были выбраны, например, но делает это динамически, поэтому вы не тратите память, используя неоднозначное число, для проверки вашего кода в будущем, например 100
, когда у вас может быть только 30 предметов. Если элементы добавлены или удалены, массив будет всегда правильного размера.
Причина, по которой мы минус 1, состоит в том, что я объявил от Option Base
до 0
для массива, что означает, что он начинается с (или Lower Bound
is) 0, а не с 1. См. Option Base Заявление для получения дополнительной информации.
Далее мы проходим oop через каждый ListBox
элемент и оцениваем, является ли он Selected
или нет. Если это так, мы используем свойство List()
, чтобы присвоить значение этого элемента массиву. См. Для ... Следующие циклы для получения дополнительной информации о том, как они работают, и см. Использование массивов для их работы.
Теперь у нас есть SelectedItemsArray()
полных значений для каждого выбранного элемента в списке.
ReDim Preserve SelectedItemsArray(0 To ArrayElementCounter - 1)
Так же, как и раньше, мы устанавливаем размер нашего массива, но на этот раз, включая часть оператора Preserve
. Это означает, что мы можем изменить размер массива, но сохранить все текущие значения в нем - Если бы мы не использовали Preserve
, массив был бы изменен, но потерял бы все значения. Мы снова устанавливаем Upper Bound
динамически, чтобы изменить размер массива до количества выбранных элементов. (См. Using Arrays информацию о размерах массива et c.)
With ThisWorkbook.Sheets("Sheet1")...End With
В этом блоке With
мы находим последнюю использованную строку Column C
и присваиваем эту строку + 1 (поэтому она ссылается на следующую пустую строку) на LastUsedRow
. Мы также определяем наш диапазон, который мы хотим записать в наши данные динамически, используя переменную LastUsedRow
и Upper Bound
нашего массива. Это сделано для того, чтобы в следующем разделе кода было записано правильное количество ячеек.
For Each TargetCell In TargetRange...Next TargetCell
Еще один l oop, но на этот раз используется For Each...Next
. Очень похоже на For...Next
l oop, но этот цикл проходит через элементы массива или коллекции - в этом случае мы будем проходить через каждую ячейку в нашем TargetRange
.
Для каждой ячейки в диапазоне, помня, что наш диапазон установлен в Column C
из следующей пустой строки, значение TextBox
записывается в столбец C и каждое значение элемента ListBox
из нашего массива записывается в столбец E. При выполнении итерации l oop увеличивается ArrayItemCounter
, что обеспечивает запись следующего элемента массива в столбец E с каждым l oop.