VBA类实例化和范围

问题描述

我想创建旨在用作配置管理和服务助手的类。它将一些基本的连接设置存储在XML文件中,将其读取为它自己的属性,并服务于任何其他模块,表单,对象等。 我创建了一个如下所示的类:

Option Compare Database
Option Explicit

Private mstrsqlServerName As String
'...


Public Property Get sqlServerName() As String
   sqlServerName = mstrsqlServerName
End Property
'...

Private Sub Class_Initialize()
    readConfigFile
End Sub

Private Function loadConfigFile() As MSXML2.DOMDocument60
On Error GoTo FunctionError
Dim XMLFileName As String
Dim objRoot As IXMLDOMElement
Dim strMsg As String
Dim oXMLFile As MSXML2.DOMDocument60
 
'Open the xml file
Set oXMLFile = New MSXML2.DOMDocument60
XMLFileName = (Application.CurrentProject.Path & "\config.xml")
With oXMLFile
    .validateOnParse = True
    .SetProperty "SelectionLanguage","XPath"
    .async = False
    .Load (XMLFileName)
End With
    
Set loadConfigFile = oXMLFile

End Function


Public Sub readConfigFile()

    Dim oXMLFile As MSXML2.DOMDocument60
    
    Set oXMLFile = loadConfigFile

    mstrsqlServerName = oXMLFile.selectSingleNode("//config/database/sqlServerName").Text

End Sub

我已经在中间窗口中测试了我的课程,并且一切正常。然后 我创建了隐藏的表单来实例化该类,如下所示:

'frmYouShouldNotSeeMe
Option Compare Database
Option Explicit

Public configuration As clsConfiguration

Private Sub Form_Load()

    Set configuration = New clsConfiguration
    MsgBox Prompt:=configuration.sqlServerName

End Sub

现在,来自其他模块/表单/报告等。我想使用以下命令调用配置项:

MsgBox configuration.sqlServerName

但是当我尝试编译我的项目时,它说“编译错误,变量未定义”。简而言之:我找不到从数据库的其他对象使用实例化(命名)对象属性方法。他们只是对它的存在一无所知。在中间窗口中,一切正常,我可以实例化对象并调用GET函数。我做错了什么?可能正是OOP设计带来的,但我对此并不了解。实现这个目标的最佳方法是什么?

Calling configuration object from some other form in Access DB

解决方法

您可以在类中添加两个公共函数。

赞:

Public Function SqlServerName() As String


  SqlServerName = oXMLFile.SelectSingleNode("//config/database/SqlServerName").Text


End Function

Public Function GetConfig(strNode As String,strValue As String) As String

  Dim strXPATH  As String
  strXMPATH = "//config/" & strNode & "/" & strValue
  
  
  GetConfig = oXMLFile.SelectSingleNode(strXMPATH).Text


End Function

现在在代码中,您可以使用:

 Msgbox configuration.SqlServerName

或者要获取任何配置,可以使用带有2个参数的辅助功能

Msgbox configuration("database","SqlServerName")

因此,班级的公共成员必须由您编写。它不会通过“魔术”或突然暴露出该类的信息。您可以使用公共功能,并且在创建此类公共功能时它们将显示为智能。 (它们成为类的属性)。因此,您的语法不起作用,因为您没有公开您想要的内容的公共函数(或属性get)。您可以使用属性let / get,但公共函数也可以如上所示很好地工作。

因此,可以为要公开的每个“事物”(节点)设置一个公共函数,或者使用上面的辅助函数,然后可以将key + node值与接受2个参数的函数一起传递。上面的两个都将成为该类的一部分,在编码过程中会显示智能感-您可以按照上面的说明随意向该类中添加更多公共成员。

#Edit

示例代码显示如下:

Set configuration = New clsConfiguration
MsgBox Prompt:=configuration.SqlServerName

必须是这样:

dim configuration as New clsConfiuration
MsgBox Prompt:=configuration.SqlServerName

您可以在应用程序启动时设置一个名为configueration的GLOBAL变量,这样就不必在表单代码中声明配置变量。

因此,您需要一个全局变量-在启动任何形式之前,请在启动代码中进行设置。

因此,在标准代码模块中,您需要:

Public configuration as new clsConfiguration

但是,您的代码屏幕快照缺少configuartion变量的创建。

您提供的代码包含以下内容:

Set configuration = New clsConfiguration
MsgBox Prompt:=configuration.SqlServerName

那么您在何时何地将配置定义为全局范围变量?

您必须对表单使用LOCAL范围(实际上是您的加载事件)

dim configuration as New clsConfiuration
MsgBox Prompt:=configuration.SqlServerName

或者,如上所述,您可以在starndard代码模块(不是Forms模块,当然也不是class模块)中将“配置”声明为公共全局变量。

如果您使用“ new”关键字,则可以使用此关键字:

Public configuration as New clsConfiuration

以上内容可以放置在任何标准代码模块中-范围是全局的。

在上面,然后在表单加载事件中,它将起作用:

 MsgBox Prompt:=configuration.SqlServerName
,

configuration中声明了frmYouShouldNotSeeMe以后,只要打开表单,就可以引用该表单来访问变量。

Debug.Print Forms("frmYouShouldNotSeeMe").configuration.SqlServerName