That's not how it works. It's simple enough to set up a test table that
consists of a single number field, and to use the formula I provided as the
default value in the text box bound to that field. Scroll through the
records (the mouse wheel can do that quickly) until you get to 101. Change
the value of the field in that record to 100019. Create a new record. The
number is 100020.
I have also used DMax + 1 in expressions involving text fields in order to
get sequences such as RPT-06-01, RPT-06-02. I use the form's Current event
rather than the default value to construct that number, but the principle is
the same. If YourID is a text field, it seems I need to pad the number with
zeros to get it to work. For instance:
Private Sub Form_Current()
Dim strID As String
Dim varID As Variant
If Me.NewRecord Then
strID = "YourID Like """ & "*"""
varID = Nz(DMax("YourID", "tblYourTable", strID))
Me.YourID = Format(Val(Right(varID, 3)) + 1, "000")
End If
End Sub
From what I can tell I need to format for the maximum number of digits.
However, if I am using just a number, I can see no reason to store it in a
text field.
There are provisions for using the DMax system in a multi-user database.
One way is explained here:
http://www.rogersaccesslibrary.com/download3.asp?SampleName=AutonumberProblem.mdb
I have worked out other methods, too.
I have tested the system extensively. It works. If you can identify an
instance in which it does not work, I would very much like to see an
example.
The person who posted originally seems to have over-complicated the problem.
I asked for clarification, in case I had misunderstood, but received none.
As to using a query to obtain the next number in a sequence, maybe that is
more complicated, but if I need to increment a number I will opt for the
simplest way of doing so. If I need to use a wrench to drive nails, maybe
it will be possible to complete the building project, but it will be much
harder.
John said:
Because the underlying table field is text DMax("[YourField]","YourTable")
as far as I can tell brings say 99 as the largest previous number instead
of say 100020 (text comparison instead of numeric comparison)and then adds
one to it thus creating a duplicate id 100 which is already in the table.
Regards
BruceM said:
How about =Nz(DMax("[YourField]","YourTable"))+1 as the default value for
a text box bound to YourField? Or am I missing your point? Incrementing
numbers have been discussed extensively in this group.
ben said:
Dear All,
This reply is more for the general public than for this specific
issue.
Incrementing a field, creating a sequence or adding one to a
number in a query are all things that Access does not do well. Oracle
has a sequence function (I believe) but there is nothing in Access.
What's more, creating such a function is not easy. I have sucessfully
created two versions of an Increment() function and thought I'd share
them with you so that anyone searching for "Access Increment sequence
query" will find it - including me!
So here's the simplest & fastest version:
Public Function RunOnceInc(Optional someField As Variant) As Long
Static val As Long
If IsMissing(someField) Then 'reset
val = 0
End If
runOnceInc = val
val = val + 1
End Function
Looks simple huh? The trick is to run this function in your query
twice. Let's say we have a field called "test" in our query that will
generate an index number increment with each record. The field should
look like this:
test: runOnceInc() + runOnceInc([AnotherField])
The query will call the function with no parameters ONLY ONCE before it
does anything else. This resets the internal increment variable from
the last time you ran this function. The second time the function is
called it takes a field as a parameter (any field) which forces it to
be called once for every row.
This function works fine for Update or Insert type queries, but has a
serious draw back when it comes to Select queries. The function is
re-evaluated every time you re-display the results of the query (i.e.
every time another window is dragged on top of it or the scroll bar is
moved). This is obviously no good, but the solution (to follow) is a
little more bulky in terms of memory usage. For this reason, I have
included the "unsafe" version for use in large Update or Append type
queries.
For select queries we need to store the generated increment value in a
Map against some unique identifier for that row. Here is the code:
Public Function SafeInc(Optional UID As String) As Long
Static val As Long
Static seq As New Collection
If IsMissing(UID) Or UID = "" Then 'reset
Set seq = New Collection
val = 0
Else
If collectionHas(seq, UID) Then
inc = seq.Item(UID)
Else
seq.Add val, UID
inc = val
val = val + 1
End If
End If
End Function
Here I used a VB Collection to store each sequance value and
implemented the CollectionHas() function to make it work a bit like a
Map. I'll include that function a little later, but first to talk about
the SafeInc(). It obviously requires a unique identifier for each row,
but that is not normally hard to find or to create. Here's an example
of you it should be used:
test: safeInc() + safeInc([surname] & " " & [firstname])
If you don't have a Unique ID handy, you can create one from whatever
fields you like. I suppose you could even concatenate all of your
fields together. This in-memory Map object could obviously get pretty
big if you are using a large dataset. For select queries however, I'd
imagine that large datasets would become difficult to handle anyway.
Here is the CollectionHas() function:
Public Function collectionHas(coll As Collection, key As Variant) As
Boolean
collectionHas = False
On Error GoTo fail
Dim tmp As Variant
tmp = coll.Item(key)
collectionHas = True
fail:
End Function
This function simply catches the "index not found" error and returns
false instead of true. Now, I actually use a modified version of this
function because I also call it directly from other VB functions and if
you call this from INSIDE another error handling block (after the
jumpto label) the NEW error trapping block kills the old error. It's a
little difficult to explain and probably beyond the scope of this issue
- but I felt I should mention this in case people start using this
function from within an error trap in code and then wonder why their
error disapears. I modified this function to copy any pre-existing
error object onto an explicit stack structure and then pop it off again
at the end. I'd be happy to supply this code to anyone who is
interested.
I hope this will help someone. I spent a long time searching for this
code before experimenting myself. Lets hope a latr version of Access
has a nice, quick, efficient, sequence or increment function built in.
Regards,
Ben.