0
votes

I'm very much an Visual Basic noob... I'm trying to create a button on my Access form that can create a record and re-sequence my non-auto-incremented Primary Key to insert the record where I want it in the record list.

Currently, to do this I 1) Open the table, 2) use an AutoHotKey keyboard macro to manually edit the Primary Key number from the last record to where I want to insert my new record, 3) create a new record (with an appropriate value in my Primary Key column) at the bottom of the list, then 4) Right-click the column and "Sort from smallest to largest", and finally 5) use a second AutoHotKey macro to re-sequence the Primary Key from the new record to the end of the list.

I'd like a Command Button that will allow me to do the same with just one click.

The database currently has 897 records- adding a new record at #185 using the method I currently use seems tedious when it seems a FOR / NEXT (Step -1) Loop in VBA would be so much more efficient.

Some names I use:

  • Form Name: [Anime Input Form]
  • Table Name: [DVDs and Blu Rays]
  • Primary Key Name: [AIN#]
2

2 Answers

0
votes

You can do like this - where the field is named Priority and you are using the AfterUpdate event of this:

Private Sub Priority_AfterUpdate()

    Dim rst             As DAO.Recordset
    Dim lngId           As Long
    Dim lngPriorityNew  As Long
    Dim lngPriorityFix  As Long

    ' Save record.
    Me.Dirty = False

    ' Prepare form.
    DoCmd.Hourglass True
    Me.Repaint
    Me.Painting = False

    ' Current Id and priority.
    lngId = Me!Id.Value
    lngPriorityFix = Nz(Me!Priority.Value, 0)
    If lngPriorityFix <= 0 Then
        lngPriorityFix = 1
        Me!Priority.Value = lngPriorityFix
        Me.Dirty = False
    End If

    ' Rebuild priority list.
    Set rst = Me.RecordsetClone
    rst.MoveFirst
    While rst.EOF = False
        If rst!Id.Value <> lngId Then
            lngPriorityNew = lngPriorityNew + 1
            If lngPriorityNew = lngPriorityFix Then
                ' Move this record to next lower priority.
                lngPriorityNew = lngPriorityNew + 1
            End If
            If Nz(rst!Priority.Value, 0) = lngPriorityNew Then
                ' Priority hasn't changed for this record.
            Else
                ' Assign new priority.
                rst.Edit
                    rst!Priority.Value = lngPriorityNew
                rst.Update
            End If
        End If
        rst.MoveNext
    Wend

    ' Reorder form and relocate record.
    Me.Requery
    Set rst = Me.RecordsetClone
    rst.FindFirst "Id = " & lngId & ""
    Me.Bookmark = rst.Bookmark

    ' Present form.
    Me.Painting = True
    DoCmd.Hourglass False

    Set rst = Nothing

End Sub
0
votes

Well, in spite of the protests, I've come up with a solution. Is it bad practice? Probably- But my database is mine to fiddle with, and I'll set it up the way I want it.

Maybe at some point, if the collection gets so large that this method becomes inefficient, I can always add a new column, make it auto-increment, and set that as the primary key and go from there.

Until then...

Private Sub Command101_Click()

    Dim CurrentRecord As Integer
    Dim LastRecord As Integer
    Dim NewRecord As Integer

'Pause screen and show it's busy
        DoCmd.Hourglass True
        Me.Painting = False

'just create new record at end of list if that's where you are
    If AIN = DMax("AIN", "DVDs and Blu Rays") Then
        CurrentRecord = AIN
        DoCmd.GoToRecord , , acNewRec
        AIN = CurrentRecord + 1
        DoCmd.RunCommand acCmdSaveRecord

    Else
'Save the current record value
        CurrentRecord = AIN

'Create new record at the end of list and give it a new record number
        DoCmd.RunCommand acCmdRecordsGoToLast
        LastRecord = AIN
        DoCmd.GoToRecord , , acNewRec
        AIN = LastRecord + 1
        DoCmd.RunCommand acCmdSaveRecord

'Increment all records by one working backwards from end to current record
        While AIN <> CurrentRecord
            AIN = AIN + 1
            DoCmd.RunCommand acCmdSaveRecord
            DoCmd.GoToRecord , , acPrevious
        Wend

'Return to last record and insert it after the current record
        DoCmd.RunCommand acCmdRecordsGoToLast
        AIN = CurrentRecord + 1
        DoCmd.RunCommand acCmdSaveRecord

'Unpause screen
        Me.Painting = True
        DoCmd.Hourglass False

'Refresh the form so new record is in correct location and open it
        Me.Requery
        DoCmd.GoToRecord , , acGoTo, CurrentRecord + 1
    End If
End Sub