如何从 Access VBA 中的另一个私有子获取私有子中声明的变量的值

Posted

技术标签:

【中文标题】如何从 Access VBA 中的另一个私有子获取私有子中声明的变量的值【英文标题】:How Can I obtain the value of variables declared in a private sub from another private sub in Access VBA 【发布时间】:2018-12-22 13:59:46 【问题描述】:

我使用的是 Microsoft Access 2013,在使用 VBA 时遇到了这个问题。 是否可以将在私有子中声明或定义的变量的值传递给全局变量? 我尝试了不同的方法......但都没有奏效

首先,我在我使用的私有子中定义并声明了变量。 接下来,我将变量定义为公共变量,然后在该私有子中定义它,但是当我尝试将其值传递给全局变量时,它返回 null。我不知道是不是因为它在条件语句中。

Option Compare Database
Public recUserID As Long
Option Explicit

Private Sub txtPassword_AfterUpdate()
  Dim db As DAO.Database
  Dim rs As DAO.Recordset 
  Set db = CurrentDb
  Set rs = db.OpenRecordset("SELECT * FROM tblUser")

'Check that user is selected/entered
If IsNull(Me.txtUser) Then
    MsgBox "Select User"
Else
    rs.FindFirst "[PersonnelID] = '" & Me.txtUser & "'"

    If rs.NoMatch Then
        MsgBox "User does not exist, please enter correct ID"
    Else
        recUserID = rs![UserID]
    End If
End If
End Sub

Private Sub Form_AfterUpdate()
    gblStudent = recUserID
End Sub 

应该是把记录的ID变量recUserID的值传给全局变量gblStudent,但是调试的时候,Form的AfterUpdate处的变量返回0

注意:表单绑定到表,因此,更新后功能起作用

【问题讨论】:

你好维克多!回答者在这里猜测是因为您没有提供足够的上下文让他们可靠地了解问题所在。不用担心这个,Access 问题很难做到。相反,您会收到有关如何自己解决问题的建议,这是我们在这种情况下可以做的最好的事情。我希望这些想法之一对您有所帮助。如果您确实找到了解决方案,请在此处发布以供未来读者使用。 如果您发布的代码在表单代码模块中,它将无法工作,因为该表单和代码可能超出范围。您必须在标准代码模块中声明 recUSERID,而不是在表单中声明。因此,您上面的所有代码都可以保持“原样”,但是您必须将更多的 recUserID 声明为标准(非表单)代码模块,这样就可以了。 【参考方案1】:

你确定事件被触发了吗? Form_AfterUpdate()

在此处放置一个消息框以进行健全性检查。

顺便说一句;我了解您的目标 - 由于调试挑战,我自己已经放弃了这种方法......相反,我的应用程序总是有一个始终打开的“开始”屏幕 - - 这里是我放置未绑定文本框的地方,它们的用途与作为一个全球性的......但我可以在开发过程中让它们可见,以便轻松看到它们的价值。如果它适合您的项目,请记住一些事情。

【讨论】:

【参考方案2】:

首先,请阅读断点和Debug.Print:Debugging VBA Code

Form_AfterUpdate() 仅在保存记录后为绑定表单触发。

登录表单通常是unbound,即它没有记录源。所以你的函数永远不会执行。您需要为此找到不同的事件。

【讨论】:

我其实是把这个表单绑定到了一个日志表上,用来跟踪登录数据库系统的人。 @VictorAbuka 我会解释安德烈的回答,并且更明确一点:如果您发现recUserIDForm_AfterUpdate 中为0,那么下一个合乎逻辑的步骤应该是停止并跟踪应该设置变量的代码。用户 Debug.Print,然后检查 VBA 即时窗口的输出。或者在recUserID = rs![UserID] 上放置一个断点来确定该行是否被调用。问题不太可能与为变量赋值有关,而更多地与代码是否实际被调用或是否按照您认为的顺序有关。 我明白了,我会这样做的【参考方案3】:

许多开发人员不喜欢全局变量,但事实证明它们在 Access 开发中通常很有用。我的建议是永远不要在模块中使用“裸全局”。而是使用公共属性:

' Standard module (not a class or code behind form/report)
Private mgblStudent As Variant ' only visible/changeable within the module
Public Property Get gblStudent As Variant
    gblStudent = mgblStudent
End Property
Public Property Let gblStudent (varStudent As Variant)
    mgblStudent = varStudent
End Property

这样,您的代码可以像以前一样工作,但您可以在属性中放置断点以查看何时或是否设置或读取它。

【讨论】:

【参考方案4】:

当您一直称某事物为“变量”而不指定您在谈论哪一个时,解析您的问题有点困难。据我所知,您说 recUserID 在问题开始时返回“Null”,但随后您还说它返回“0”,在这种情况下这将是非常不同的结果。无论如何,我的印象是 recUserID 设置不正确,或者在您引用它时不再正确。

要在我自己的代码中解决此问题,我将从 Cahaba Data 建议的内容开始;添加一些消息框:

If IsNull(Me.txtUser) Then
    MsgBox "Select User"
Else
    rs.FindFirst "[PersonnelID] = '" & Me.txtUser & "'"

    If rs.NoMatch Then
        MsgBox "User does not exist, please enter correct ID"
    Else
        recUserID = rs![UserID]
        MsgBox (recUserID) 'Add here
    End If
End If
End Sub

Private Sub Form_AfterUpdate()
    MsgBox (recUserID) 'Add here    
    gblStudent = recUserID
    MsgBox (gblStudent) 'Add here
End Sub

理想情况下,您应该看到所有 3 个消息框,其中包含您期望的 ID。第一个错误将有助于告诉您问题出在哪里。

【讨论】:

【参考方案5】:

我通过从数据库中的记录集中调用值来解决问题,然后将该值传递给我所需的全局变量

Dim state As DAO.Recordset
Set state = CurrentDb.OpenRecordset("select * from tblStudent")

state.FindFirst "[MatriculationNumber] = '" & Me.txtUser & "'"

gblStudent = state![StudentID]

然而,我将此代码放在表单 (txtPassword) 上控件的 AfterUpdate 属性中以避免歧义

【讨论】:

以上是关于如何从 Access VBA 中的另一个私有子获取私有子中声明的变量的值的主要内容,如果未能解决你的问题,请参考以下文章

从 Access 中的另一个子窗体更改子窗体的记录源

在 Excel 中运行 VBA 代码以获取 Access 数据库中的 VBA

可以通过 VBA 更改 MS Access 子表单字段吗?

从 Access 中的另一个表中获取输入

如何遍历所有子窗体 MS Access VBA

VBA + SQL Server - 获取插入的最后一个 ID