Next Available Number that includes missing gap numbers (1 Viewer)

JMongi

Active member
Local time
Yesterday, 19:01
Joined
Jan 6, 2021
Messages
802
I'm working on a little app to assign and track our drawing numbers. As such, our current drawings are going to have some gaps in the drawing number scheme.
I can use a Dmax to find the greatest number and increment that. But, that won't do much for filing in gaps of missing numbers. I'm doing reading on various numeric functions in VBA but thought I would throw this out to you VBA experts! :)

As a simplified clarifying example, I might have the root drawing numbers of:

00001
00002
00003
00010
00015

Using DMax plus increment would start me at 00016 and the app would never fill in 00004, etc.
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 00:01
Joined
Sep 12, 2006
Messages
15,651
I would ignore the old gaps, and carry on from the new number.

Rather than use a dmax, I would store the next number in a table somewhere, so you can start a new sequence if you ever have the need.

If you want to fill the gaps, either enter some dummy records or renumber the records, but that is likely to affect other tables in the database.
 

plog

Banishment Pending
Local time
Yesterday, 18:01
Joined
May 11, 2011
Messages
11,643
1. Why? What hardship does a gap create?

2. "00003" doesn't look like a number--numbers don't have leading zeroes. Are you storing it as a number or text?

3A. Method 1 is to load all the numbers into a recordset ordered numerically, iterate through the whole thing and make sure each number is 1 more than the prior one.

3B. Method2 is to create a table of of numbers that will exceed the highest possible ID, then create a query from that table to your ID table, show all from the Number table and then show records where the ID value is NULL.
 

JMongi

Active member
Local time
Yesterday, 19:01
Joined
Jan 6, 2021
Messages
802
Just to clarify, these are not table ID numbers at all. These are unique drawing numbers. We have gaps because we've never really had a great system for managing drawings. I don't even know how large the gaps will be. It's certainly easier to ignore them but I'm investigating NOT ignoring them.

@gemna-the-husky - Why avoid DMax?

@plog - Technically these would be strings because of the need for leading zeros. An Example Drawing number would be "FD-00056-01"
 
Last edited:

sxschech

Registered User.
Local time
Yesterday, 16:01
Joined
Mar 2, 2010
Messages
792
Are you incrementing like this?
"FD-00056-01"
"FD-00056-02"
"FD-00056-03"

If so, this function should help.
Code:
Function RegexIncrement(ByVal NumToIncrement As String, Optional sepchar As String = "-")
'Increment a text string number by 1
'(add 1 to the number)
'(add one to the number)
'and keep any leading zeroes.
'To keep leading zeroes, split out the numeric from the text
'count number of characters in the number and use that in
'the format function when concatenating back with the text
'Original code did not require breaking string up, but in
'that case, it did not preserve the leading zeroes
'Post #5:
'https://www.ozgrid.com/forum/forum/help-forums/excel-vba-macros/144719-increment-number-within-variable-length-alphanumeric-string
'
'https://answers.microsoft.com/en-us/msoffice/forum/all/repeat-function/6a6142bc-6fae-403c-af5d-ca471c13ced4
'20181126
'Added optional sepchar so that can keep leading zeroes
'since now also using this function on numbers that contain
'space rather than dash between text and number with a
'leading zero
'20200115
    Dim x As Variant
    Dim z As Long
    Dim i As Long
    Dim stAlpha As String
    Dim stLeadZero As String
    Dim stLeadZeroFormat As String
   
    stAlpha = Left(NumToIncrement, InStrRev(NumToIncrement, sepchar))  '"-"))
    stLeadZero = Mid(NumToIncrement, InStrRev(NumToIncrement, sepchar) + 1) '"-") + 1)
    stLeadZeroFormat = String(Len(Mid(NumToIncrement, InStrRev(NumToIncrement, sepchar) + 1)), "0") '"-") + 1)), "0")
   
    With CreateObject("VBScript.RegExp")
        .Global = True
        .IgnoreCase = False
        .Pattern = "[0-9]+"
            For Each x In .Execute(stLeadZero)
            RegexIncrement = Replace(stLeadZero, x, x + 1)
            Next x
    End With
    RegexIncrement = stAlpha & Format(RegexIncrement, stLeadZeroFormat)
End Function

You could then use a recordset and edit/append the incremented data to fill in the gaps.
 

JMongi

Active member
Local time
Yesterday, 19:01
Joined
Jan 6, 2021
Messages
802
No, I just wanted to give an example of the full drawing number and that it is technically a string not a number.

The part that is incremented is the 5 digit middle part.
 

sxschech

Registered User.
Local time
Yesterday, 16:01
Joined
Mar 2, 2010
Messages
792
I imagine you can modify the code to fit your numbering scheme by passing in up to the portion that needs incrementing and then concatenate it back together once incremented
 
Last edited:

Cotswold

