关于
Function或 a ,或者和Sub之间的区别(尽管一些见解是不可避免的)。ByRefByValFunction,但也可以选择使用“修改”意义上的Subusing来解决。ByRef代码
考虑以下函数:
' Returns the worksheet (object) with a specified name in a specified workbook (object).
Function getWsF(wb As Workbook, _
ByVal wsName As String) _
As Worksheet
' 'getWsF' is 'Nothing' by default.
' Try to define worksheet.
On Error Resume Next
Set getWsF = wb.Worksheets(wsName)
End Function
Run Code Online (Sandbox Code Playgroud)
您可以像下面这样使用它:
' Writes the name of a specified worksheet, if it exists, to the `Immediate` window...
Sub testFunction()
Const wsName As String = "Sheet1"
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
' Define worksheet.
Dim ws As Worksheet
Set ws = getWsF(wb, wsName)
' Test if worksheet exists.
If Not ws Is Nothing Then
Debug.Print "The worksheet name is '" & ws.Name & "'."
Else
Debug.Print "Worksheet '" & wsName & "' doesn't exist in workbook '" _
& wb.Name & "'."
End If
End Sub
Run Code Online (Sandbox Code Playgroud)
但您也可以按以下方式编写每个过程:
' Although 'ByRef' is not necessary, I'm using it to indicate that whatever
' its variable is referring to in another procedure (in this case
' a worksheet object), is going to be modified (possibly written to
' for other datatypes).
Sub getWsS(ByRef Sheet As Worksheet, _
wb As Workbook, _
ByVal wsName As String)
' 'Sheet' could be 'Nothing' or an existing worksheet. You could omit
' the following line if you plan to use the procedure immediately
' after declaring the worksheet object, but I would consider it
' as too risky. Therefore:
' 'Reinitialize' worksheet variable.
Set Sheet = Nothing
' Try to define worksheet.
On Error Resume Next
Set Sheet = wb.Worksheets(wsName)
End Sub
' Writes the name of a specified worksheet, if it exists, to the `Immediate` window...
Sub testSub()
Const wsName As String = "Sheet1"
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
' Define worksheet.
Dim ws As Worksheet
getWsS ws, wb, wsName
' Test if worksheet exists.
If Not ws Is Nothing Then
Debug.Print "The worksheet name is '" & ws.Name & "'."
Else
Debug.Print "Worksheet '" & wsName & "' doesn't exist in workbook '" _
& wb.Name & "'."
End If
End Sub
Run Code Online (Sandbox Code Playgroud)
并排
程序
Function getWsF(wb As Workbook, _ Sub getWsS(ByRef Sheet As Worksheet, _
wsName As String) _ wb As Workbook, _
As Worksheet wsName As String)
Set Sheet = Nothing
On Error Resume Next On Error Resume Next
Set getWsF = wb.Worksheets(wsName) Set Sheet = wb.Worksheets(wsName)
End Function End Sub
Run Code Online (Sandbox Code Playgroud)
用途(相关)
' Define worksheet. ' Define worksheet.
Dim ws As Worksheet Dim ws As Worksheet
Set ws = getWsF(wb, wsName) getWsS ws, wb, wsName
Run Code Online (Sandbox Code Playgroud)
问题
对于你的情况,我会使用这种Function方法,原因如下:
With getWsF(ThisWorkbook, "Sheet1")
'...
End With
Run Code Online (Sandbox Code Playgroud)
显然,我需要确保它永远不会返回Nothing或有一些错误处理。
或者
DoSomething getWsF(ThisWorkbook, "Sheet1")
Run Code Online (Sandbox Code Playgroud)
其中 DoSomething 是一个需要工作表/无的方法
正如 @TimWilliams 在评论中提到的,如果您不期望多个返回值,那么这是“预期”的方法。一个公认的约定是,如果方法没有返回值,则它应该是Sub. 如果它有一个返回值,那么它应该是一个Function. 如果它返回多个值,那么它也应该是Functionand:
您可以使用类或类型将它们打包为一个结果
或者,该函数返回一个主值作为结果,其余返回值通过引用(有关示例,请参阅 @UnhandledException 的答案)。
如果您需要调用该方法,Application.Run那么Function是安全的。使用 aSub通常会导致自动化错误或代码在执行方法后停止运行。是否需要使用 Function 的结果并不重要,Sub如果您不想出现严重错误,请不要使用 Application.Run 调用 a 。当然,为了避免 Application.Run 出现问题,您可以拥有一个不分配返回值但仍返回 Worksheet ByRef 的 Function,但这对读者来说太令人困惑了。
编辑#1
忘记提及Application.Run从不同文档调用方法时会发生自动化错误(对于 Excel - 不同的工作簿)
编辑#2
在本节中,我将尝试解决您的问题的正确描述方面,而不是进行初级解释和高级解释,而是综合解释。
Suba和 a之间的区别Function
ASub只是一个函数,函数执行后不返回值。在许多语言中,这样的函数称为Void Function。
其含义是 aSub只是一个独立的语句。不能从表达式内部调用它。您只能使用以下之一来调用它:
MySub [argsList]Call MySub([argsList])另一方面,aFunction可以在语句中使用,例如:
DoSomething MyFunction(...);Debug.Print MyFunction(...)x = MyFunction(...)With块例如With MyFunction(...)MyFunction(...).DoSomething上面提到的约定:
一个公认的约定是,如果方法没有返回值,则它应该是
Sub. 如果它有一个返回值那么它应该是Function
当我们根据定义了解 aSub执行某些操作并且 aFunction返回单个值时,情况就变得非常清楚了。
aSub和 a之间的相似性Function
返回值函数(Function在 VBA 中)和 void 函数(Sub在 VBA 中)都接收值作为参数。在VBA中,可以通过ByRef参数返回结果。并非所有语言都支持 ByRef 参数(例如 Java - 例如修改对象的成员除外)。
请注意,如果在源平台中滥用 ByRef 方法,则将代码从支持 ByRef 的平台移植到另一个不支持 ByRef 的平台可能会非常耗时。
ByVal和ByRef参数之间的差异
按值传递(ByVal):
通过引用传递(ByRef):
所提出方法的比较
现在我们对差异有了一些了解,我们可以看看所提出的两种方法。让我们从以下开始Sub:
Sub getWsS(ByRef Sheet As Worksheet, wb As Workbook, ByVal wsName As String)
Set Sheet = Nothing
On Error Resume Next
Set Sheet = wb.Worksheets(wsName)
End Sub
Run Code Online (Sandbox Code Playgroud)
首先,On Error GoTo 0在 之前应该有一个语句End Sub,因为否则错误 9 会沿着调用链向上传播(如果未找到工作表),并且在 getWsS 方法返回很久之后会影响其他方法内的逻辑。
方法名称以动词“get”开头,这意味着该方法返回某些内容,但方法声明是 a Sub,根据定义,它更像是Do Something而不是Return Something。可读性肯定会受到影响。
需要一个额外的 ByRef 参数来返回单个结果。影响:
Set Sheet = Nothing以确保原始变量不保留以前的内容现在,让我们看看该Function方法:
Function getWsF(wb As Workbook, ByVal wsName As String) As Worksheet
On Error Resume Next
Set getWsF = wb.Worksheets(wsName)
End Function
Run Code Online (Sandbox Code Playgroud)
和以前一样,前面应该有一个On Error GoTo 0语句End Function,否则错误 9 会沿着调用链向上传播。此外,工作簿可以通过 ByVal 作为最佳实践。
明显差异:
Sub同行Nothing我使用过CTimer,在我的 x64 机器上,该Sub方法运行速度更快,当运行该方法一百万次时,大约需要 20 毫秒。这些微小的效率提升值得牺牲可读性和使用灵活性吗?这是只有代码库的维护者才能决定的事情。
| 归档时间: |
|
| 查看次数: |
788 次 |
| 最近记录: |