使用类模块

时间:2016-05-09 21:33:37

标签: class ms-access access-vba ms-access-2007 ado

前言:我正在使用SQL Server 2008 R2 BackEnd和MS Access 2007作为FrontEnd

我有一个类模块,可以从SQL Server返回我想要的任何ADO记录集。然后,我可以将其分配给任何格式RecordSource属性。

问题在于,当我尝试编辑字段时,它会显示"此表单在状态栏中为只读" 。我希望表单可以编辑。

我有两种形式

  1. FormEntities
  2. FormEntitiesEdit
  3. FormEntitiesEdit表单不使用类模块。相反,所有代码都在表单中。

    类模块的目的是避免冗余,只需使用类模块就可以轻松地从SQL Server获取记录集。

    这里首先是我的全球模块

    
        'Default error message. 'eh' stands for error handler
        Public eh As String
    
        'Global variables for universal use
        Public conn As ADODB.Connection
        Public rs As ADODB.Recordset
        Public com As ADODB.Command
    

    第二个是CLASS MODULE(名称是 cADO )。 此类模块使用 conn 上面的连接对象

    
        Option Explicit
    
        Private Const CONST_LockType = 3
        Private Const CONST_CursorType = 1
        Private Const CONST_CursorLocationServer = 3
        Private Const CONST_CursorLocationClient = 2
    
        Private m_Recordset As ADODB.Recordset
        'For Public Recordset function
        Private cSQL$
        '**********************************************************************
        Public Function cGetRecordset(ByRef sql) As ADODB.Recordset
    
            Set m_Recordset = New ADODB.Recordset
    
            cSQL = sql
            cOpenRecordset
    
            Set cGetRecordset = m_Recordset
    
        End Function
        '**********************************************************************
        Public Property Set Recordset(Value As ADODB.Recordset)
            'Assigns private variable a property
            If Not Value Is Nothing Then Set m_Recordset = Value
    
        End Property
        '**********************************************************************
        Public Property Get Recordset() As ADODB.Recordset
            'Reads the recordset from the private variable and assigns to new object variable
            Set Recordset = m_Recordset
    
        End Property
    
    
        '********************************** PRIVATE SECTION **********************************
    
        Private Sub cOpenRecordset()
    
        On Error GoTo eh
    
            'Ensures that if a recordset is opened from previously that it closes before opening a new one
            If m_Recordset.State  adStateClosed Then m_Recordset.Close
    
            Set m_Recordset.ActiveConnection = conn
    
            With m_Recordset
                .LockType = CONST_LockType
                .CursorType = CONST_CursorType
                .CursorLocation = CONST_CursorLocationClient
                .Source = cSQL
                .Open .Source
            End With
    
            If Not m_Recordset.EOF Then m_Recordset.MoveFirst
    
        Exit Sub
        eh:
            eh = "Error # " & Str(Err.Number) & " was generated by " & _
            Err.Source & Chr(13) & Err.Description
            MsgBox eh, vbCritical, "Open Recordset System"
        End Sub
        '**********************************************************************
        Private Sub cCloseRecordset()
            m_Recordset.Close
            Set m_Recordset = Nothing
        End Sub
        '**********************************************************************
        Private Sub Class_Terminate()
    
            If Not (m_Recordset Is Nothing) Then Set m_Recordset = Nothing
    
        End Sub
    

    第三个代码是我的 FormEntities 形式(使用 cADO CLASS MODULE)

    
        Option Explicit
    
        Dim db As cADO
        '**********************************************************************
        Private Sub Form_Current()
            LoadTab
        End Sub
        '**********************************************************************
        Private Sub Form_Load()
    
            Set db = New cADO
            FetchRecordSource
        End Sub
        '**********************************************************************
        Private Sub FetchRecordSource()
    
            db.cGetRecordset ("SELECT * FROM dbo.Entities")
            Set Forms("fEntities").Recordset = db.Recordset
    
        End Sub
    
    

    第四个也就是 FormEntitiesEdit 表格背后的代码(此表格不使用类模块,我可以编辑它)

    
        Option Compare Database
        Option Explicit
    
        Dim rsEntity As New ADODB.Recordset
    
        '**********************************************************************
        Private Sub Form_Load()
            FetchRecordSource
        End Sub
    
        '**********************************************************************
        Private Sub FetchRecordSource()
    
            Set rsEntity.ActiveConnection = conn
    
            'Sets the record source for the main form
            With rsEntity
                .LockType = adLockOptimistic
                .CursorType = adOpenKeyset
                .CursorLocation = adUseClient
                .Source = "SELECT * FROM dbo.Entities"
                .Open .Source
            End With
            Set Forms("fEntitiesEdit").Recordset = rsEntity
    
        End Sub
        '**********************************************************************
        Private Sub CloseConn()
            rsEntity.Close
        End Sub
    
    

    如果Access Jet SQL可以执行SQL,我会将此表单绑定到链接表。但是我使用的是Jet SQL无法执行的分层(递归)查询,因此我不得不绕过绑定表的绑定表的想法。

    我有。允许将表单上的Edits和.AllowAdditions设置为true。

    我也尝试将ADO Recordset上的.LockType更改为

    1. adOpenKeyset和
    2. adOpenDynamic
    3. 我的LockType是adLockOptimistic

      如您所见,属性设置正确,可以编辑我返回的记录集。

      我知道这是真的,因为当我使用具有相同属性的 FormEntitiesEdit 表单时,我可以编辑该字段。但是,当我使用类模块返回(使用相同的属性)时,它表示它是只读的。

      这很重要,因为你可以看到使用类模块要简单得多,只需要它就可以返回一个可编辑的记录集。

      有人有想法吗?建议?

1 个答案:

答案 0 :(得分:2)

问题出在课堂上的.CursorLocation = CONST_CursorLocationClient 方法:

Private Const CONST_CursorLocationServer = 3
Private Const CONST_CursorLocationClient = 2

您可以在此处指定常量值...

ADODB.CursorLocationEnum

不幸的是,你交换了这两个值。以下是adUseClient = 3 adUseServer = 2 常量...

.CursorLocation = adUseServer

所以你的班级实际上是这样做的......

Private Const CONST_CursorLocationClient = 3

但如果您希望记录集可编辑,则需要客户端游标。我认为如果你只是重新定义常量,你的类方法可能会起作用,或者你会暴露出另一个问题......

.CursorLocation = adUseClient

FormEntitiesEdit 是可编辑的,因为你在那里使用了正确的常量......

// figure out what kind of format we are dealing with
if (format.indexOf('$') > -1) { // currency!!!!!