excel - 如何在用户定义的 VBA 函数中从另一个工作表中提取数据

标签 excel vba function

我为一位同事创建了一个函数,其工作方式类似于 xLookUp,但允许用户返回 N从找到的最后一场比赛开始。为了使该功能正常工作,我必须为用户添加一个参数以输入 Worksheet.Name。如果没有这个参数,如果 lookup_sheet 不是输入函数的工作表,我无法让函数从正确的工作表返回值。我了解 Application.Caller 方法可用于确保代码正在查看输入函数的工作表,但我如何让它查看范围参数设置的工作表?
我在名为“Supplies_List”的工作表中输入的函数读取为 =xLookUp_X_From_Last (D2,"Orders",Orders!E:E,Orders!I:I,"",2)代码是:

Public Function xLookUp_X_From_Last(ByVal LookUp_Value As String, ByVal LookUp_Sheet As String, ByVal LookUp_Column As Range, ByVal Return_Column As Range, ifNA As String, Return_From_Last As Long) As String
    
    Dim myCol As Collection
    Dim i, LR, colCount, lColumn, rColumn, lookBack As Long
    Dim lLetter, cLetter, s As String
    Dim lSheet As Worksheet
    Dim wb As Workbook
    
    Set wb = ActiveWorkbook
    Set lSheet = wb.Worksheets(LookUp_Sheet)
    
    lookBack = Return_From_Last - 1
    
    If LookUp_Column.Columns.Count <> 1 Or Return_Column.Columns.Count <> 1 Then
        xLookUp_X_From_Last = "SELECTED RANGE ERROR"
        Exit Function
    End If
    If LookUp_Value = "" Then
        xLookUp_X_From_Last = ifNA
        Exit Function
    End If
    
    Set myCol = New Collection
    
    lColumn = LookUp_Column.Column
    rColumn = Return_Column.Column
    lLetter = Split(Cells(1, lColumn).Address, "$")(1)
    
    LR = lSheet.Range(lLetter & Rows.Count).End(xlUp).Row
    
    For i = 1 To LR
        If lSheet.Cells(i, lColumn).Value = LookUp_Value Then
            myCol.Add lSheet.Cells(i, rColumn).Value
        End If
    Next i

    colCount = myCol.Count
    
    If (colCount - lookBack) < 1 Then
        s = ifNA
    Else
        s = myCol(colCount - (lookBack))
    End If
    
    xLookUp_X_From_Last = s

End Function
即使 LookUp_Column参数使用 Orders!E:E 引用工作表,我必须添加 LookUp_Sheet争论。我很擅长子程序,但不太擅长函数,这让我很困惑。
我从高处和低处寻找vLookUp和xLookUp的VBA代码来剖析和学习,但找不到。如果有人可以将我指向这些功能的源代码,那也很棒。

最佳答案

(一) 如评论中所述,您可以通过 Parent 获取范围的工作表-属性(property)
(二) 在 VBA 中几乎不需要处理列字符。
(c) 小心你的变量声明。如果要在一行中声明多个变量,则需要为每个变量指定类型,否则仅指定类型的最后一个变量,所有其他变量都声明为Variant .参见示例 https://stackoverflow.com/a/71250993/7599798
(d) 子例程和函数之间几乎没有区别,只是函数返回一个值。如果你想将该函数用作UDF,你有一些(明显的)限制,例如不要修改底层的excel,不要使用SelectActivate - 但无论如何你都不应该在 VBA 中使用它。
看看下面的函数。出于速度原因,我将查找和返回范围读入一个数组,特别是对于 UDF 速度很重要,这减少了 Excel 和 VBA 之间的往返次数。我还将最后两个参数设为可选。

Public Function xLookUp_X_From_Last(ByVal LookUp_Value As String, _
          ByVal LookUp_Column As Range, ByVal Return_Column As Range, _
          Optional ifNA As String = "not found", _
          Optional Return_From_Last As Long = 1) As String
    
    Dim myCol As Collection
    Dim i As Long, LR As Long, lookBack As Long
    
    lookBack = Return_From_Last - 1
    If LookUp_Column.Columns.Count <> 1 Or Return_Column.Columns.Count <> 1 Then
        xLookUp_X_From_Last = "SELECTED RANGE ERROR"
        Exit Function
    End If
    
    If LookUp_Value = "" Then
        xLookUp_X_From_Last = ifNA
        Exit Function
    End If
    
    Set myCol = New Collection
    
    Dim lookupValues As Variant, returnValues As Variant
    With LookUp_Column.Parent
        LR = .Cells(.Rows.Count, LookUp_Column.Column).End(xlUp).Row
        lookupValues = LookUp_Column.Cells(1, 1).Resize(LR, 1)
        returnValues = Return_Column.Cells(1, 1).Resize(LR, 1)
    End With

    For i = LBound(lookupValues) To UBound(lookupValues)
        If lookupValues(i, 1) = LookUp_Value Then
            myCol.Add CStr(returnValues(i, 1)), CStr(i)
        End If
    Next i

    If (myCol.Count - lookBack) < 1 Then
        xLookUp_X_From_Last = ifNA
    Else
        xLookUp_X_From_Last = myCol(myCol.Count - lookBack)
    End If
End Function
更新 : 你不需要 Application.Caller。如果您将公式放入工作表中,例如
=xLookUp_X_From_Last (D2,Orders!E:E,Orders!I:I,"",2)
Excel 会将前 3 个参数转换为 Range -variables,并且 Range 总是自动属于一个(并且只有一个)工作表。
第一个参数 (D2) 将指向公​​式所在的同一工作表的单元格 D2,接下来的两个参数将指向工作表 Orders 的 E 列和 I 列.
不要被 Range.Address 的事实所迷惑。不显示工作表名称 - Range 不是地址,它是指向工作表上一个或多个单元格的对象。

关于excel - 如何在用户定义的 VBA 函数中从另一个工作表中提取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71299165/

相关文章:

excel - VBA for Excel : Server Data Not Updating

excel - 如何在 Excel 2016 VBA 中读取已用或可用内存量

vba - Excel 使用列表对列重新排序

Excel 外部数据放入表中

vba - 在 Excel 中将 RTF(富文本格式)代码转换为纯文本

c++ - 引用变量的默认值

vba - Excel 如果选择被剪切然后做事

excel - 替换部分文件名(时间戳)

c++ - dllimport C++ DLL 在 VB.net 中

python - 如何在多处理参数中使用函数指针