How to "copy" data and "pasting" to the acNewRec (1 Viewer)

DBApprentice

On Error GoTo AWF *****:
Local time
Yesterday, 23:22
Joined
Dec 24, 2018
Messages
150
Guys,

I have a small DB and it has a form where users can input information. Since sometimes they have to input the basic information all the time, they asked me if it would be possible to have a "copy" of a certain record to paste it on the acNewRec, so they can change only the few things that differs them from the previous records.

Now, I believe I could:
- Put a button or check box called "Template Me" or something like that.
- If the user click on that control, it will save data to the underlying query and also will save it to a temp table or query to write it the data there after saving the records
- On a new record the button "Paste from previous record", or something like that, would be activated and the user can click it to paste the data from the temp table/query.
-The temp table/query would be cleared once the user unload/close the form.

I was wondering what would be the best solution and I would like to know if you have any comments in case you have dealt with such a thing (I am quite sure you did!), what pitfalls I should avoid. ;)

Thanks for your time!
 

theDBguy

I’m here to help
Staff member
Local time
Yesterday, 19:22
Joined
Oct 29, 2018
Messages
21,455
Hi. Take a look at the RunCommand method of the DoCmd object and the following arguments: acCmdSelectRecord, acCmdCopy, and acCmdPasteAppend


Hope it helps...
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 10:22
Joined
May 7, 2009
Messages
19,229
you mean carry over the last record.
the code is not mine although HasProperty edited.
Code:
Option Compare Database
Option Explicit

Public Function subCarryOver(frm As Form, strErrMsg As String, ParamArray avarExceptionList()) As Long
On Error GoTo err_handler
    'Purpose: Carry over the same fields to a new record, based on the last record in the form.
    'Arguments: frm               = the form to copy the values on.
    '           strErrMsg         = string to append error messages to.
    '           avarExceptionList = list of control names NOT to copy values over to.
    'Return:    Count of controls that had a value assigned.
    'Usage:     In a form's BeforeInsert event, excluding Surname and City controls:
    '               Call CarryOver(Me, strMsg, "Surname", City")
    Dim rs As DAO.Recordset         'Clone of form.
    Dim ctl As Control              'Each control on form.
    Dim strForm As String           'Name of form (for error handler.)
    Dim strControl As String        'Each control in the loop
    Dim strActiveControl As String  'Name of the active control. Don't assign this as user is typing in it.
    Dim strControlSource As String  'ControlSource property.
    Dim lngI As Long                'Loop counter.
    Dim lngLBound As Long           'Lower bound of exception list array.
    Dim lngUBound As Long           'Upper bound of exception list array.
    Dim bCancel As Boolean          'Flag to cancel this operation.
    Dim bSkip As Boolean            'Flag to skip one control.
    Dim lngKt As Long               'Count of controls assigned.

    'Initialize.
    strForm = frm.Name
    strActiveControl = frm.ActiveControl.Name
    lngLBound = LBound(avarExceptionList)
    lngUBound = UBound(avarExceptionList)

    'Must not assign values to the form's controls if it is not at a new record.
    If Not frm.NewRecord Then
        bCancel = True
        strErrMsg = strErrMsg & "Cannot carry values over. Form '" & strForm & "' is not at a new record." & vbCrLf
    End If
    'Find the record to copy, checking there is one.
    If Not bCancel Then
        Set rs = frm.RecordsetClone
        If rs.RecordCount <= 0& Then
            bCancel = True
            strErrMsg = strErrMsg & "Cannot carry values over. Form '" & strForm & "' has no records." & vbCrLf
        End If
    End If

    If Not bCancel Then
        'The last record in the form is the one to copy.
        rs.MoveLast
        'Loop the controls.
        For Each ctl In frm.Controls
            bSkip = False
            strControl = ctl.Name
            'Ignore the active control, those without a ControlSource, and those in the exception list.
            If (strControl <> strActiveControl) And HasProperty(ctl, "ControlSource") Then
                For lngI = lngLBound To lngUBound
                    If avarExceptionList(lngI) = strControl Then
                        bSkip = True
                        Exit For
                    End If
                Next
                If Not bSkip Then
                    'Examine what this control is bound to. Ignore unbound, or bound to an expression.
                    strControlSource = ctl.ControlSource
                    If (strControlSource <> vbNullString) And Not (strControlSource Like "=*") Then
                        'Ignore calculated fields (no SourceTable), autonumber fields, and null values.
                        With rs(strControlSource)
                            If (.SourceTable <> vbNullString) And ((.Attributes And dbAutoIncrField) = 0&) _
                                And Not (IsCalcTableField(rs(strControlSource)) Or IsNull(.Value)) Then
                                If ctl.Value = .Value Then
                                    'do nothing. (Skipping this can cause Error 3331.)
                                Else
                                    ctl.Value = .Value
                                    lngKt = lngKt + 1&
                                End If
                            End If
                        End With
                    End If
                End If
            End If
        Next
    End If

    subCarryOver = lngKt

Exit_Handler:
    Set rs = Nothing
    Exit Function

err_handler:
    strErrMsg = strErrMsg & Err.Description & vbCrLf
    Resume Exit_Handler
End Function

Private Function IsCalcTableField(fld As DAO.Field) As Boolean
    'Purpose: Returns True if fld is a calculated field (Access 2010 and later only.)
On Error GoTo ExitHandler
    Dim strExpr As String

    strExpr = fld.Properties("Expression")
    If strExpr <> vbNullString Then
        IsCalcTableField = True
    End If

ExitHandler:
End Function

Public Function HasProperty(obj As Object, strPropName As String) As Boolean
    'Purpose: Return true if the object has the property.
    Dim varDummy As Variant
    
    On Error GoTo err_handler
    varDummy = obj.Properties(strPropName)
    HasProperty = (Err.Number = 0)
    If HasProperty Then _
        varDummy = obj.ControlSource
    HasProperty = True
    Exit Function
err_handler:
    HasProperty = False
End Function

call it on the Click event of the button:
Code:
Private Sub button_Click()
    Me.Dirty = False
    DoCmd.GoToRecord acActiveDataObject, , acNewRec
    Call subCarryOver(Me.Form, "", "")
End Sub
 

DBApprentice

On Error GoTo AWF *****:
Local time
Yesterday, 23:22
Joined
Dec 24, 2018
Messages
150
Thank you all for the invaluable and usual support!

I will study all options and see what i will apply.
 

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 22:22
Joined
Feb 19, 2002
Messages
43,233
Most of the time when you want to copy data from the "previous" row, it is because you have not designed the tables correctly. You might want to examine the possibility of breaking the one table into two tables. The "parent" table contains the common fields that will repeat for the set of records and the "child" table will contain the values that are normally different for each row.
 

Users who are viewing this thread

Top Bottom