【问题标题】:Search row for clipboard value, when value found, filter column with cliboard value搜索剪贴板值的行,找到值时,使用剪贴板值过滤列
【发布时间】:2018-07-30 11:53:32
【问题描述】:

有点新手,但在没有帮助的情况下,我已经尽我所能:

我正在尝试创建一个宏来执行以下操作:

1) 在列 (B) 中搜索用户输入的值

2) 找到 (1) 中的值后,复制活动行 U 列中的单元格内容

3) 在 U 列之后的其余行中搜索在 (2) 中复制的值

4) 如果在 (2) 中复制的值在该行中再次找到(仅在 U 列之后的第一次重复),则使用相同的值过滤找到它的单元格列

看起来我有步骤 1 和 2 工作,不确定步骤 3 是否不起作用或失败,因为循环从 A 列开始并在遇到 U 列中的剪贴板值时停止(而不是搜索超出U 列)。第 4 步看起来肯定行不通。

感谢您在解决第 3 步和第 4 步时提供的所有帮助。

使用下面的示例,如果用户在 MyFind/Input 框中输入 9,则将搜索列 B 以在单元格 B2 中找到 9(列 B 中的值将始终是唯一的)。将搜索第 2 行的其余部分(B 列之后)以在单元格 E2 中找到重复的 9。然后以 9 作为标准过滤 E 列。

..A BC DE F G

1|1 2 3 4 5 6 7

2|1 9 3 4 9 9 7

3|1 8 3 4 9 6 7

4|1 3 3 4 5 6 7

我的代码:

Sub LCOUN_Search()
Dim OrgNum As Integer
LastRow = Cells(Rows.Count, "B").End(xlUp).Row


MyFind = InputBox("Please enter 8 digit employee number:") 
    If MyFind = "" Then End

For i = LastRow To 1 Step -1
   If Range("B" & i).Value = MyFind Then
      Range("B" & i).Select
   End If
Next i

Cells(ActiveCell.Row, "U").Select
Selection.Copy

LastCol = Cells(ActiveCell.Row, "V").End(xlToLeft).Column  
*'?Column V so that it searches from after column U?*

For i = LastCol To 1 Step -1
        If Cells(ActiveCell.Row, i) = Selection Then
        ActiveCell.Select
        Selection.Copy

        End If
Next i

Columns(ActiveCell.Column).AutoFilter Field:=1, Criteria:=Selection

End Sub

我也试过这个:

Sub LCOUN_Search()

Dim Found As Long
LastRow = Cells(Rows.Count, "B").End(xlUp).Row


MyFind = InputBox("Please enter 8 digit employee number:")
    If MyFind = "" Then End

For i = LastRow To 1 Step -1
   If Range("B" & i).Value = MyFind Then
      Range("B" & i).Select
   End If
Next i


Cells(ActiveCell.Row, "U").Select
Found = Selection.Copy

FirstCol = Cells(ActiveCell.Row, "V").Column      
LastCol = ActiveSheet.UsedRange.Column + _
                ActiveSheet.UsedRange.Columns.Count - 1


For k = FirstCol To LastCol
    If Cells(ActiveCell.Row, k) = Selection Then Exit For 
Next k

If k <= LastCol Then                             
     With ActiveSheet.UsedRange
          .AutoFilter Field:=k, Criteria1:=Cells(ActiveCell.Row, k).contents
    End With
End If
End Sub

【问题讨论】:

  • 看看使用 .Find on Range(“B1:B” & lastRow)。抱歉,由于移动设备而引起的有趣“”。如果找到,将返回找到的地址,然后取该值并在范围 U 同一行到最后一列 U 行的行上重复 .Find。我不确定您所说的第一次重复是什么意思。您还可以使用 .Find 指定搜索顺序。
  • 您还需要对没有用户输入或用户按下取消以及 .Find 未找到匹配项进行错误处理。也可能值得限制 InputBox 类型参数以限制用户输入预期的数据类型并添加一些基本验证检查用户输入是否有效。
  • 复制的值可能会在行中重复几次(在列 U 之后,例如在列 BA、BB、BC 中),第一次重复我的意思是在列 U 之后的第一次值重复(例如 BA 列)
  • .Find 可用于返回第一个,如果您指定按列排序。 Tbh,如果您将搜索范围缩小到 1 行,我不确定搜索顺序是否重要,但需要调查。值得看一下关于它的 MSDN 文档。这将比您目前尝试的方法高效得多。
  • 仍然无法正常工作,我已经尝试了上面已编辑问题中的第二个代码以及使用 .Find 而不是循环

