【问题标题】:Returning value adjacent to two search criteria返回与两个搜索条件相邻的值
【发布时间】:2016-08-14 09:51:16
【问题描述】:

我需要从这样的表中查找与两个搜索条件相邻的值:

我写的代码是:

Dim mAin As Worksheet
Dim findc As Range
Dim findsc As Range
Dim code As Long
Dim scode As Integer
Dim i As Integer
Dim ttlrw As Long

i = 1
Set mAin = ActiveSheet
ttlrw = mAin.Columns(1).SpecialCells(xlCellTypeConstants).Count

Do
    code = mAin.Cells(i, 5).Value
    scode = mAin.Cells(i, 6).Value

    Set findc = mAin.Columns(1).Find(code)
    Set findsc = mAin.Columns(2).Find(scode)
    Do
        Set findc = mAin.Columns(1).FindNext(findc)
        Set findsc = mAin.Columns(2).FindNext(findsc)
    Loop Until findc.Row = findsc.Row

    mAin.Cells(i, 7).Value = findsc.Offset(0, 1).Value
    i = i + 1
Loop Until i = ttlrw + 1

找到的值应该与相似的表格相邻输出,但更混乱。

此外,宏在第 5 行之后进入无限循环。

我设法使用 INDEX、MATCH 和 &s 来解决这个问题,并将其转换为数组公式;但我也想进一步提高我对 VBA 的理解。

【问题讨论】:

  • 如果您提供示例输入数据和预期输出,回答您的问题会容易得多。此外,您的代码不会检查是否找到了搜索值。
  • 你应该在 Youtube 上观看这个视频系列:[Excel VBA 介绍](聪明的猫头鹰教程)。下载Smart Indenter;它会为你格式化你的代码。适当的缩进可以很容易地找到未闭合的代码块。
  • 谢谢,我一定会去看看。并且处理我的缩进,当我再次查看它时,我什至无法判断它是否未关闭。

标签: vba excel


【解决方案1】:

有很多方法可以做你想做的事。

Sub Example1_ForLoop()

    Dim lastRow As Long, x As Long
    Dim Criteria1 As Variant, Criteria2 As Variant

    Criteria1 = 2134
    Criteria2 = "003"

    lastRow = Range("A" & Rows.Count).End(xlUp).Row

    For x = 1 To lastRow
        If Cells(x, 1) = Criteria1 And Cells(x, 2) = Criteria2 Then

            Cells(x, 6) = Cells(x, 3)

        End If

    Next

End Sub


Sub Example2_ForEachLoop()

    Dim c As Range, SearchRange As Range
    Dim Criteria1 As Variant, Criteria2 As Variant

    Criteria1 = 2134
    Criteria2 = "003"

    Set SearchRange = Range("A1", Range("A" & Rows.Count).End(xlUp))

    For Each c In SearchRange
        If c = Criteria1 And c.Offset(0, 1) = Criteria2 Then

            c.Offset(0, 5) = c.Offset(0, 3)

        End If

    Next

End Sub

'Here is the proper way to use Find and FindNext.

Sub Example3_DoLoop_Find_FindNext()

    Dim c As Range, SearchRange As Range
    Dim firstAddress As String
    Dim Criteria1 As Variant, Criteria2 As Variant

    Criteria1 = 2134
    Criteria2 = "003"

    Set SearchRange = Range("A1", Range("A" & Rows.Count).End(xlUp))

    Set c = SearchRange.Find(Criteria1, LookIn:=xlValues)

    If Not c Is Nothing Then
        firstAddress = c.Address
        Do

            If c = Criteria1 And c.Offset(0, 1) = Criteria2 Then

                c.Offset(0, 5) = c.Offset(0, 3)

            End If

            Set c = SearchRange.FindNext(c)
        Loop While Not c Is Nothing And c.Address <> firstAddress
    End If

End Sub

