VBA:获取 ComboBox 以显示唯一值以从筛选工作表数据中进行选择 - 然后通过筛选的数据运行特定搜索

VBA: Get a ComboBox to display unique values to choose from filter sheet data - to then run a specific search through filtered data

提问人:RadioEye 提问时间:9/8/2023 最后编辑:RadioEye 更新时间:9/8/2023 访问量:47

问:

您好,感谢您的点击和花费您的时间。我并不为寻求帮助而感到自豪,但由于这个项目的最后期限,我没有时间自己正确理解和解决它。

我有一个宏,它正在运行字符串搜索的代码,以显示来自名为 (Tabelle1) 的工作表中的许多不同的必要数据。但是,我需要能够首先根据列(“L”)中的“货件编号”过滤该工作表数据,以便仅获取每个货件的相应列(共 27 个,从“A”到“AA”)数据,然后我必须运行搜索过程。

理想情况下(如果可能的话),当选择货件(从下拉列表中单击)时,搜索/输入栏(userinput.KeyUp) 会自动选择,以便可以直接在其中输入搜索字符串。

我认为 ComboBox 可以完成这项工作。在其下拉菜单中显示所有唯一的货件编号(理想情况下仅显示一次)。我怀疑它不会通过添加一个 ComboBox 并单独编写它的函数来完成(但我什至无法做到这一点),我需要将其连接到已经存在的搜索代码,该代码在编写时没有包含 ComboBox/filter 函数。

以下是我的数据表的简明示例:

工作表“Tabelle1”

我创建的对象的示例:

输入界面截图

这是整个代码,以及我对 ComboBox 集成的糟糕尝试:

Private Sub ComboBox1_Change()

Dim lastr As Integer
    lastr = Range("L" & Rows.Count).End(xlUp).Row
    ThisWorkbook.Sheets("Tabelle1").Range("A:AA" & lastr).AutoFilter Field:=12, Criteria1:=Range("L1").Value, Operator:=xlFilterValues
    
End Sub

Private Sub Frame1_Click()

End Sub

Private Sub Frame2_Click()

End Sub

Private Sub Label1_Click()

End Sub

Private Sub Label13_Click()

End Sub

Private Sub Label2_Click()

End Sub

Private Sub lastbin_Click()

End Sub

Private Sub Label9_Click()

End Sub

Private Sub limiter_a_Click()

End Sub

Private Sub limiter_b_Click()

End Sub

Private Sub locationfound_Click()

End Sub

Private Sub partfound_Click()

End Sub

Private Sub partnotein_Click()

End Sub

Private Sub partspecialin_Click()

End Sub

Private Sub quickbin2_Click()

End Sub

Private Sub lineqtydetail_Change()

End Sub

Private Sub partqtyinfound_Change()

End Sub

Private Sub TestCountMultiple()

End Sub

Public Sub UserForm_Initialize()

limiter_a = "^#01^"
limiter_b = "^#02^"

End Sub

Private Sub suchbutton_Click()

Dim fullstring, searchstring As String
Dim partfound, locationfound, partqtyinfound As String
Dim partnotein, partspecialin, lastbin As String
Dim columnpart, columnlocation, lineqtydetail As String
Dim quickbin2 As String
Dim ergebnis As String
Dim j As Long
Dim lenght_a, lenght_b As Long
Set ws = ThisWorkbook.Sheets("Tabelle1")

columnpart = "M"
columnlocation = "C"
quickbin2 = "D"
partqtyinfound = "N"
partnotein = "P"
partspecialin = "Q"
lastbin = "B"
lineqtydetail = "O"

lenght_a = Len(limiter_a)
lenght_b = Len(limiter_b)

fullstring = SucheTeilenummer.userinput.Value

openPos = InStr(fullstring, limiter_a)
closePos = InStr(fullstring, limiter_b)

If openPos > "0" And closePos > "0" Then
    searchstring = Mid(fullstring, openPos + lenght_a, closePos - openPos - lenght_b)
Else
    ergebnis = "Keine Limiter gefunden"
End If