标签: excel vba search filter rows


【解决方案1】:

如我所见,您搜索的方向错误:您从“V”列开始,然后返回到 A 列。)

如果您想过滤“B”列,那么您应该申请Field:=2

试试这个:

FirstCol = Cells(i, "V").Column      ' employee is found in row i
LastCol = Activesheet.Usedrange.Column + _  
                Activesheet.Usedrange.Columns.Count - 1

For k = FirstCol to LastCol
    If Cells(i, k) = MyFind Then Exit For ' break the loop when found
Next k

If k <= LastCol Then                              ' found
     With Activesheet.Usedrange
          .AutoFilter Field:=2, Criteria1:=MyFind    ' column B
          .AutoFilter Field:=k, Criteria1:=MyFind
     End With
End If

您可以选择使用.Find,然后您可以在该行的其余部分搜索该值,因此命令是:

Dim rFound As Range
Set rFound = Range(Cells(i, FirstCol), CElls(i, LastCol)).Find(What:=MyFind, LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing then       ' found (1st match after U)
     ' here rFound.Column gives you the column of found cell

由于更改要求而编辑的答案:从 C 列到 U 列搜索一行,像这样更改第一列和最后一列,它会满足您的需要。

FirstCol = 3           ' C
LastCol = Cells(i, "U").Column  ' it's not easy to memorize which column is U

【讨论】:

  • 可能完全限定范围
  • @QHarr,我同意,并避免使用 Activesheet 和 Activecell 以及 Selection 等,但这将是下一次培训的主题 :)
  • 感谢您的回复,但我仍然遇到问题
  • 我已经编辑了我的问题以提供更多细节
【解决方案2】:

这可能会被整理,但会向您展示一个带有 Find 函数的示例

Option Explicit

Private Sub LCOUN_Search()

    Dim wb As Workbook
    Dim ws As Worksheet
    Dim lastRow As Long

    Set wb = ThisWorkbook
    Set ws = wb.Worksheets("Sheet1")             'change as appropriate
    lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row

    Dim myFind As String

ResumeLine:
    On Error Resume Next
    myFind = InputBox("Please enter 8 digit employee number or press Cancel to quit.") 'tested with user input 12345686
    On Error GoTo 0

    If myFind = vbNullString Then
        End
    ElseIf Len(myFind) < 8 Or Len(myFind) > 8 Then
        MsgBox "Please enter an 8 digit employee number"
        GoTo ResumeLine
    End If

    Dim foundCell As Range
    Dim initialSearchRange As Range
    Set initialSearchRange = ws.Range("B1:B" & lastRow)

    With initialSearchRange

        Set foundCell = .Find(myFind, LookIn:=xlValues)

        If Not foundCell Is Nothing Then

            Dim foundRow As Long
            foundRow = foundCell.Row
            Set foundCell = Nothing

            Dim lastColumn As Long
            lastColumn = ws.Cells(foundRow, ws.Columns.Count).End(xlToLeft).Column

            myFind = ws.Range("U" & foundRow)

            If myFind = vbNullString Then
                MsgBox "Value not found after column U"
                End
            End If

            Dim newSearchRange As Range
            Set newSearchRange = ws.Range(ws.Cells(foundRow, "V"), ws.Cells(foundRow, lastColumn))

            Set foundCell = newSearchRange.Find(myFind, LookIn:=xlValues)

            Dim filterValue As String

            If Not foundCell Is Nothing Then

                filterValue = CStr(foundCell)    'this depends on what datatype you are expecting to have returned
                ws.Range(ws.Cells(1, "A"), ws.Cells(lastRow, lastColumn)).AutoFilter Field:=foundCell.Column, Criteria1:=filterValue

            End If

        End If

    End With


End Sub

参考资料:

1) How to find a value in an excel column by vba code Cells.Find

2)Find last row, column or last cell

下面的示例过滤器(道歉,但在图像中粘贴 SO 的常用方法似乎不起作用,因此图像中有很多空白):

请注意,上面没有正确的标题。你的例子没有提到这一点。如果在设置范围时要牢记标题,您可能需要使用 row = 1 或 row = 2 而不仅仅是提供的代码中的 row = 1。这里的原则是使用 Find 来完成您描述的步骤。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多