【问题标题】:VBA vlookup reference in different sheet不同工作表中的 VBA vlookup 参考
【发布时间】:2013-12-23 08:33:31
【问题描述】:

在 Excel 2007 中,我正在遍历工作表 2 中第 4 列的值。仍然在工作表 2 中,我想将我的 vlookup 公式的结果输出到第 5 列。vlookup 公式需要参考工作表 1,其中参考列是。为此,我有以下公式

Range("E2") = Application.WorksheetFunction.VLookup(Range("D2"), _
          Worksheets("Sheet1").Range("A1:C65536"), 1, False)

问题,它返回错误代码 1004。我读到这是因为我需要在运行以下公式之前选择工作表 1:

ThisWorkbook.Worksheets("Sheet1").Select

但是搜索到的值 Range ("D2") 不属于 Sheet 1,并且在将 Sheet 1 带入视图后仍然返回代码 1004。

在这种情况下,引用不同工作表的正确方法是什么?

【问题讨论】:

  • 你为什么要使用VBA来返回一个可以直接在Worksheets("Sheet2").range("E2")中输入的公式的结果?
  • 我同意 Mark 的逻辑,所以我发布了一个替代您的代码的替代方案,它的作用完全相同。但是,如果您想坚持自己的逻辑,请尝试将 .Value 添加到您的数组参数中。喜欢这个Application.WorksheetFunction.Vlookup(Range("D2"),Worksheets("Sheet1").Range("A1:C65536").Value, 1, False)。另外,您是否返回Column A 中的值?您在Vlookup 第三个参数中使用1,即col_index_num
  • @Mark:这段代码包含在一个循环中,迭代几列,将结果输出到字符串变量中,我将在每行处理结束时将它们连接到最后一列。我只是简化了我的代码以避免在此处粘贴我的整个宏。
  • @L42:正如我向 Mark 提到的,我将结果输出到变量中; Range("E2") 实际上是 MyStringVar1,因为我有几个这样的变量/公式要落实到位。我尝试过使用 .value 但它使循环变慢并且仍然返回 1004。
  • 是的,我添加了一些符合您逻辑的内容。此外,正如我在代码中评论的那样,如果找不到您的搜索,Vlookup 将失败并返回Runtime Error 1004。所以你必须使用代码中显示的Error Handlers 来处理它。是的,无需添加.Value

标签: vba excel


【解决方案1】:

试试这个:

Dim ws as Worksheet

Set ws = Thisworkbook.Sheets("Sheet2")

With ws
    .Range("E2").Formula = "=VLOOKUP(D2,Sheet1!$A:$C,1,0)"
End With

End Sub

这只是您想要的简化版本。
如果您只在Range("E2") 中输出答案,则无需使用Application

如果您想坚持自己的逻辑,请声明变量。
例如,请参见下文。

Sub Test()

Dim rng As Range
Dim ws1, ws2 As Worksheet
Dim MyStringVar1 As String

Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
Set rng = ws2.Range("D2")

With ws2
    On Error Resume Next 'add this because if value is not found, vlookup fails, you get 1004
    MyStringVar1 = Application.WorksheetFunction.VLookup(rng, ws1.Range("A1:C65536").Value, 1, False)
    On Error GoTo 0
    If MyStringVar1 = "" Then MsgBox "Item not found" Else MsgBox MyStringVar1
End With

End Sub

希望这能让你开始。

【讨论】:

  • 我刚刚意识到我在矩阵中搜索的参考值必须在第一列,至少在创建简单公式时是这样。因此,我根据我的初始要求连接了我需要的所有值,并且效果很好。但我会测试您的 Test 宏,因为我有兴趣在后台运行此逻辑而不是使用单元格公式。
  • +1 用于定义 rng 属于哪个工作表。如果您声明变量并正确定义它们,则不必选择工作表。
【解决方案2】:

回答您的问题:引用不同工作表的正确方法是适当限定您使用的每个 Range。 请阅读this explanation 及其结论,我想这将提供基本信息。