If ergebnis = "Keine Limiter gefunden" Then
    SucheTeilenummer.partfound = ergebnis
    SucheTeilenummer.locationfound = ""
    SucheTeilenummer.partqtyinfound = ""
    Suche.Teilenummer.partnotein = ""
    Suche.Teilenummer.partspecialin = ""
    Suche.Teilenummer.lastbin = ""
    Suche.Teilenummer.lineqtydetail = ""
    Suche.Teilenummer.quickbin2 = ""
Else
    letzteZeileTeilenummer = ws.Cells(ws.Rows.Count, columnpart).End(xlUp).Row
    For j = letzteZeileTeilenummer To 2 Step -1
        
        If Range(columnpart & j).Value = searchstring Then
            booFOUND = True
            
            SucheTeilenummer.partfound = ws.Range(columnpart & j).Value
            SucheTeilenummer.locationfound = ws.Range(columnlocation & j).Value
            SucheTeilenummer.partqtyinfound = ws.Range(partqtyinfound & j).Value
            SucheTeilenummer.partnotein = ws.Range(partnotein & j).Value
            SucheTeilenummer.partspecialin = ws.Range(partspecialin & j).Value
            SucheTeilenummer.lastbin = ws.Range(lastbin & j).Value
            SucheTeilenummer.lineqtydetail = ws.Range(lineqtydetail & j).Value & Chr(vbKeySpace) & "PCS" & " - " & ws.Range(columnpart & j).Value & vbCrLf & ws.Range(partnotein & j).Value & vbCrLf & "##################" & vbCrLf & SucheTeilenummer.lineqtydetail
            SucheTeilenummer.quickbin2 = ws.Range(quickbin2 & j).Value
            
            ergebnis = "Wert gefunden"
        Else
            ergebnis = "Wert nicht gefunden"
        End If
        
    Next j
        
        If booFOUND Then
            ergebnis = "Wert gefunden"
        Else
            ergebnis = "Wert nicht gefunden"
        End If

End If
        
        If ergebnis = "Wert nicht gefunden" Then
            SucheTeilenummer.partfound = searchstring
            SucheTeilenummer.locationfound = ""
            SucheTeilenummer.partqtyinfound = ""
            SucheTeilenummer.partnotein = ""
            SucheTeilenummer.partspecialin = ""
            SucheTeilenummer.lastbin = ""
            SucheTeilenummer.lineqtydetail = ""
            SucheTeilenummer.quickbin2 = ""
        End If

SucheTeilenummer.userinput.Value = ""
fullstring = ""
ergebnis = ""
SucheTeilenummer.userinput.SetFocus

End Sub

Private Sub userinput_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)

If KeyCode = vbKeyReturn Then 'wenn die Taste vbKeyReturn ist was für 13 steht dann soll die Suche gestartet werden
    Call suchbutton_Click
    KeyCode = 0 'hier wird der Key für die nächste Suche resettet
End If

End Sub

Private Sub userinput_change()
If InStr(SucheTeilenummer.userinput.Value, limiter_b) Then 'wenn in dem Einfgabefeld irgendwo der limiter_b auftaucht, dann soll die Suche gestartet werden
    Call suchbutton_Click
End If

End Sub

亲切问候 埃罗尔。

你尝试了什么,你期待什么? 试图在谷歌上搜索类似的问题并将其应用于我的代码。无法让它运行。对不起,谢谢。

Excel VBA 对象 筛选器 组合框

评论

