【问题标题】:VBA using function return values instead of variablesVBA使用函数返回值而不是变量
【发布时间】:2020-10-28 13:46:47
【问题描述】:

我尝试在互联网上搜索这个由两部分组成的场景的明确答案,但找不到任何结论性的答案。我已经在 Access 和 Excel 中编写 VBA 程序有一段时间了,在尝试简化一些代码时,我遇到了一些难题

第一部分是关于使用函数返回对象。下面的例子一般是我在网上看到的一个函数返回一个 ADODB.Recordset(我已经简化了代码,所以没有错误处理等)。

Public Function CreateADORecordset(SQL As String, Connection As ADODB.Connection) As ADODB.Recordset

Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Call rst.Open(SQL, Connection)
Set CreateADORecordset = rst

End Function

问题的第一部分是,当我可以这样重写函数时,为什么我需要一个名为 rst 的变量:

Public Function CreateADORecordset(SQL As String, Connection As ADODB.Connection) As ADODB.Recordset

Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, Connection)

End Function

上面的函数重写有什么根本错误吗?由于函数返回一个ADO记录集,为什么要单独声明一个变量呢?

我可以更进一步:

Public Function CreateADOConnection(ConnectionString As String) As ADODB.Connection

Set CreateADOConnection = New ADODB.Connection
Call CreateADOConnection.Open(ConnectionString)

End Function

Public Function CreateADORecordset(SQL As String, ConnectionString As String) As ADODB.Recordset

Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, CreateADOConnection(ConnectionString))

End Function

再一次,使用函数返回对象而不是通过 Dim 在过程中声明对象是一件特别糟糕的事情吗?

总体而言,我一直在编写 VBA 代码以通过 GetRows 将记录集的内容传输到 Excel 范围。函数声明行是:

Public Sub TransferRecordsetArray(GetRows As Variant, Destination As Range)

由于 TransferRecordsetArray 工作正常,我没有包含代码。

我现在的困境是在这种情况下,我已经达到了不需要为代码正确运行而声明任何变量的地步,而且我不确定有多少是好事还是坏事this 在函数返回对象、范围和变量等方面。

为了正确运行代码,我只需要没有变量的两行之一:

Call TransferRecordsetArray(CreateADOConnection(ConnectionString).Execute(SQL).GetRows, Target)

或

Call TransferRecordsetArray(CreateADORecordset(SQL, CreateADOConnection(ConnectionString)).GetRows, Target)

对于这种编写 VBA 代码的方式的任何建议/建议将不胜感激。我已经使用任务管理器来关注这两种方法的内存使用情况,它似乎并没有太大的不同,而且似乎 VBA 会在一段时间后销毁函数返回对象,尽管它们没有通过将它们设置为显式销毁什么都没有。

非常感谢。

【问题讨论】:

  • Call CreateADORecordset.Open(SQL, Connection) - 你可以去掉Call 和括号:CreateADORecordset.Open SQL, Connection。
  • @freeflow "VBA 可能会卡住" 不是真的。那是静态错误。代码要么编译,要么不编译。 VBA 不会卡住。

标签: vba function variables scope


【解决方案1】:

问题的第一部分是,当我可以将函数重写为 this 时,为什么我需要一个名为 rst 的变量

Public Function CreateADORecordset(SQL As String, Connection As ADODB.Connection) As ADODB.Recordset

Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, Connection)

End Function

您不需要单独的变量。您的代码非常好。

我可以更进一步:

Public Function CreateADOConnection(ConnectionString As String) As ADODB.Connection

Set CreateADOConnection = New ADODB.Connection
Call CreateADOConnection.Open(ConnectionString)

End Function

Public Function CreateADORecordset(SQL As String, ConnectionString As String) As ADODB.Recordset

Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, CreateADOConnection(ConnectionString))

End Function

是的,当然。没有错。

我已经达到了不需要为代码正确运行而声明任何变量的地步

恭喜,继续加油。 :)

延伸阅读:Is there a need to set Objects to Nothing

【讨论】:

  • 总的来说,我同意你所说的。对于最后一个也是最后一个场景,我关心的是可读性,更重要的是,错误处理。如果无法建立连接怎么办?如果数据检索失败怎么办?所以是的,语法是有效的,但是将方法调用串在一起假设太多了。
  • @BrianMStafford OP 表示他们出于问题的目的进行了错误处理。当CreateADOConnection 失败时,它可以像以前一样在内部处理错误。当下游代码调用 CreateADOConnection 失败时,同样适用。 “在一条线上做所有事情”是否是一种选择,这是一个偏好(以及必要性或缺乏)的问题,但这不是 IMO 问题的范围。
  • @BrianMStafford 针对可读性问题,我有一条规则,即代码行不得超过 95 个字符(这似乎是从 VBE 中打印时 A4 纸可以容纳的最大尺寸) .如果一行确实变得太长,则始终可以选择续行。
猜你喜欢
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
相关资源
最近更新 更多