Как удалить значения на листе «база данных»?
Когда вы назначаете элементы базы данных с помощью метода массива (не используя ControlSource
), вы хотите знать, каксинхронизировать элементы списка со своей базой данных после удаления вручную.
Подход A) - Запишите все Listbox1.List
Если вам нужно зеркальное отображение элементов списка после цикла For
- Next
, выможно просто записать эти элементы обратно в заданный диапазон (конечно, вы также должны очистить «лишние строки») через следующий один вкладыш
rng.Resize(Me.ListBox1.ListCount, 2) = Me.ListBox1.List
Вместо дублирования объявления диапазона данныхв CommandButton2_Click
я бы предложил объявить это ОДИН РАЗ в главе объявления модуля кода Userform (и опустить это в Userform_Initialize
):
Таким образом, полныйкод будет следующим:
► Дополнительные примечания по комментарию
Вставьте эти две строки кода в top вашего модуля кода UserForm (и до любых процедур).
Option Explicit
настоятельно рекомендуется в любом коде принудительно объявлять типы переменных (но вы не можете использовать этот оператор в Sub
, как вы это сделали).Объявление Dim rng As Range
ВНЕ других процедур (то есть сверху) позволяет любой процедуре в этом кодовом модуле знать переменную rng
.
Option Explicit ' declaration head of the UserForm module
Dim rng as Range ' ONE database declaration only!
' << OUTSIDE of following procedures
' << Start of regular procedures
Private Sub UserForm_Initialize()
Dim ws As Worksheet
' Dim rng As Range ' << not needed here, see top declaration
Dim MyArray
Set ws = Sheets("Database")
Set rng = ws.Range("K2:L" & ws.Range("K" & ws.Rows.Count).End(xlUp).Row)
With Me.ListBox1
.Clear
.ColumnHeads = False
.ColumnCount = rng.Columns.Count
MyArray = rng
.List = MyArray
.ColumnWidths = "90;90"
.TopIndex = 0
End With
End Sub
Private Sub CommandButton3_Click()
Dim lItem&
For lItem = Me.ListBox1.ListCount - 1 To 0 Step -1
If ListBox1.Selected(lItem) Then
ListBox1.RemoveItem lItem ' remove item from listbox
If Me.ListBox1.MultiSelect = fmMultiSelectSingle Then
Exit For
End If
End If
Next
rng.Offset(Me.ListBox1.ListCount, 0).Resize(rng.Rows.Count, 2) = "" ' clear rows
rng.Resize(Me.ListBox1.ListCount, 2) = Me.ListBox1.List ' write list back
End Sub
Примечание если строки физически не удаляются, результирующие элементы списка в двух целевых столбцах K:L
сдвигаются только вверх (подход B также позволяет удалять целые строки) .
Подход B) - Справочная процедура в основном цикле
Использование того же объявления диапазона данных в заголовке объявления пользовательской формы ►, как показано выше (т. Е. ВНЕ процедур как Subs илиФункции), вы можете использовать справочную процедуру DelData
, позволяющую различать два основных случая:
- [1] Сдвиг удаленных ячеек в вашей базе данных
- [2] Удалитьвесь ряд
процедура события CommandButton2_Click
Private Sub CommandButton2_Click()
' Purpose: delete items both from database and listbox
Dim lItem&
For lItem = Me.ListBox1.ListCount - 1 To 0 Step -1
If ListBox1.Selected(lItem) Then
DelData lItem, True ' [1] True=delete items and shift up
'DelData lItem, False ' [2] False=delete entire row
ListBox1.RemoveItem lItem ' remove item from listbox
If Me.ListBox1.MultiSelect = fmMultiSelectSingle Then
Exit For ' do it once in single select case
End If
End If
Next
End Sub
процедура помощи DelData
Sub DelData(ByVal indx&, Optional ByVal bShiftUp As Boolean = True)
' Purpose: delete indicated row items in database
' Note: data set in OP includes header
If bShiftUp Then ' [1] bShiftUp = True: delete row items and shift up
rng.Offset(indx).Resize(1, rng.Columns.Count).Delete xlShiftUp
Else ' [2] bShiftUp = False: delete entire row of indicated items
rng.Offset(indx).Resize(1, rng.Columns.Count).EntireRow.Delete
End If
End Sub
Примечание к сведению
Рекомендуется пройти квалификационный забегge ссылки, чтобы избежать получения данных из неправильных рабочих книг, поэтому я бы предложил следующее утверждение в вашей UserForm_Initialize
процедуре:
Set ws = ThisWorkbook.Worksheets("Database")
Наслаждайтесь: -)