Access form associated with disabled ADODB.Recordset: save changes

I am trying to set up a form to use a disabled ADODB.Recordset as source.
The problem is that the changes are not saved in the original Access table after you close the form and answer Yes to the prompt. What am I missing?

Note. Please don't tell me the method is useless, it's just a POC with a local table, I plan to try a more remote recordset later.

Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset

Private Sub Form_Load()
    Set conn = New ADODB.Connection
    conn.Open CurrentProject.Connection

    Set rs = New ADODB.Recordset
    With rs
        rs.CursorLocation = adUseClient
        rs.Open "select * from amsPor", conn, adOpenStatic, adLockBatchOptimistic
        Set rs.ActiveConnection = Nothing
    End With
    Set Me.Recordset = rs
    conn.Close
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Select Case MsgBox("Save changes ?", vbQuestion + vbYesNoCancel)
    Case vbNo
        'do nothing
    Case vbYes
        conn.Open CurrentProject.Connection
        rs.ActiveConnection = conn
        rs.UpdateBatch
        rs.Close
        conn.Close
        Set conn = Nothing
    Case vbCancel
        Cancel = True
    End Select
End Sub

      


Steps to reproduce:

  • Take a small table with a primary key
  • Create an automatic form with it
  • Save the form.
  • Add the above code to the form, replacing the table name in the sentence select

    .
  • An empty Record Source

    form property .
  • Save and close the form.
  • You can open the form and make changes to the data. Once closed, you will be prompted to save your changes.

EDIT . I wonder if the problem might be CurrentProject.Connection

?
In the debug window, I typed ? CurrentProject.Connection

and got this:

Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=\\xxxxxx\yyyy$\Documents\AMS.accdb;Mode=Share Deny None;Extended Properties="";Jet OLEDB:System database=C:\Users\G828992\AppData\Roaming\Microsoft\Access\System.mdw;Jet OLEDB:Registry Path=Software\Microsoft\Office\14.0\Access\Access Connectivity Engine;Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=6;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=True;Jet OLEDB:Bypass UserInfo Validation=False

      

+3


source to share


4 answers


I came here looking for the same answer as you after a ton of searching and trial and error. Finally, I was able to accomplish exactly what you are trying to do. I realize this is an old post, but I haven't seen any answers that actually gave an answer that would allow for what you are trying to do. I will use your example and try to apply what I had to change and add to make it work correctly.

Dim rs As ADODB.Recordset
Dim conn As ADODB.Connection

Private Sub Form_Load()
    If CurrentProject.Connection.State = adStateOpen Then CurrentProject.Connection.Close

    Set conn = New ADODB.Connection
    conn.Open CurrentProject.Connection.ConnectionString

    Set rs = New ADODB.Recordset
    rs.CursorLocation = adUseClient
    rs.Open "select * from amsPor", conn, adOpenForwardOnly, adLockBatchOptimistic

    If Not rs Is Nothing Then
        If Not rs.ActiveConnection Is Nothing Then Set rs.ActiveConnection = Nothing
        If Not (rs.eof And rs.BOF) Then
            Set Me.Recordset = rs
        End If

        If conn.State = adStateOpen Then
            conn.Close
        End If
    End If

    Call AddNewRecord(Me.Recordset)
End Sub


Private Sub AddNewRecord(ByRef rs As ADODB.Recordset)
    On Error Resume Next 

    If Not rs Is Nothing Then
        If rs.Supports(adAddNew) Then
            rs.AddNew
            rs.Fields("FirstName").Value = "John"
            rs.Fields("LastName").Value = "Doe"

            If rs.Supports(adUpdate) Then rs.Update
        End If
    End If

    If Err.Number <> 0 Then
        Debug.Print "AddNewRecord Err Msg: " & Err.Description
        Err.Clear
    End If
End Sub


Private Sub Form_Unload(Cancel As Integer)
    Select Case MsgBox("Save changes ?", vbQuestion + vbYesNoCancel)
    Case vbYes
        Call UpdateDbWithRS(Me.Recordset)
    Case vbCancel
        Cancel = True
    Case Else
        ' Nothing.
    End Select
End Sub


