【问题标题】:Index and match with concatenated values索引并与连接值匹配
【发布时间】:2019-08-15 11:30:14
【问题描述】:

我正在尝试索引和匹配 2 个单独列中的值。如果它是一个 Excel 公式,它看起来像......

 =INDEX('Critical Times'!D:D,MATCH(CONCATENATE(B7,C7),'Critical Times'!G:G,0))

不过,我正在努力在 VBA 中执行此操作。我已经尝试了下面的代码,但它不起作用。这里发生的情况是,它沿着一列中的每一行写入一个开始日期和结束日期的值,直到它到达一个空白行。

我尝试了一个稍微不同的版本,它只将单元格 C7 与另一列匹配,并且工作正常。只有当我想加入 B7 和 C7 中的值时,它才会停止工作。代码有点乱,请见谅,还在学习中!

Dim r As Range


Worksheets("Overview").Activate


Set r = Range("B7") & Range("c7")

Do While r.Value <> ""


Dim datestr As Long
Dim dateend As Long
datestr = WorksheetFunction.Index(Worksheets("Critical Times").Range("D:D"),     WorksheetFunction.Match(r.Value, Worksheets("Critical Times").Range("G:G"), 0), 0)
dateend = WorksheetFunction.Index(Worksheets("Critical Times").Range("E:E"),     WorksheetFunction.Match(r.Value, Worksheets("Critical Times").Range("G:G"), 0), 0)


Dim MatchFormula As Long
Dim ColumnMatch As Long
Dim MatchFormula2 As Long
Dim ColumnMatch2 As Long



If datestr <> 0 Then
MatchFormula = WorksheetFunction.Match(r.Value, Range("C:C"), 0)
ColumnMatch = WorksheetFunction.Match(datestr, Range("4:4"), 0)
Range(Col_Letter(ColumnMatch) & MatchFormula).Value = "A"

MatchFormula2 = WorksheetFunction.Match(r.Value, Range("C:C"), 0)
ColumnMatch2 = WorksheetFunction.Match(dateend, Range("4:4"), 0)
Range(Col_Letter(ColumnMatch2) & MatchFormula2).Value = "A"
End If

    Set r = r.Offset(1)
  Loop

【问题讨论】:

  • 一种选择是使用.FindG 列中设置一个单元格,然后使用.Offset 来获取D 列值。此外,为了将来参考,在 MATCH 中连接多个值并不是最好的方法。想象一下像 1111 连接的值....
  • 我同意连接点,我通常不会在 Excel 的论坛中这样做,但会索引并匹配多个标准。老实说,我觉得 vba 超出了我的能力范围,所以认为将这些价值观结合在一起更容易。
  • 因此,如果连接在工作表公式中是不好的做法,那么在 VBA 中也是不好的做法。那么您是否宁愿遍历一个范围并检查多个值?你会喜欢一个简化的例子吗?
  • 拜托,我将不胜感激
  • =INDEX('Critical Times'!D:D,MATCH(1,INDEX(('Critical Times'!A:A=B7)*('Critical Times'!B:B=C7 ),0,1),0)) 如果它是一个正常的 Excel 公式,我会这样做。

标签: excel vba


【解决方案1】:

让我们想象一下这个示例数据:

| Tests | Vals | Return |
|-------|------|--------|
| Test1 | Val1 | Ret1 |
| Test1 | Val2 | Ret2 |
| Test1 | Val3 | Ret3 |
| Test1 | Val4 | Ret4 |
| Test1 | Val5 | Ret5 |
| Test2 | Val1 | Ret6 |
| Test2 | Val2 | Ret7 |
| Test2 | Val3 | Ret8 |
| Test2 | Val4 | Ret9 |
| Test2 | Val5 | Ret10 |
| Test3 | Val1 | Ret11 |
| Test3 | Val2 | Ret12 |
| Test3 | Val3 | Ret13 |
| Test3 | Val4 | Ret14 |
| Test3 | Val5 | Ret15 |

要根据多个条件(在本例中为 col A 和 col B)返回某个值,我们可以在一个范围内使用一些迭代,如下所示:

Sub Test()

Dim rng As Range, cl As Range
Dim var1 As String, var2 As String, fa As String

var1 = "Test2"
var2 = "Val4"

With Worksheets("Sheet1")
    Set rng = .Range("A2:A" & .Cells(.Rows.Count, "A").End(xlUp).Row)
    For Each cl In rng
        If cl.Value = var1 And cl.Offset(0, 1).Offset = var2 Then
            Debug.Print cl.Offset(0, 2).Value
            Exit For
        End If
    Next cl
End With

End Sub

如果您的数据范围很大,查看.FindNext 以防止迭代和处理时间过长可能会有所帮助。


如果您确定这些值存在,您还可以使用.Evaluate 函数来模拟工作表函数并返回它的结果。在这种情况下,.Evaluate 会识别出您打算使用数组公式,因此不需要第二个INDEX。示例:

Sub Test2()

Dim rng As Range, cl As Range
Dim var1 As String, var2 As String, fa As String

var1 = "Test2"
var2 = "Val4"

With Worksheets("Sheet1")
    Debug.Print .Evaluate("=INDEX(C:C,MATCH(1,(A:A=""" & var1 & """)*(B:B=""" & var2 & """),0))")
End With

End Sub

为了缩短处理时间,您也可以在评估公式中定义范围并实施这些范围。

【讨论】:

  • 感谢您抽出宝贵时间。在原始代码中,datestr 和 dateend = 我尝试使用的索引和匹配公式。在第二个示例中,我将如何定义它们中的每一个?对不起,如果这是一个愚蠢的问题,我仍然试图通过这个来选择我的方式
  • @KeithWilliams,如果它是长变量,您可以将它们调暗,此外,您可以删除三引号之一,因为我们不再需要文本值而是数值。它看起来像:Dim var1 As Long, var2 As Long.Evaluate("=INDEX(C:C,MATCH(1,(A:A="" &amp; var1 &amp; "")*(B:B="" &amp; var2 &amp; ""),0))")
  • 对不起,这更多是因为我缺乏了解!
  • @KeithWilliams,也许是我不理解您的要求。你想引用两个特定的单元格而不是变量吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多