将记录集存储为类的实例?

Lie*_*cin 4 excel vba recordset

有以下场景.我有一些表单,基本上有一些dropbox,列表等.我用ms sql db中的记录填充它们.但是,有没有办法只查询一次数据库并在整个应用程序生命周期中将记录存储为类的实例,而不是每次用户打开表单时查询?

连接如下:

Sub connection_test()

    Dim Cn As ADODB.Connection
    Dim Rs As ADODB.Recordset
    Dim stSQL As String

    stSQL = "SELECT * FROM dbo.Client"

    Set Cn = New ADODB.Connection

    With Cn
        .CursorLocation = adUseClient
        .Open CONNECTION_STRING
        .CommandTimeout = 0
        Set Rs = .Execute(stSQL)
    End With

    Rs.Close
    Cn.Close
    Set Rs = Nothing
    Set Cn = Nothing
End Sub
Run Code Online (Sandbox Code Playgroud)

有人可以为我建议一个解决方案吗?我可以看到来自交通繁忙的所有问题,而且大部分是不必要

Dic*_*ika 5

如果您只想获得记录集,请将变量调整为标准模块中的公共变量

Public Rs As ADODB.Recordset

Sub connection_test()

    Dim Cn As ADODB.Connection
    Dim sSQL As String

    If Rs.State = adStateClosed Then
        sSQL = "SELECT * FROM dbo.Client"

        Set Cn = New ADODB.Connection

        With Cn
            .CursorLocation = adUseClient
            .Open CONNECTION_STRING
            .CommandTimeout = 0
            Set Rs = .Execute(sSQL)
        End With
    End If

End Sub
Run Code Online (Sandbox Code Playgroud)

现在Rs将在项目的任何地方可用.您可以随时运行connection_test,如果它关闭了记录集,它将创建它.如果没有,你很高兴.

通常我的方法是创建自定义类.我将创建一个CClient类,从记录集(或其他地方)填充它,使用业务逻辑操作对象,然后将新值写回数据库.这样,我的业务逻辑都不依赖于我正在使用ado的事实.我可以切换到文本文件或Excel工作表作为数据存储,而不必担心代码中的所有依赖项.

例如,假设我有一个Access表:

 ClientID, Autonumber
 ContactFirst, String
 ContactLast, String
 Company, String
 CityState, String
 Volume, Double
Run Code Online (Sandbox Code Playgroud)

我创建了一个CClient类,其中包含表格中每个字段的属性.我还创建了一个CClients类来保存所有CClient实例.在标准模块中,您可能有这样的东西

Public gclsClients As CClients

Sub Main()

    Set gclsClients = New CClients

    'Fill the class
    gclsClients.FillFromRS

    'change some value
    gclsClients.Client(1).Volume = 100

    'write back to the database
    gclsClients.WriteToDB

End Sub
Run Code Online (Sandbox Code Playgroud)

在我改变一个客户端的数量的地方,你会有更多的代码调用你的用户形式等等.基础知识是,加载类,做你需要的任何事情,然后把类数据写回数据库.我不会向你展示所有类代码,但在CClients中

Public Sub FillFromRS()

    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim clsClient As CClient

    Const sSQL As String = "SELECT * FROM tblClient"

    Set cn = New ADODB.Connection

    cn.Open msCON
    Set rs = cn.Execute(sSQL)

    If Not rs.BOF And Not rs.EOF Then
        rs.MoveFirst
        Do While Not rs.EOF
            Set clsClient = New CClient
            With clsClient
                .ClientID = rs.Fields("ClientID").Value
                .ContactFirst = rs.Fields("ContactFirst").Value
                .ContactLast = rs.Fields("ContactLast").Value
                .Company = rs.Fields("Company").Value
                .CityState = rs.Fields("CityState").Value
                .Volume = rs.Fields("Volume").Value
            End With
            Me.Add clsClient
            rs.MoveNext
        Loop
    End If

End Sub
Run Code Online (Sandbox Code Playgroud)

此方法从数据库获取数据并填充一堆CClient实例.也在CClients中

Public Sub WriteToDB()

    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim clsClient As CClient
    Dim sSQL As String

    Set cn = New ADODB.Connection

    cn.Open msCON

    For Each clsClient In Me
        sSQL = BuildUpdateSQL(clsClient)
        cn.Execute sSQL
    Next clsClient

End Sub

Private Function BuildUpdateSQL(clsClient As CClient)

    Dim sReturn As String

    With clsClient
        sReturn = "UPDATE tblClient SET ContactFirst = '" & .ContactFirst & "',"
        sReturn = sReturn & " ContactLast = '" & .ContactLast & "',"
        sReturn = sReturn & " Company = '" & .Company & "',"
        sReturn = sReturn & " CityState = '" & .CityState & "',"
        sReturn = sReturn & " Volume = " & .Volume
        sReturn = sReturn & " WHERE ClientID = " & .ClientID & ";"
    End With

    BuildUpdateSQL = sReturn

End Function
Run Code Online (Sandbox Code Playgroud)

此方法遍历所有CClient实例,创建UPDATE sql语句并执行它.您将要在CClient中实现某种IsDirty属性,以便您只更新那些更改了某些内容的客户端.CClients和CClient的其余部分是基本的类模块.

你可以调用WriteToDB很多或者一点点.在某些应用程序中,只要有变化,我就会编写它.在其他情况下,我只在工作簿关闭时回写到数据库.这取决于您的应用程序的流程.真正的美妙之处在于,如果您从Access数据库更改为用于数据存储的文本文件,您只需要更改为CClients中的方法.所有其余代码都使用CClients,而不关心数据的存在位置.

您可以在此处查看工作簿和Access数据库http://www.dailydoseofexcel.com/excel/ClientClassExample.zip