在表单打开时将对象保存在内存中(访问)
Keep object in memory while is form is open (access)
我正在编写一个访问应用程序,我只是花时间设置了一个 class 以使该应用程序易于理解和高效。
但是,当我第二次点击事件需要该对象时,该对象已不在内存中。
我让用户点击一个按钮来设置对象并进行一些测试:
Public this_renewal As Renewal
Private Sub cmdMA_Click()
Set this_renewal = Factory.CreateRenewal(cMA)
Call BranchLabelVisibility(True)
Me.lblBranchToAdd.Caption = this_renewal.Abb
Call DateLabelVisibility(True)
Me.lblYearToAdd.Caption = this_renewal.Year
Me.lblMonthToAdd.Caption = this_renewal.Month
Call TestMonth
End Sub
这是我在名为 factory 的常规模块中的 CreateRenewal 函数。我从另一个关于如何使用属性初始化 class 的线程中得到这个想法:VBA: Initialize object with values?
Public Function CreateRenewal(strFileName As String) As Renewal
Dim renewal_obj As Renewal
Set renewal_obj = New Renewal
Call renewal_obj.InitiateProperties(strFileName)
Set CreateRenewal = renewal_obj
End Function
并在更新中调用 InititateProperties class:
Public Sub InitiateProperties(ByVal strFileName As String)
strRenewalFile = strFileName
strRenewalFullFileName = fnGetFullFileName()
strRenewalFileAndPath = cPath & strRenewalFullFileName
strBranchLetter = fnGetLetterFromFile(strRenewalFile)
strAbb = DLookup("BranchAbb", "tblBranches", "BranchLetter = '" & strBranchLetter & "'")
strBranchName = DLookup("Branch", "tblBranches", "BranchAbb = '" & strAbb & "'")
If Len(Mid(strRenewalFullFileName, 10, 2)) = 1 Then
strRenewalMonth = "0" & Mid(strRenewalFullFileName, 10, 2)
Else
strRenewalMonth = Mid(strRenewalFullFileName, 10, 2)
End If
strRenewal2DigitYear = Mid(strRenewalFullFileName, 12, 2)
strRenewalYear = "20" & strRenewal2DigitYear
strRenewalTable = strAbb & " " & strRenewalYear & " Renewals"
End Sub
然后用户决定是否要导入 this_renewal 文件(这是内存中的对象),如果要导入则单击导入按钮运行此代码:
Private Sub cmdImport_Click()
DoCmd.SetWarnings False
Call FixExcelFile
Dim strTableName As String
Dim strImportName As String
strTableName = this_renewal.Table
'strImportName = Left(fnGetFileName(Me.tbFileToImport), 8)
Call ImportTable
'Count and Display Values of the two Tables
Call TableLabelVisibility(True)
Call GetTableValues
'Create Backup of Original
Call CreateBackup
'Run Queries to Update Data of Import
Call AppendQuery
Call UpdateMonth
Call UpdateStatus
Call UpdateUnderWriter
Call ShowResults
DoCmd.SetWarnings True
End Sub
如果我在 cmdMA_Click 事件期间单步执行代码,则会创建对象并在 class 的 InitiateProperties 子项中初始化这些属性。单击事件完成后,我触发了下一个单击事件(在下一个按钮上,在同一表单上),我收到该对象的“对象变量或未设置变量”。在原始点击事件中我没有问题。
由于未显示 Factory.CreateRenewal(cMA)
的相关代码,我创建了一个如何 re-produce 错误的示例。
我有一个 class this_renewal
,代码如下
Option Explicit
Public Function myTest() As String
myTest = "Test"
End Function
然后我用 Attribute VB_PredeclaredId = True
和下面的代码
创建了一个 class Factory
Option Explicit
Public Function CreateRenewal(cMA As String) As this_renewal
' Doing nothing here
' result will be that CreateRenewal will return Nothing
' which will lead to the error
' "Object Variable or With Variable not set"
End Function
在用户表单中,我有两个带有代码的按钮
Option Explicit
Public this_renewal As this_renewal
Private Sub btn1_Click()
Set this_renewal = Factory.CreateRenewal("cMA")
End Sub
Private Sub btn2_Click()
Debug.Print this_renewal.myTest
End Sub
如果我将 Factory
class 中的代码更改为
Public Function CreateRenewal(cMA As String) As this_renewal
Set CreateRenewal = New this_renewal
End Function
如果我先按 btn1 然后再按 btn2,一切都会正常。
如果 class var 是 public 到表单代码并创建?然后它将并且应该在该表单打开的整个生命周期内持续存在。您当然不能在全局级别或以其他形式引用您以该形式创建的 class 变量。
因此您可以将 var 声明移动到标准 public 模块(在表格之外),或者实际上在其他表格中这样做:
在我们的表单中 - 在表单级模块中声明 class - 作为 public
Option Compare Database
Option Explicit
Public this_renewal As Renewal
所以,现在假设您的表单运行代码来设置对象,就像这样:
Set this_renewal = Factory.CreateRenewal(cMA)
现在,如果您打开任何其他表格?好吧,您有两种选择来获得 class.
您可以参考上面的表格,并在代码中这样做:
dim this_renewal As Renewal
set this_renewal = forms!ThatFirstFormabove.this_renewal.
因此,class 实例仅存在于您声明 var (this_renewal) 的表单的上下文中。
你也可以这样做。用第一种形式说(public this_renewal)。
您将在目标表单中同时在表单级别代码中声明 this_renewal。
那么你会并且可以这样做:
docmd.OpenForm("frmB")
set forms("frmB").this_renewal = me.this_renewal
因此,要么传递 class,要么直接从具有 class 的当前表单引用它,或者将 class 的 var 声明移出形成模块代码,放置在全球标准平面jane模块中。在模块 1 中说。
如果您这样做,那么所有表单和所有代码都可以使用 class.
的那个实例
我明白了;发生这种事情真是太愚蠢了。所以在第一次点击事件期间调用的最后一个过程中:
Private Sub TestMonth()
If this_renewal.IsNewMonth Then
Me.cmdImport.Enabled = True
Me.lblFileMistake.Visible = False
Else
GoTo WrongFile
End If
endSub:
Exit Sub
WrongFile:
Me.cmdImport.Enabled = False
Me.lblFileMistake.Visible = True
Me.lblFileMistake.Caption = "Month " & this_renewal.Month & " was already added for branch " & this_renewal.Name & "!!"
GoTo endSub
End Sub
就在我 'Exit Sub' 的地方,它是 'End'。这将清除所有变量。一旦我将其更改为 'Exit Sub',它现在可以正常工作了。
我正在编写一个访问应用程序,我只是花时间设置了一个 class 以使该应用程序易于理解和高效。
但是,当我第二次点击事件需要该对象时,该对象已不在内存中。
我让用户点击一个按钮来设置对象并进行一些测试:
Public this_renewal As Renewal
Private Sub cmdMA_Click()
Set this_renewal = Factory.CreateRenewal(cMA)
Call BranchLabelVisibility(True)
Me.lblBranchToAdd.Caption = this_renewal.Abb
Call DateLabelVisibility(True)
Me.lblYearToAdd.Caption = this_renewal.Year
Me.lblMonthToAdd.Caption = this_renewal.Month
Call TestMonth
End Sub
这是我在名为 factory 的常规模块中的 CreateRenewal 函数。我从另一个关于如何使用属性初始化 class 的线程中得到这个想法:VBA: Initialize object with values?
Public Function CreateRenewal(strFileName As String) As Renewal
Dim renewal_obj As Renewal
Set renewal_obj = New Renewal
Call renewal_obj.InitiateProperties(strFileName)
Set CreateRenewal = renewal_obj
End Function
并在更新中调用 InititateProperties class:
Public Sub InitiateProperties(ByVal strFileName As String)
strRenewalFile = strFileName
strRenewalFullFileName = fnGetFullFileName()
strRenewalFileAndPath = cPath & strRenewalFullFileName
strBranchLetter = fnGetLetterFromFile(strRenewalFile)
strAbb = DLookup("BranchAbb", "tblBranches", "BranchLetter = '" & strBranchLetter & "'")
strBranchName = DLookup("Branch", "tblBranches", "BranchAbb = '" & strAbb & "'")
If Len(Mid(strRenewalFullFileName, 10, 2)) = 1 Then
strRenewalMonth = "0" & Mid(strRenewalFullFileName, 10, 2)
Else
strRenewalMonth = Mid(strRenewalFullFileName, 10, 2)
End If
strRenewal2DigitYear = Mid(strRenewalFullFileName, 12, 2)
strRenewalYear = "20" & strRenewal2DigitYear
strRenewalTable = strAbb & " " & strRenewalYear & " Renewals"
End Sub
然后用户决定是否要导入 this_renewal 文件(这是内存中的对象),如果要导入则单击导入按钮运行此代码:
Private Sub cmdImport_Click()
DoCmd.SetWarnings False
Call FixExcelFile
Dim strTableName As String
Dim strImportName As String
strTableName = this_renewal.Table
'strImportName = Left(fnGetFileName(Me.tbFileToImport), 8)
Call ImportTable
'Count and Display Values of the two Tables
Call TableLabelVisibility(True)
Call GetTableValues
'Create Backup of Original
Call CreateBackup
'Run Queries to Update Data of Import
Call AppendQuery
Call UpdateMonth
Call UpdateStatus
Call UpdateUnderWriter
Call ShowResults
DoCmd.SetWarnings True
End Sub
如果我在 cmdMA_Click 事件期间单步执行代码,则会创建对象并在 class 的 InitiateProperties 子项中初始化这些属性。单击事件完成后,我触发了下一个单击事件(在下一个按钮上,在同一表单上),我收到该对象的“对象变量或未设置变量”。在原始点击事件中我没有问题。
由于未显示 Factory.CreateRenewal(cMA)
的相关代码,我创建了一个如何 re-produce 错误的示例。
我有一个 class this_renewal
,代码如下
Option Explicit
Public Function myTest() As String
myTest = "Test"
End Function
然后我用 Attribute VB_PredeclaredId = True
和下面的代码
Factory
Option Explicit
Public Function CreateRenewal(cMA As String) As this_renewal
' Doing nothing here
' result will be that CreateRenewal will return Nothing
' which will lead to the error
' "Object Variable or With Variable not set"
End Function
在用户表单中,我有两个带有代码的按钮
Option Explicit
Public this_renewal As this_renewal
Private Sub btn1_Click()
Set this_renewal = Factory.CreateRenewal("cMA")
End Sub
Private Sub btn2_Click()
Debug.Print this_renewal.myTest
End Sub
如果我将 Factory
class 中的代码更改为
Public Function CreateRenewal(cMA As String) As this_renewal
Set CreateRenewal = New this_renewal
End Function
如果我先按 btn1 然后再按 btn2,一切都会正常。
如果 class var 是 public 到表单代码并创建?然后它将并且应该在该表单打开的整个生命周期内持续存在。您当然不能在全局级别或以其他形式引用您以该形式创建的 class 变量。
因此您可以将 var 声明移动到标准 public 模块(在表格之外),或者实际上在其他表格中这样做:
在我们的表单中 - 在表单级模块中声明 class - 作为 public
Option Compare Database
Option Explicit
Public this_renewal As Renewal
所以,现在假设您的表单运行代码来设置对象,就像这样:
Set this_renewal = Factory.CreateRenewal(cMA)
现在,如果您打开任何其他表格?好吧,您有两种选择来获得 class.
您可以参考上面的表格,并在代码中这样做:
dim this_renewal As Renewal
set this_renewal = forms!ThatFirstFormabove.this_renewal.
因此,class 实例仅存在于您声明 var (this_renewal) 的表单的上下文中。
你也可以这样做。用第一种形式说(public this_renewal)。
您将在目标表单中同时在表单级别代码中声明 this_renewal。
那么你会并且可以这样做:
docmd.OpenForm("frmB")
set forms("frmB").this_renewal = me.this_renewal
因此,要么传递 class,要么直接从具有 class 的当前表单引用它,或者将 class 的 var 声明移出形成模块代码,放置在全球标准平面jane模块中。在模块 1 中说。
如果您这样做,那么所有表单和所有代码都可以使用 class.
的那个实例我明白了;发生这种事情真是太愚蠢了。所以在第一次点击事件期间调用的最后一个过程中:
Private Sub TestMonth()
If this_renewal.IsNewMonth Then
Me.cmdImport.Enabled = True
Me.lblFileMistake.Visible = False
Else
GoTo WrongFile
End If
endSub:
Exit Sub
WrongFile:
Me.cmdImport.Enabled = False
Me.lblFileMistake.Visible = True
Me.lblFileMistake.Caption = "Month " & this_renewal.Month & " was already added for branch " & this_renewal.Name & "!!"
GoTo endSub
End Sub
就在我 'Exit Sub' 的地方,它是 'End'。这将清除所有变量。一旦我将其更改为 'Exit Sub',它现在可以正常工作了。