У меня есть пользовательская форма со списком, использующая объект списка в качестве источника строк.
Я хочу выбрать несколько строк данных из списка, удалить соответствующие данные из списка, а затем обновить список.
Private Sub Delete_Click()
'Option Explicit is enabled
Dim ws As Worksheet
Dim tbl As ListObject
Dim myListBox As MSForms.listbox
Dim i As Long
Set ws = ThisWorkbook.Worksheets("Data")
Set tbl = ws.ListObjects("Table1")
Set myListBox = Me.listbox
With myListBox
For i = .ListCount - 1 To 0 Step -1
If .Selected(i) Then
tbl.ListRows(i + 1).Delete
End If
Next i
End With
myListBox.RowSource = ""
myListBox.RowSource = tbl
End Sub
У меня был код для удаления одной строки. Это для попытки удалить несколько строк.
Я могу выбрать несколько строк данных из списка, но он удалит только самую нижнюю строку данных, независимо от порядка выбора.
Спасибо карме! На самом деле это сработало очень хорошо! Я столкнулся с двумя проблемами, которые я пытаюсь понять. Первая ошибка заключается в том, что я получаю ошибку времени выполнения '91' Объектная переменная или переменная блока, не установленная в rgU.Delete. Эта проблема возникает, когда у меня осталась одна строка с данными внутри нее, и я пытаюсь ее удалить. Вторая ошибка возникает, когда я удаляю несколько строк. Он удалит все строки, кроме нижней. Он подталкивает эти данные к вершине. Я просто пытаюсь понять сейчас. Тем не менее, я взял концепцию, если это правильный термин, rgU и сделал код, который также работает примерно так же!
У меня есть код, который у меня есть в настоящее время, который несколько работает, но я не знаю надлежащего этикета для публикации нового кода или будет ли это теперь отдельным вопросом. Сказав это, вы мне очень помогли. Спасибо, Вантан.
Я допустил ошибку в этой строке ListBox1.RowSource = .Range.Address
. Вот почему он выдает вам ошибку. Пожалуйста, посмотрите на мой ответ ниже. Без rgU вы удаляете строки таблицы одну за другой внутри цикла. С rgU вы собираете/объединяете строку таблицы внутри цикла. Затем после цикла вы сразу удаляете строки в rgU. Спасибо.
Я допустил ошибку в коде в своем комментарии, а именно в этой строке ListBox1.RowSource = .Range.Address
. Должно быть ListBox1.RowSource = tbl.Range.Address
. И лучше, если данные листа не активны: ListBox1.RowSource = ws.Name & "!" & tbl.Range.Address
Чтобы протестировать приведенный ниже код, создайте пользовательскую форму с одним списком и одной командной кнопкой.
Dim ws As Worksheet
Dim tbl As ListObject
Private Sub UserForm_Initialize()
Set ws = ThisWorkbook.Worksheets("Data")
Set tbl = ws.ListObjects("Table1")
With ListBox1
.ColumnCount = 3
.RowSource = ws.Name & "!" & tbl.Range.Address
.ColumnWidths = "35,35,35"
.MultiSelect = fmMultiSelectExtended
End With
End Sub
Private Sub CommandButton1_Click()
Dim rgU As Range: Dim i As Integer
If Not tbl.DataBodyRange Is Nothing Then
With ListBox1
For i = 0 To .ListCount - 1
If .Selected(i) And i <> 0 Then If rgU Is Nothing Then Set rgU = tbl.ListRows(i).Range Else Set rgU = Union(rgU, tbl.ListRows(i).Range)
Next
rgU.Delete: .RowSource = ws.Name & "!" & tbl.Range.Address
End With
End If
End Sub
Источник строки для списка использует адрес таблицы, но в своем комментарии я забыл указать имя листа (который является данными листа) на случай, если данные листа не активны при отображении пользовательской формы. Теперь в приведенном выше коде я включаю имя листа (ws.name).
Поскольку это всего лишь тестовая подпрограмма, вам нужно, чтобы данные листа были активны перед отображением пользовательской формы, чтобы увидеть, удаляет ли она правильную строку в таблице.
Спасибо карме за помощь. Я смог заставить его работать! Мне просто нужно было отключить свойство заголовка столбца listbox1. Я пытался заставить его работать с включенными заголовками, но это вызывает у меня много проблем. Я предпочитаю внешний вид заголовков столбцов в списке, но у меня проблемы с заголовками. Я получаю две строки с заголовками, являющимися второй строкой. Первая строка показывает по столбцам a,b,c и d. соответственно а, б, в и г. Если вы знаете, почему это так, я хотел бы знать, как последовательно заставить его работать! Если нет спасибо за помощь. Я собираюсь применить это не только к удалению.
Вы написали: я получаю две строки с заголовками, являющимися второй строкой. Предположим, что в строке 1 у вас есть a, b и c, а в строке 2 у вас есть AAA, BBB и CCC. На мой взгляд, возможно, когда вы создаете таблицу, вы включаете row1. Таким образом, ваши ListObjects ("Table1") начинаются с строки 1 с заголовком a, b, c. Может быть, поэтому в списке отображаются a, b, c и AAA, BBB, CCC. если при создании таблицы вы определяете диапазон, начинающийся со строки 2, то ваши ListObjects ("Table1") начинаются со строки 2, и вы не увидите в списке a, b и c, а AAA, BBB и CCC.
Это определенно имеет смысл, поскольку это была и моя мысль! Мне просто нужно выяснить, как заставить его работать правильно. Хотя я сделал так, чтобы информация заголовков помещалась в правильное место, когда включены заголовки столбцов, после этого все становится не так. Я попытаюсь что-нибудь удалить, а потом данные начнут перемещаться в разные места. С учетом сказанного я сделаю все возможное, чтобы это произошло, а если нет, я отправлю вопрос с моим кодом. Спасибо за помощь Карме, Вантан
Может попробовать добавить одну переменную...
dim rgU as range
. rgU используется для сбора всех выбранных строк таблицы на основе выбранного элемента в списке. Затем используйте такую петлюFor i = 0 To .ListCount - 1:If .Selected(i) and i<>0 Then If rgU Is Nothing Then Set rgU = tbl.ListRows(i).Range Else Set rgU = Union(rgU, tbl.ListRows(i).Range):next
, затем добавьтеrgU.delete:ListBox1.RowSource = .Range.Address:end with
. Обратите внимание, что источник строки списка использует диапазон tbl.address. Итак, списки начинаются с 1 (это строка 2, поскольку строка 1 является заголовком таблицы), поэтому она нужнаand i<>0