我是vba的新手,但是我正在尝试创建一个函数,该函数可动态查找整个工作表的范围,以供其他宏用于数据清理。
以下是函数:
Public Function FindRange(Rw As Long, CL As Long)
Dim Rw As Long
Dim CL As Long
CL = ActiveSheet.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Rw = ActiveSheet.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End Function
这是我要称呼它的地方:
Sub Range_Find_Method()
Call FindRange(Rw, CL)
ActiveSheet.Range("A1", Cells(Rw, CL)).Select
End Sub
我一直收到不匹配的ByRef参数类型。
答案 0 :(得分:2)
您不应调用函数,而应将其返回值分配给调用子/函数中的变量。您还应该给函数一个返回类型,例如
Public Function GetUsedRange() As Range
Set GetUsedRange = ActiveSheet.UsedRange
End Function
也如上面的代码所示,您不能使用
ActiveSheet.UsedRange
要找到使用的单元格范围?! https://msdn.microsoft.com/en-us/vba/excel-vba/articles/worksheet-usedrange-property-excel
我编写的函数本质上是多余的,因为您可以使用
Dim MyUsedRange As Range
Set MyUsedRange = ActiveSheet.UsedRange
在这种情况下,除非将结果分配给变量,否则您甚至都不需要去做,除非在代码运行过程中使用的范围发生了变化。
答案 1 :(得分:2)
考虑:
Public Function FindRange()
Dim Rw As Long
Dim CL As Long
CL = ActiveSheet.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Rw = ActiveSheet.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Dim arr(1 To 2) As Long
arr(1) = CL
arr(2) = Rw
FindRange = arr
End Function
Sub MAIN()
Dim coor() As Long
coor = FindRange()
ActiveSheet.Range("A1", Cells(coor(2), coor(1))).Select
End Sub
答案 2 :(得分:1)
Public Function FindRange(Rw As Long, CL As Long) Dim Rw As Long Dim CL As Long
这甚至不应该编译,Rw
和CL
局部变量是重复的声明,在这里:
同时删除它们,您的代码应能按预期工作,即分配ByRef
参数 Rw
和CL
...,它们都可以使用更具描述性的名称和显式的ByRef
修饰符(如果未指定,则为隐式)。
另外,正如其他人所暗示的,函数应该返回值。您可以通过在函数签名中指定返回类型来做到这一点...
Public Function FindRange(ByVal inRow As Long, ByVal inColumn As Long) As Range
...然后在该函数的主体中分配该函数的标识符:
Set FindRange = result ' where result is a Range object reference
使用ByRef
参数作为返回值是可行的,但是当过程为Function
时,则需要使用相当混乱的API。将其设为Sub
过程将消除关于返回值可能是什么的模糊性,再次命名可以使意图更清晰:
Public Sub FindRange(ByRef outRow As Long, ByRef outColumn As Long)
您正在进行的Range.Find
方法调用是假设将找到一个单元格-如果对一个空工作表调用该单元格,则会因运行时错误91而崩溃。 从不假设Range.Find
将返回有效的对象引用-将其结果存储在Range
对象引用中,并验证其是否为Nothing
:
Dim result As Range
Set result = ActiveSheet.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not result Is Nothing Then
outRow = result.Row
outColumn = result.Column
End If
作为奖励,您可以避免打相同的电话两次。但是再一次,请考虑只返回result
范围:
Set FindRange = result
最后,在here中查找一种实际上可靠的方法来检索工作表上的最后一行/列。 UsedRange
能说谎。该答案还列出了执行此操作的各种方法,以及为什么不使用它们。
答案 3 :(得分:0)
这里是根据上述说明进行的重写。
Public sub FindRange(ws as worksheet, byref Rw As Long, byref CL As Long)
with ws
CL = .Cells.Find(What:="*", _
After:=.cells(1), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Rw = .Cells.Find(What:="*", _
After:=.cells(1), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
end with
End sub
Sub Range_Find_Method()
Dim Rw As Long
Dim CL As Long
FindRange ActiveSheet, Rw, CL
ActiveSheet.Range("A1", ActiveSheet.Cells(Rw, CL)).Select
End Sub