【问题标题】:Extracting values from listbox从列表框中提取值
【发布时间】:2017-04-01 00:15:46
【问题描述】:

我在 VBA 中用 2 个列表框创建了一个用户窗体。

我想要做的是从正确的 ListBox 中提取值(并将它们保存在 temp 中)并删除另一个包含这些名称的工作表中的每一行。

编写删除行的代码不是问题。我不知道如何在另一个 VBA 模块中使用这些选定的项目。有什么想法吗?

【问题讨论】:

  • 一开始你是如何填充该列表框的?

标签: vba excel


【解决方案1】:

您可以将它们保存在一个集合中,然后将该集合用作其他过程中的参数。

【讨论】:

    【解决方案2】:

    实际上我希望我的代码看起来更像这样:

    For Each c In Range
        If c.Value = [any of values from list box] Then
            c.EntireRow.Delete
        End If
    Next c
    

    【讨论】:

    • 我的答案将贯穿您在列表框中选择的每个项目。放置您想要删除的任何代码。您希望您的代码看起来像您发布的内容是什么意思?那不引用列表框?
    • 情况是我不知道如何在这个片段中引用ListBox "If c.Value = [any of values from list box]"
    • 您通常会在“范围”中找到多少行?您将需要嵌套一段代码或另一段代码(循环遍历 ListBox 并查找要删除的行,或遍历行并查找是否在列表框中)。一种简单的方法是在列表框中构建所有选择的分隔字符串,然后为每一行查看分隔值是否在您构建的字符串中。我可以告诉你一些代码来处理任何一种方式......
    • 所以请给我看代码。如果我理解正确,我应该有 2 个嵌套循环(循环遍历列表和行或其他方式)
    【解决方案3】:

    更新以反向处理行(因为删除会将行向上移动)。请参阅代码顶部的 cmets。

    Option Explicit
    
    Sub cmdDelete_Click()
        ' This subroutine will allow a user to delete selected rows from an Excel sheet.
        ' In a multi-select listbox on a user form, select the items that you want to delete.
        ' Click the 'Delete' button on the form and the following will occur:
        ' a. Each selected item will be delimited and concatenated into one string.
        '    (The reason for doing that is to avoid spinning thru each listbox item for
        '    every row)
        ' b. Each row in the selected range will have it's value checked within the string.
        ' c. If found. the row will be deleted.
        '
        ' Notes: - Need to loop thru the rows from bottom upwards to top because
        '          as each row is deleted, it will shift remainder upwards.
        '        - You don't really need the delimiters if values can never be confused
    
        Dim sList       As String
        Dim lItem       As Long
        Dim r           As Range
        Dim ws          As Worksheet
        Dim lFirstRow   As Long
        Dim lLastRow    As Long
        Dim lRow        As Long
    
        For lItem = 0 To lstCountries.ListCount - 1
            If lstCountries.Selected(lItem) = True Then
                sList = sList & "<" & Me.lstCountries.column(0, lItem) & ">"     ' Adjust to the column YOU want (relative to zero)
            End If
        Next
        Debug.Print "Full List to Delete: " & sList
    
        Set ws = ThisWorkbook.Sheets("Sheet1")      ' Change to YOUR worksheet name
        ' Find the last used row
        lLastRow = Cells.Find(What:="*", after:=Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
        lFirstRow = 2                               ' Set to YOUR first used row
    
        ' Spin thru all rows in the range of rows
        ' Go in reverse order since the Delete will shift the rows UP
        For lRow = lLastRow To lFirstRow Step -1
            ' See if row value exists in the selections made in the listbox
            If InStr(1, sList, "<" & ws.Cells(lRow, 1) & ">") > 0 Then
                ws.Rows(lRow).Delete            ' Delete row if a match is found
            End If
        Next lRow
    End Sub
    

    【讨论】:

    • 实际上,使用您的代码不会 100% 有效。由于 Excel 将在删除后向上移动行,并且“下一个 C”将移动到下一行,因此您可能会错过要删除的行。一个简单的解决方案是获取范围的行数,然后执行“For i = iMaxRow to iStartRow Step -1”
    • 实际上这段代码对我不起作用。尽管如此,它还是启发了我使用双重上传。在我的回答中,您会发现我的方法非常有效。
    • 我假设您进行了必要的代码更正以指定您自己的环境?在我的测试中,列表框有 10 多个项目,我选择了其中的三个。在 Sheet1 的 A 列中,我输入了有时匹配有时不匹配的测试数据。所有匹配的行都被删除。很高兴您有自己的工作,并期待看到您发布的解决方案...
    【解决方案4】:

    这段代码解决了我的问题

    Private Sub delete_button_Click()
    
    On Error Resume Next
    
    Dim custom_range(1 To 5) As Range
    
    Set custom_range(1) = ActiveWorkbook.Sheets("Countries").Columns(5).Cells
    Set custom_range(2) = ActiveWorkbook.Sheets("Operations").Columns(2).Cells
    Set custom_range(3) = ActiveWorkbook.Sheets("Costs").Columns(2).Cells
    Set custom_range(4) = ActiveWorkbook.Sheets("Revenue").Columns(2).Cells
    Set custom_range(5) = ActiveWorkbook.Sheets("FS").Columns(2).Cells
    
    For i = 0 To ListBox_selected_countries.ListCount - 1
        country_to_delete = ListBox_selected_countries.List(i)
    
        For j = 1 To 5
        Set active_range = custom_range(j)
            For Each c In active_range
                If c.Value = country_to_delete Then
                    c.EntireRow.delete
                End If
            Next c
        Next j
    
    Next i
    
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多