您遇到的错误可能是由于在搜索范围 Sheet1!A1:A65536 中未找到所需值 Sheet2!D2。这可能源于两种情况:

  1. 该值实际上不存在(由 chris nielsen 指出)。

  2. 您正在搜索错误的范围。如果ActiveSheetSheet1,那么在没有限定条件的情况下使用Range("D2") 将搜索Sheet1!D2,即使搜索的值存在于正确的范围内,它也会抛出相同的错误。 对此(以及以下项目)的代码说明如下:

    Sub srch()
        Dim ws1 As Worksheet, ws2 As Worksheet
        Dim srchres As Variant
    
        Set ws1 = Worksheets("Sheet1")
        Set ws2 = Worksheets("Sheet2")
    
        On Error Resume Next
        srchres = Application.WorksheetFunction.VLookup(ws2.Range("D2"), ws1.Range("A1:C65536"), 1, False)
        On Error GoTo 0
        If (IsEmpty(srchres)) Then
          ws2.Range("E2").Formula = CVErr(xlErrNA) ' Use whatever you want
        Else
          ws2.Range("E2").Value = srchres
        End If
    End Sub
    

我将指出一些额外的值得注意的点:

  1. 按照 chris nielsen 的做法捕获错误是一种很好的做法,如果使用 Application.WorksheetFunction.VLookup,则可能是强制性的(尽管它不适合处理上述情况 2)。

  2. 这个捕获实际上是由函数VLOOKUP在单元格中输入的(如果没有找到寻找的值,错误的结果在结果中显示为#N/A) .这就是为什么 L42 的第一个解决方案不需要任何额外的错误处理(由=VLOOKUP... 负责)。

  3. 使用=VLOOKUP...Application.WorksheetFunction.VLookup有根本的不同:​​第一个留下一个公式,如果引用的单元格发生变化,其结果可能会改变;第二个写入一个固定值。

  4. L42 的两种解决方案都适合限定范围。

  5. 您正在搜索范围的第一列,并返回同一列中的值。其他功能可用于此(尽管您的功能很好)。

【讨论】:

    【解决方案3】:

    只要Sheet2!D2 中的值存在于Sheet1!A:A 中,您的代码就可以正常工作。如果没有,则会引发错误 1004。

    要处理这种情况,请尝试

    Sub Demo()
        Dim MyStringVar1 As Variant
        On Error Resume Next
        MyStringVar1 = Application.WorksheetFunction.VLookup(Range("D2"), _
          Worksheets("Sheet1").Range("A:C"), 1, False)
        On Error GoTo 0
        If IsEmpty(MyStringVar1) Then
            MsgBox "Value not found!"
        End If
    
        Range("E2") = MyStringVar1
    
    End Sub
    

    【讨论】:

    • +1 用于使用IsEmpty 检查MyStringVar1。我认为它更安全。 :)
    【解决方案4】:

    自从我发布这个问题以来,已经有很多函数、宏和对象了。我处理它的方式(在此处的答案之一中提到)是通过创建一个字符串函数来处理由 vlookup 函数生成的错误,并且不返回任何内容或返回 vlookup 结果(如果有)。

    Function fsVlookup(ByVal pSearch As Range, ByVal pMatrix As Range, ByVal pMatColNum As Integer) As String
        Dim s As String
        On Error Resume Next
        s = Application.WorksheetFunction.VLookup(pSearch, pMatrix, pMatColNum, False)
        If IsError(s) Then
            fsVlookup = ""
        Else
            fsVlookup = s
        End If
    End Function
    

    人们可能会争论错误处理的位置或缩短此代码,但它在所有情况下都适用于我,正如他们所说,“如果它没有损坏,请不要尝试修复它”。

    【讨论】:

    • 如果发生错误,这总是返回上一次成功查找的值。至少对我来说..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    相关资源
    最近更新 更多