Private Sub UpdateDbWithRS(ByRef rs As ADODB.Recordset)
    If Not rs Is Nothing Then
        If CurrentProject.Connection.State = adStateOpen Then CurrentProject.Connection.Close

        Set conn = New ADODB.Connection
        conn.Open CurrentProject.Connection.ConnectionString
        rs.ActiveConnection = conn

        If rs.Supports(adUpdateBatch) Then
            rs.UpdateBatch

            If Not conn Is Nothing Then
                If conn.State = adStateOpen Then conn.Close
                Set conn = Nothing
            End If
            If Not rs Is Nothing Then
                If rs.State = adStateOpen Then rs.Close
                Set rs = Nothing
            End If
        End If
    End If
End Sub

      



With the above code, I was able to Add a Record to my Recordset and make sure it doesn't show up in my database table. Then when I executed UpdateDbWithRS the Record that I added to the Recordset earlier was moved to my database table.

The biggest changes I had to make to your code was to change conn.Open CurrentProject.Connection

to conn.Open CurrentProject.Connection.ConnectionString

, add code If CurrentProject.Connection.State = adStateOpen Then CurrentProject.Connection.Close

to fix the error I was getting about a connection already opened. Then the last biggest change I made was replacing CursorType adOpenStatic

with adOpenForwardOnly

. I'm not sure if the last change is really necessary, but I used it based on a disabled RecordSet example I found on this Microsoft support site .

+1


source


When you use a disabled recordset, you do not get the benefit of automatically updating table changes. To save the data, you need to run SQL Update and Insert Statement.



0


source


First of all, your code looks perfect and should work, but ...

Solution 1

In my experience, I would advise to forget about this functionality. I was struggling with the same problem a few years ago. I haven't found any solution, but I'm pretty sure that the access database used in a multi-user environment cannot be updated because the Jet / ACE mechanism does not allow a static recordset to be updated when another user has made changes at that time (changes are rejected ).

I solved this problem by using a "temporary table" associated with the form:

DELETE * FROM ~TableName;
INSERT INTO ~TableName SELECT * FROM TableName;

      

The user can edit the records until the form is open. In Form_Unload, I run the request like this:

UPDATE t1 SET Field1 = t2.Field1,
Field1 = t2.Field2 ... and so on
FROM TableName As t1 INNER JOIN ~TableName AS t2 ON t1.Key = t2.Key

      

Note that insertion and deletion of records (if permitted) must be handled separately.

Solution2

Use a dynamic cursor and do not detach the recordset from the database;) Catch the changes using the Form.Dirty Property .

0


source


None of your codes have anything to do with DISCONNECTED RECORDSETS. Your records are connected. The disabled recordset can be saved to a file as xml or binary. There is no underlying database.

Please note that we are doing a disabled recordset.

Sub Randomise
    Randomize 
    Set rs = CreateObject("ADODB.Recordset")
    With rs
        .Fields.Append "RandomNumber", 4 

        .Fields.Append "Txt", 201, 5000 
        .Open
        Do Until Inp.AtEndOfStream
            .AddNew
            .Fields("RandomNumber").value = Rnd() * 10000
            .Fields("Txt").value = Inp.readline
            .UpDate
        Loop
        .Sort = "RandomNumber"
        Do While not .EOF
            Outp.writeline .Fields("Txt").Value

            .MoveNext
        Loop
    End With
End Sub

      

Here are the states

ConnectionState

The ConnectionState enumeration is used to identify the state of a connector space object. The CSEntry.ConnectionState property contains one of the values ​​in this enumeration.

Connected

A connector space object is connected to a meta object.

Explicitly bound

The connector space object is explicitly linked by a member of the MIISAdmins or MIISOperators group to a meta object from the account collector side.

Disabled

The connector space object is not connected to the meta object, but may be a candidate for future connection to the meta object.

DisconnectedByFilter

A connector space object has been disabled by connector filter rules.

Explicitly disabled The connector space object is not connected to a meta-object and will not be a candidate for a future connection to a meta-like object. Placeholder The connector feature exists implicitly in the linked directory, but has not been imported.

-4


source







All Articles