【讨论】:

  • 说实话,我从来没有使用过“For”参数。刚刚开始,我一直在使用 IF 和循环。但是使用起来似乎很简单!谢谢。
  • @Jo_Ash 我更新了我的答案以包括ForFor EachDo 循环的示例。当您知道循环的确切开始和结束时,使用For 循环。当您不确定循环何时结束时,DoWhile 会更好。
  • 谢谢,我在理解一些问题时遇到了一些困难,但可能还是新的,所以需要更多时间。顺便说一句,我如何让它不断找到所有标准(而不是单个值)。 For Arguments 可以吗?而不是让 msgbox 显示输出,我可以更改代码以使其输出标准 1 和 2 右侧的值吗?
  • 标准是什么?你想输出什么值?您在比较两个列表吗?
  • 在我的图像中,A 列中的值是代表一个组的代码,每个组都有几个标识号(在 B 列中)。对于每个类别 ID 组合,在 C 列中为其分配了一个值。 D 列和 E 列是一组生成的组合,我用来测试我的代码是否有效,F 列应该是它的输出位置。抱歉到目前为止所有的混乱,并感谢您的帮助。当我不确定如何解释我的情况时,真的非常感谢您的努力和耐心。
【解决方案2】:

试试这个

Option Explicit

Sub mAin()
    Dim mAin As Worksheet
    Dim cell As Range

    With Worksheets("mAin") '<--| '<-- change "mAin" with your actual sheet name
        .Rows(1).Insert '<--| insert a dummy header row, it'll be eventually removed
        .Cells(1, 1).Resize(, 2).Value = Array("head1", "head2") '<--| write dummy headers
        With .Range("A1:B" & .Cells(.Rows.Count, 1).End(xlUp).Row) '<--| reference its range in columns A:B from row 1 to column "A" last non empty cell row
            For Each cell In .Parent.Columns(5).SpecialCells(xlCellTypeConstants) '<-- loop through column "E" non empty cells
                .AutoFilter field:=1, Criteria1:=cell.Value 'operator:=xlAnd, '<--| filter referenced range on its 1st column with current cell value
                .AutoFilter field:=2, Criteria1:=cell.Offset(, 1).Value 'operator:=xlAnd, '<--| filter referenced range again on its 2nd column with current cell adjacent column value
                If Application.WorksheetFunction.Subtotal(103, .Cells.Resize(, 1)) > 1 Then '<--| if any cell other than header ones has been filtered...
                    cell.Offset(, 2) = .Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, 3) '<--| copy current cell offseted 2 columns value to column "G"
                End If
                .Parent.AutoFilterMode = False '<--| show all rows back
            Next cell
        End With
        .Rows(1).Delete '<--| remove dummy header row
    End With
End Sub

【讨论】:

  • 有很多东西是我以前没见过或不懂的。在我尝试理解它之后会尝试它。非常感谢!
  • 不客气。我评论了代码,所以你有一个“指南”来理解它。告诉我。
  • @Jo_Ash,你通过了吗?
  • 嘿@user3598756,抱歉,这周工作简直就是地狱。每当我有空时,我的 vba 学习应该是娱乐性的,将工作目标作为作业。还没有解决这个问题,但我确实有一种解决方法(从匹配和索引中得到这个想法)。没有确切的代码 atm 但基本上我做了一个 if 循环并将 2 个字符串组合在一起;一直到最后一列 + 1(dk 为什么我需要它)。
  • 抱歉 @user3598756 让您编写代码和所有内容。一旦工作量减轻,我将重新审视它并正确地完成它!已经了解当我的设置数据达到数千时 if 循环是多么低效(那和工作的计算机真的很慢)。现在我应该解决另一个问题,我应该优先考虑它,因为我不能用最好的公式来解决它 - 需要从活动单元格开始,复制范围直到最后一个非空白并粘贴它在最后一个填充的单元格下方(即复制数据)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-24
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 2013-11-18
相关资源
最近更新 更多