Active member
Local time
Today, 00:01
Joined
Dec 31, 2020
Messages
526
Why not just add all drawing numbers? Presumably the blanks are drawing numbers that haven't been used. So just filter out any drawings without a title, revision or issued flag. When a drawing number is used, just add a title or an issued flag and it will appear as you want it to.
 

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 19:01
Joined
Feb 19, 2002
Messages
43,257
I would not attempt to fill the gaps.
 

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 19:01
Joined
Feb 19, 2002
Messages
43,257
Also, I wouldn't use the drawing number as the PK. When you use "smart" codes as the PK that tends to come back to haunt you. Use an autonumber as the PK and therefore the FK to all other tables.
 

JMongi

Active member
Local time
Yesterday, 19:01
Joined
Jan 6, 2021
Messages
802
@Pat Hartman - Definitely true. I think an assumption got made somewhere in the thread that I was talking about PKs but I am not.
@Cotswold - That is an interesting suggestion, I never thought of creating 99,999 records in advance. Interesting concept.
@sxschech - Thanks for the code reference!

It seems the consensus is that trying to fill in any existing gaps programmatically is not worth the trouble.
 

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 19:01
Joined
Feb 19, 2002
Messages
43,257
I would NOT advise adding "blank" records. That just gives them other ways to make errors. Plus you don't actually know in advance how many drawings you need for a given project.
 

JMongi

Active member
Local time
Yesterday, 19:01
Joined
Jan 6, 2021
Messages
802
@Pat Hartman - I wasn't planning on it, but it was a novel idea.

I don't like to implement code I don't personally understand so I wrote my own functions for incrementing a string full of numbers including leading zeroes.

C-like:
Function LeadingZeroIncrement(ByVal NumToIncrement As String) As String
'This function takes a number with leading zeroes in string format and increments it by 1
Dim intNumDigits, intDwgNum, intStringLength As Integer
Dim strLeadingZero, strAfterZero As String

'Determine the length of the inputted string, the numeric value and it's string length
intStringLength = Len(NumToIncrement)
intDwgNum = Val(NumToIncrement)
intNumDigits = Len(intDwgNum)

'Use the preceding information to separate the leading zeros, increment the number and concatenate
strLeadingZero = Left(NumToIncrement, intStringLength - intNumDigits)
strAfterZero = Right(NumToIncrement, intNumDigits)
intDwgNum = intDwgNum + 1
LeadingZeroIncrement = strLeadingZero & intDwgNum
 
Last edited:

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 19:01
Joined
Feb 19, 2002
Messages
43,257
I wasn't planning on it, but it was a novel idea.
Good.

You should be keeping the sequence number as a NUMBER not as a string. That way you can use simple arithmetic to increment the value.

Here's an example that shows how to build a "friendly" ID and how to build a sequence number for details.
 

Attachments

  • CustomSequenceNumber20210303.zip
    93.7 KB · Views: 294

JMongi

Active member
Local time
Yesterday, 19:01
Joined
Jan 6, 2021
Messages
802
Looks like I'm doing very similarly to this form, but I was unaware of Format(Me.txtSeqNum, "000")
 

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 19:01
Joined
Feb 19, 2002
Messages
43,257
The number of zeros controls the length of the fixed numeric portion. So "00000" makes strings of 5 characters in length. "000" makes three character strings. Use the number of zeros that will provide enough room for what you want to accommodate but which is not so long that you have lots of extra zeros.
 

theDBguy

I’m here to help
Staff member
Local time
Yesterday, 16:01
Joined
Oct 29, 2018
Messages
21,467
Looks like I'm doing very similarly to this form, but I was unaware of Format(Me.txtSeqNum, "000")
Hi. I also like using the Format() function to provide leading zeroes. However, please understand that it doesn't necessarily limit the size of your string. For example, if you use Format(99999, "000"), you won't get 999 back; instead, you will still get 99999.
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 07:01
Joined
May 7, 2009
Messages
19,230
you don't need to fill the gap?
go to Engineering and ask for their Drawing number list (in excel format)
and import them.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Yesterday, 18:01
Joined
Feb 28, 2001
Messages
27,167
You've gotten some other feedback on this, but here is the way I see it.

Whoever dealt with these drawing numbers before you didn't care enough to address the gaps. They left the gaps unchanged long enough for the problem to fall into your lap and nobody cared. Why should you allow yourself to lose even a half a second of sleep over it?
 

MarkK

bit cruncher
Local time
Yesterday, 16:01
Joined
Mar 17, 2004
Messages
8,180
Gaps in a series assumes there is a definition of the series without gaps. To find gaps, iterate through the pristine series, and compare each element in the series you are testing. The first time they mismatch (assuming there are no duplicates in the test series) there is one missing. Here's a simple example...
Code:
Function GetFirstMissingLong(Table As String, Field As String) As Long
    Dim sql As String
    Dim i As Long
   
    ' construct SQL
    sql = Join(Array("SELECT", Field, "FROM", Table, "ORDER BY", Field))
   
    With CurrentDb.OpenRecordset(sql)       ' open recordset of series to test
        For i = 1 To DMax(Field, Table)     ' iterate thru pristine series
            If i <> .Fields(Field) Then     ' if there is no match
                GetFirstMissingLong = i     ' then we have our missing number
                Exit For
            End If
            .MoveNext
        Next
    End With
End Function
 

Users who are viewing this thread

Top Bottom