5. But I Need it for Multiple Forms; I Can’t Have Several VBA.Collection Instances!
The problem with the previous example is that it’s OK since you only need it in one place but if you will have several places where it is used, you now have to qualify the instance of VBA.Collection to each place – not insurmountable but too easy to get messy and hairy very fast.
However, there is a property we can use to get ourselves out of this problem and that is the AbsolutePosition property of the recordset. We can create a textbox, bind it to expression “=RowNumber()” and then create a function on the module behind the form that references the recordset:
Public Function RowNumber() As Variant
On Error Resume Next
If Me.NewRecord Then
If Me.Dirty Then
RowNumber = Null
Exit Function
End If
End If
With Me.RecordsetClone
.Bookmark = Me.Bookmark
RowNumber = .AbsolutePosition + 1
End With
If Err.Number Then
RowNumber = Null
End If
End Function
This requires no pre-knowledge of a primary key and only assumes that when you load the form initially, it is already sorted. Any records newly inserted will get the next bigger number. However, if you requery and it causes the newly inserted rows to be re-sorted, they will be now given a new number that relates to their actual position within the set, which can be either good or bad, depending on your specific requirements.
You might find it useful to ensure that the RowNumber() is called after insert of records, perhaps with this code:
Private Sub Form_AfterInsert()
'Assumes there's a textbox named txtRowNumber
'and it is bound to expression "=RowNumber()"
Me.txtRowNumber.Requery
End Sub
You also will find the code much easier to re-use, perhaps by packaging into a class module and thus encapsulate the implementation while sharing among several forms without worrying about VBA.Collections bloating since you are just using an innate property of the Recordset object.