Увидел, что вы работали над этим несколько недель.
Я произвел рефакторинг кода вашей формы и реализовал функции, которые вы искали.
Как и мой другой ответ на ваш вопрос.Другой вопрос, на мой взгляд, легче добавлять и удалять элементы в списке, чем работать с диапазонами Excel.( Как исправить эту ошибку в моем коде, которая не позволяет мне обновлять другие столбцы в пользовательской форме Excel? )
Важные замечания: - Я преобразовал данные на листе вструктурированная таблица Excel (Ctrl + T) - я взял один из ваших предыдущих файлов, поэтому информация, находящаяся внутри таблицы, может быть устаревшей - при тестировании я также изменил некоторые данные - я предлагаю вам скопировать и вставить последниеданные и заменить его внутри таблицы
Здесь вы можете скачать файл на основе ваших данных: https://github.com/rdiazjimenez/excel-vba-userform-basic-listbox-demo/blob/master/MDM_DB_Checking_09122018_RD.xlsm
Я охватил основные операции (создание, чтение, обновление,Delete and Search / Filter) с данными Excel, загруженными в список внутри пользовательской формы.
Это код формы:
Option Explicit
' Code updated
Private Sub btnDelete_Click()
Application.EnableEvents = False
Call mCode.Delete
Application.EnableEvents = True
End Sub
' Code updated
Private Sub btnView_Click()
Application.EnableEvents = False
Call mCode.Read
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbAdd_Click()
Application.EnableEvents = False
Call mCode.Create
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbClearFields_Click()
Application.EnableEvents = False
Call mCode.ClearControls
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbSearch_Change()
Application.EnableEvents = False
Call FilterList(Me.listHeader, Me.cmbSearch.Text)
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbUpdate_Click()
Application.EnableEvents = False
Call mCode.Update
Application.EnableEvents = True
End Sub
' Code updated
Private Sub CommandButton5_Click()
Application.EnableEvents = False
Call mCode.ClearList
Application.EnableEvents = True
End Sub
' Code from this event was removed
Private Sub listHeader_Click()
End Sub
' Code added
Private Sub listHeader_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Application.EnableEvents = False
Call mCode.LoadControls
Application.EnableEvents = True
End Sub
' Code partially updated
Private Sub UserForm_Initialize()
Me.cmbSearch.List = ThisWorkbook.Sheets("PRESTAGE DB").ListObjects("TableData").ListColumns(1).DataBodyRange.Value
Me.cmbEnvironment.AddItem "DEV"
Me.cmbEnvironment.AddItem "UAT"
Me.cmbEnvironment.AddItem "SIT"
Me.cmbEnvironment.AddItem "QA"
Me.cmbEnvironment.AddItem "PROD"
Me.cmbAccessible.AddItem "Y"
Me.cmbAccessible.AddItem "N"
Me.cmbIP.AddItem "1521"
Me.cmbProjects.AddItem "DP - proposed for DEV/SIT"
Me.cmbProjects.AddItem "PH EFUSE SIT"
Me.cmbProjects.AddItem "MyAXA SG DEV/DIT"
End Sub
И это код внутримодуль с именем mCode:
Option Explicit
' Global variables
Const sheetName As String = "PRESTAGE DB"
Const tableName As String = "TableData"
Public Sub ShowUserForm()
oUserForm.Show
End Sub
Public Sub Read()
' Comments: Loads the data from an excel table (listobject) into a listbox located inside a userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myRange As Excel.Range
' Define other variables
Dim columnCount As Integer
Dim selectedItem As Integer
Dim rowCounter As Long
Dim columnCounter As Integer
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Load the data from the Excel table into a range variable
' Note: It's safer to refer to thisworkbook
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
'''''''' Initialize variables ''''''''
myUserForm.listHeader.ColumnWidths = "130 pt;60 pt;82 pt;55 pt;70 pt;195 pt;170 pt;130 pt"
' Set the number of columns to the same of the table in the Excel sheet
columnCount = myListObject.ListColumns.Count
' Get the current selected item
selectedItem = myUserForm.listHeader.ListIndex ' this returns -1 if none is selected
' Clear the listbox contents
Call mCode.ClearList
' Set the number of columns to load into the listbox
myUserForm.listHeader.columnCount = columnCount
' Loop through each row and load it into the listbox
' Note: begins with 2 because the first row are the table headers
For rowCounter = 2 To myListObject.Range.Rows.Count
With myUserForm.listHeader
.AddItem
' Load value of each column in the table row
For columnCounter = 0 To columnCount
.List(rowCounter - 2, columnCounter) = myListObject.Range.Cells(rowCounter, columnCounter + 1).Value
Next columnCounter
End With
Next
' Select previously selected row
If selectedItem < myUserForm.listHeader.ListCount Then
myUserForm.listHeader.ListIndex = selectedItem
End If
' Clean up objects
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub Create()
' Comments: Adds a new row with the data entered by the user and reloads the listbox inside the userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myListRow As Excel.listRow
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Add the information to the Excel table
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
' Validate if all the information is correct
If myUserForm.cmbEnvironment.Text = vbNullString _
Or myUserForm.cmbHost.Text = vbNullString _
Or myUserForm.cmbIP.Text = vbNullString _
Or myUserForm.cmbAccessible.Text = vbNullString _
Or myUserForm.cmbLast.Text = vbNullString Then
MsgBox "Some fields cannot be blank!", vbCritical, "Data Missing"
Exit Sub
End If
' Add a blank row at the end of the Excel table
Set myListRow = myListObject.ListRows.Add
' Set the information into de excel table
With myListRow
.Range(1) = myUserForm.cmbSchema.Text
.Range(2) = myUserForm.cmbEnvironment.Text
.Range(3) = myUserForm.cmbHost.Text
.Range(4) = myUserForm.cmbIP.Text
.Range(5) = myUserForm.cmbAccessible.Text
.Range(6) = myUserForm.cmbLast.Text
.Range(7) = myUserForm.cmbConfirmation.Text
.Range(8) = myUserForm.cmbProjects.Text
End With
MsgBox "Data Added!"
' Reload the data into the listbox
Call mCode.Read
' Select the last item in the listbox
myUserForm.listHeader.ListIndex = myUserForm.listHeader.ListCount - 1
' Clear control's contents
Call ClearControls ' Note that this is a private procedure inside the mCode module
' Clean up objects
Set myListRow = Nothing
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub Update()
' Comments: Updates a row with the data entered by the user and reloads the listbox inside the userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myListRow As Excel.listRow
' Define variables
Dim selectedItem As Integer
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Add the information to the Excel table
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
' Define selected row number
selectedItem = myUserForm.listHeader.ListIndex + 1
' Exit if there are no other rows
If selectedItem = 0 Then
MsgBox "There are no rows left!"
Exit Sub
End If
' Initialize the row at the end of the Excel table
Set myListRow = myListObject.ListRows(selectedItem)
' the following section is exactly as the Create procedure, so you theorically could make just one procedure for Create and Update
' Set the information into de excel table
With myListRow
.Range(2) = myUserForm.cmbEnvironment.Text
.Range(3) = myUserForm.cmbHost.Text
.Range(4) = myUserForm.cmbIP.Text
.Range(5) = myUserForm.cmbAccessible.Text
.Range(6) = myUserForm.cmbLast.Text
.Range(7) = myUserForm.cmbConfirmation.Text
.Range(8) = myUserForm.cmbProjects.Text
End With
' Reload the data into the listbox
Call mCode.Read
' Select the updated item in the listbox
myUserForm.listHeader.ListIndex = selectedItem - 1
MsgBox "Data Updated!"
' Clear control's contents
Call ClearControls ' Note that this is a private procedure inside the mCode module
' Clean up objects
Set myListRow = Nothing
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub Delete()
' Comments: Deletes a row with the data entered by the user and reloads the listbox inside the userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myListRow As Excel.listRow
' Define variables
Dim selectedItem As Integer
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Add the information to the Excel table
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
' Define selected row number
selectedItem = myUserForm.listHeader.ListIndex + 1
' Exit if there are no other rows
If selectedItem = 0 Then
MsgBox "There are no rows left or you didn't select a valid row!"
Exit Sub
End If
If MsgBox("Are you sure you want to delete this row?", vbYesNo + vbQuestion, "Yes") = vbNo Then
Exit Sub
End If
' Initialize the row at the end of the Excel table
Set myListRow = myListObject.ListRows(selectedItem)
' Delete the row
myListRow.Delete
' Reload the data into the listbox
Call mCode.Read
' Select the next item in the listbox
myUserForm.listHeader.ListIndex = WorksheetFunction.Min(selectedItem - 1, myUserForm.listHeader.ListCount) - 1
' Clean up objects
Set myListRow = Nothing
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub ClearList()
' Comments: Clear the listbox
' Define objects variables
Dim myUserForm As oUserForm
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
myUserForm.listHeader.Clear
End Sub
Public Sub LoadControls()
' Comments: Loads the selected row's data into the controls
' Define objects variables
Dim myUserForm As oUserForm
Dim selectedItem As Integer
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Get the row of the selected item in the listbox
selectedItem = myUserForm.listHeader.ListIndex
' Set the control's text to each column of the selected item
myUserForm.cmbSchema.Value = myUserForm.listHeader.List(selectedItem, 0)
myUserForm.cmbEnvironment.Value = myUserForm.listHeader.List(selectedItem, 1)
myUserForm.cmbHost.Value = myUserForm.listHeader.List(selectedItem, 2)
myUserForm.cmbIP.Value = myUserForm.listHeader.List(selectedItem, 3)
myUserForm.cmbAccessible.Value = myUserForm.listHeader.List(selectedItem, 4)
myUserForm.cmbLast.Value = myUserForm.listHeader.List(selectedItem, 5)
myUserForm.cmbConfirmation.Value = myUserForm.listHeader.List(selectedItem, 6)
myUserForm.cmbProjects.Value = myUserForm.listHeader.List(selectedItem, 7)
' Clean up objects
Set myUserForm = Nothing
End Sub
Public Sub ClearControls()
' Comments: Reset controls to empty strings
' Define objects variables
Dim myUserForm As oUserForm
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Clear the controls
myUserForm.cmbSchema.Text = vbNullString
myUserForm.cmbEnvironment.Text = vbNullString
myUserForm.cmbHost.Text = vbNullString
myUserForm.cmbIP.Text = vbNullString
myUserForm.cmbAccessible.Text = vbNullString
myUserForm.cmbLast.Text = vbNullString
myUserForm.cmbConfirmation.Text = vbNullString
myUserForm.cmbProjects.Text = vbNullString
' Clean up objects
Set myUserForm = Nothing
End Sub
Public Sub FilterList(oLb As MSForms.ListBox, strFiltro As String)
Dim columnCounter As Integer
Dim listString As String
Dim rowCounter As Integer
oLb.ListIndex = -1
' Read the whole list
Call mCode.Read
' Remove unmatching items
For rowCounter = oLb.ListCount - 1 To 0 Step -1
listString = vbNullString
' Concat the list columns values in one string
For columnCounter = 0 To oLb.columnCount
listString = listString & oLb.Column(columnCounter, rowCounter)
Next columnCounter
If InStr(1, listString, strFiltro, 1) = 0 Then
' Remove items that don't match
oLb.RemoveItem rowCounter
End If
Next
End Sub