0赞 Notus_Panda 9/8/2023
只获取我必须运行搜索过程的每批货物的相应列(总共 27 列,从”A“到”AA“)数据是什么意思,是给定的值还是需要隐藏列在您的工作表上?另外,为什么在你的第二个 If 子句中?SucheTeilenummerSuche.Teilenummer
0赞 RadioEye 9/8/2023
你好。我无法对第二个 if 子句给出明确的解释,因为我没有编写代码。但是它的作用是根据输入到输入栏中的内容搜索整个工作表(请参阅第二个附加图像,黄色)。所以是的,我想我需要 ComboBox 过滤器做的是隐藏与其他货件相关的所有信息/值,除了从组合框的下拉菜单中选择的信息/值。我希望这更有意义。
0赞 Notus_Panda 9/8/2023
(我不够流利,无法完全翻译这个)是独一无二的吗?或者这就是为什么搜索是从下到上(letzte 的意思是最后的 afaik,因此是问题)?letzteZeileTeilenummer
0赞 RadioEye 9/8/2023
是的,这代表最后一行(teilenummer = 项目编号)。搜索确实是从下到上进行的。我不知道为什么。
0赞 Notus_Panda 9/8/2023
这并不能告诉我它们是否是唯一的,如果所有 M 值都是唯一的,则无需过滤即可找到您要查找的值。如果它们在每个运输编号上都是唯一的,那么过滤器就会派上用场。

答:

0赞 RadioEye 9/8/2023 #1

我现在能够执行以下操作,并且至少能够让 ComboBox 搜索我要过滤的列中的值。但是,一旦我开始输入第一个数字,它只会向我显示框中的值:

下拉列表有效,但是...

但是我正在尝试在下拉字段中填充每个值一次(尽管由于数据的性质,列本身将其列在多个单元格中)。一旦我选择了货件编号,我就需要数据来过滤工作表上的所有信息,以及“L”列中该特定货号的所有其他相应值(隐藏不属于该货件的所有内容,而是属于另一个货件)。

Private Sub ComboBox1_Change()

    FilterCbo1 (UCase(ComboBox1.Value))
    ComboBox1.DropDown
    
End Sub

Public Sub FilterCbo1(strFilter As String)

Dim lastrow As Long
    lastrow = ThisWorkbook.Sheets("Tabelle1").Range("L" & Rows.Count).End(xlUp).Row
        For Each strchoice In Range(Cells(2, 12), Cells(lastrow, 12))
            If InStr(1, strchoice, strFilter) <> 0 Then
                SucheTeilenummer.ComboBox1.AddItem strchoice
            End If
        Next
End Sub
0赞 Notus_Panda 9/8/2023 #2

以下是使用L列的唯一值填充组合框的方法:

Private Sub ComboBox1_Change()
    Dim lRow As Long
    ShowAll
    lRow = Range("L" & Rows.Count).End(xlUp).Row
    ThisWorkbook.Sheets("Tabelle1").Range("A1:AA" & lRow).AutoFilter Field:=12, Criteria1:=ComboBox1.Value, Operator:=xlFilterValues
    Me.userinput.SetFocus 'sets focus to your textbox
    Dim arr, rng As Range
    Set rng = ThisWorkbook.Sheets("Tabelle1").Range("A1:AA" & lRow).Offset(1)
    arr = rng.SpecialCells(xlCellTypeVisible).Value 'could use something like this instead of looping through your cells
End Sub

Private Sub UserForm_Initialize()
    Dim lRow As Long, i As Long, arr
    ShowAll
    lRow = Range("L" & Rows.Count).End(xlUp).Row
    arr = Range("L2:L" & lRow).Value 'all L-values
    With CreateObject("Scripting.Dictionary")
        For i = 1 To UBound(arr, 1)
            If Not .Exists(arr(i, 1)) Then
                .Add arr(i, 1), Nothing 'keeps only the unique shipping numbers
            End If
        Next i
        ComboBox1.List = .Keys 'gives the combobox those unique numbers all at once
    End With
    limiter_a = "^#01^"
    limiter_b = "^#02^"
End Sub

Private Sub ShowAll()
    On Error Resume Next
    With ThisWorkbook.Worksheets("Tabelle1")
        If .AutoFilterMode Then .ShowAllData
    End With
    On Error GoTo 0
End Sub

以下是修剪不必要的代码时其他代码的样子:

Private Sub suchbutton_Click()

    Dim fullstring As String, searchstring As String
    Dim partfound As String, locationfound As String, partqtyinfound As String
    Dim partnotein As String, partspecialin As String, lastbin As String
    Dim columnpart As String, columnlocation As String, lineqtydetail As String
    Dim quickbin2 As String
    Dim ergebnis As String
    Dim j As Long
    Dim lenght_a As Long, lenght_b As Long
    'Common mistake to not declare your variables for each, i.e. fullString in your code was a Variant, not a string variable
    Set ws = ThisWorkbook.Sheets("Tabelle1")
    
    columnpart = "M"
    columnlocation = "C"
    quickbin2 = "D"
    partqtyinfound = "N"
    partnotein = "P"
    partspecialin = "Q"
    lastbin = "B"
    lineqtydetail = "O"
    
    lenght_a = Len(limiter_a)
    lenght_b = Len(limiter_b)
    
    fullstring = SucheTeilenummer.userinput.Value
    
    openPos = InStr(fullstring, limiter_a)
    closePos = InStr(fullstring, limiter_b)
    
    If openPos > "0" And closePos > "0" Then
        searchstring = Mid(fullstring, openPos + lenght_a, closePos - openPos - lenght_b)
        letzteZeileTeilenummer = ws.Cells(ws.Rows.Count, columnpart).End(xlUp).Row
        For j = letzteZeileTeilenummer To 2 Step -1
            If Range(columnpart & j).Value = searchstring Then
                booFound = True
                
                SucheTeilenummer.partfound = ws.Range(columnpart & j).Value
                SucheTeilenummer.locationfound = ws.Range(columnlocation & j).Value
                SucheTeilenummer.partqtyinfound = ws.Range(partqtyinfound & j).Value
                SucheTeilenummer.partnotein = ws.Range(partnotein & j).Value
                SucheTeilenummer.partspecialin = ws.Range(partspecialin & j).Value
                SucheTeilenummer.lastbin = ws.Range(lastbin & j).Value
                SucheTeilenummer.lineqtydetail = ws.Range(lineqtydetail & j).Value & Chr(vbKeySpace) & "PCS" & " - " & ws.Range(columnpart & j).Value & vbCrLf & ws.Range(partnotein & j).Value & vbCrLf & "##################" & vbCrLf & SucheTeilenummer.lineqtydetail
                SucheTeilenummer.quickbin2 = ws.Range(quickbin2 & j).Value
                Exit For 'no need to keep searching
            End If
        Next j
    Else
        searchstring = "Keine Limiter gefunden"
    End If
        
    If Not booFound Then
        SucheTeilenummer.partfound = searchstring
        emptySucheForm
    End If

    SucheTeilenummer.userinput.Value = ""
    fullstring = ""
    ergebnis = ""
    SucheTeilenummer.userinput.SetFocus

End Sub

Private Sub emptySucheForm()
    SucheTeilenummer.locationfound = ""
    SucheTeilenummer.partqtyinfound = ""
    SucheTeilenummer.partnotein = ""
    SucheTeilenummer.partspecialin = ""
    SucheTeilenummer.lastbin = ""
    SucheTeilenummer.lineqtydetail = ""
    SucheTeilenummer.quickbin2 = ""
End Sub

Private Sub userinput_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)

If KeyCode = vbKeyReturn Then 'wenn die Taste vbKeyReturn ist was für 13 steht dann soll die Suche gestartet werden
    Call suchbutton_Click
    KeyCode = 0 'hier wird der Key für die nächste Suche resettet
End If

End Sub

Private Sub userinput_change()
If InStr(SucheTeilenummer.userinput.Value, limiter_b) Then 'wenn in dem Einfgabefeld irgendwo der limiter_b auftaucht, dann soll die Suche gestartet werden
    Call suchbutton_Click
End If

End Sub

如果我更多地了解 M 列项目编号的唯一性,这可以得到改进。我保留了你的大部分代码,因为如果它们不是唯一的,重点是得到最后一个,我不想打破这个逻辑(现在)。如果是,则会想到使用 的 来按顺序获取剩余值。Application.Match

评论

0赞 RadioEye 9/8/2023
感谢您的帮助和努力。我一回到办公室就会尝试一下,但我现在仍然想回答谢谢你,因为我真的很感激。