DGM
DGM

Reputation: 26979

Can I wrap an Access form with a transaction?

I want to make a form the essentially creates an invoice, but using some other related data as inputs or limits; In the process of adding items to the invoice, I need to reduce the items in another table. Since the user will enter several items at a time, I'd like to issue a "START TRANSACTION" when the form loads, and then do a "COMMIT" when the form updates. Thus, if they cancel the form, the other related tables (shown via subforms) would roll back to the previous values.

Upvotes: 2

Views: 2566

Answers (3)

Andrius Solopovas
Andrius Solopovas

Reputation: 1057

I have figured it out its possible to have it on bound forms. Everything you need to assign variable that contain an ID number on change event of any of the parent control. Than you need to transmit that ID value into the subform connected field and perform transaction on both forms the primary and the subform. Here is the example of how I did it.

Primary Form VBA

Option Compare Database
Option Explicit

Private boolFrmDirty As Boolean
Private boolFrmSaved As Boolean

Private Sub EmpolyeesID_Change()
Dim ordID As Integer
Dim subFormOrdID As Object

Set subFormOrdID = Forms!Order.OrderInstallation.Form!OrderID

ordID = Me.Form!OrderID

subFormOrdID.DefaultValue = ordID

End Sub

Private Sub Form_AfterDelConfirm(Status As Integer)
    If Me.Saved = False Then Me.Saved = (Status = acDeleteOK)
End Sub
Private Sub Form_AfterUpdate()
    Me.Saved = True
End Sub
Private Sub Form_Delete(Cancel As Integer)
    If Me.Dirtied = False Then DBEngine.BeginTrans
    Me.Dirtied = True
End Sub
'Check if form has got new values in it
Private Sub Form_Dirty(Cancel As Integer)
    If Me.Dirtied = False Then DBEngine.BeginTrans
    Me.Dirtied = True
End Sub
'Open Form as a Record Set and set the variables for it
Private Sub Form_Open(Cancel As Integer)
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Set db = CurrentDb
    Set rs = db.OpenRecordset("SELECT * FROM Orders", dbOpenDynaset, dbAppendOnly)
    Set Me.Recordset = rs
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Dim msg As Integer
    If Me.Saved Then
        msg = MsgBox("Do you want to commit all changes?", vbYesNoCancel)
        Select Case msg
            Case vbYes
                DBEngine.CommitTrans
            Case vbNo
                DBEngine.Rollback
            Case vbCancel
                Cancel = True
        End Select
    Else
        If Me.Dirtied Then DBEngine.Rollback
    End If
End Sub

Public Property Get Dirtied() As Boolean
    Dirtied = boolFrmDirty
End Property

Public Property Let Dirtied(boolFrmDirtyIn As Boolean)
    boolFrmDirty = boolFrmDirtyIn
End Property

Public Property Get Saved() As Boolean
    Saved = boolFrmSaved
End Property

Public Property Let Saved(boolFrmSavedIn As Boolean)
    boolFrmSaved = boolFrmSavedIn
End Property

Private Sub ProductID_AfterUpdate()
'Calculations of VAT and Floor Price
Dim clcVAT As Integer
Dim sqlQry As String
Dim instID As Integer

instID = Me.Form!ProductID.Value

sqlQry = "SELECT Products.Price FROM Products WHERE Products.ProductID =" & instID & ""

Me.flPrice.RowSource = sqlQry

End Sub

Sub Form VBA 

Option Compare Database
Option Explicit
'Transaction for sub-form
Private Sub Form_Open(Cancel As Integer)
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Set db = CurrentDb
    Set rs = db.OpenRecordset("SELECT * FROM OrderInstallation")
    Set Me.Recordset = rs
End Sub
Private Sub Form_AfterUpdate()
    Dim emplID As Object
    Dim cstmID As Object
    Dim prdcID As Object
    Dim DataArray As Variant
    Dim RqrdFieldErorr As String
    Dim qry As String

    Set emplID = Me.Parent!EmpolyeesID
    Set cstmID = Me.Parent!CustomerID
    Set prdcID = Me.Parent!ProductID

    If IsNull(emplID.Value) Or IsNull(cstmID.Value) Or IsNull(prdcID.Value) Then
        MsgBox ("Please enter select required fields first")

        Else
    End If
End Sub
'Restrict updates of Installation subform if Employee, Customer and Product is not selected
Private Sub InstallationID_AfterUpdate()
    Dim instID As Integer
    Dim instPrice As Integer
    Dim strQry As String

    ' Create query based on InstallationID value
    instID = InstallationID.Value
    strQry = "SELECT Installation.Price, Installation.InstallationID FROM Installation WHERE Installation.InstallationID =" & instID & ""
    Me.Price.RowSource = strQry
End Sub

Upvotes: 0

Carlos
Carlos

Reputation: 11

Yes it can be done, to take control over the transaction in the form you need use this code:

Private Sub Form_Open(Cancel As Integer)
    Set Me.Recordset = CurrentDb.OpenRecordset("NAME_OF_YOUR_TABLE_OR_QUERY")
End Sub

After that, you can use DBEngine to control the transaction.

It work for me (Im using Access 2007)

Note: If you insert a new record using the form interface it is visible when the Form_AfterInsert event is raised, therefore you can use DbEngine.Rollback in that event to undo the changes.

Upvotes: 1

Tony Toews
Tony Toews

Reputation: 7882

Can't be done using bound forms. You could use temporary tables to store the data and then update the main tables. A bit of a kludge but I've done that in the past.

See the TempTables.MDB page at my website which illustrates how to use a temporary MDB in your app.

Upvotes: 3

Related Questions