Mike
Mike

Reputation: 35

Generate unique serial number incrementally

I am writing a vb.net program to generate a three digit serial number I will use in printing a barcode.

The requirements are the counter must count:

001 - 999, A00 - A99, B00 - B99, ..., Z00 - Z99

I cannot use the letters O and I

This code simply increments the value I pass to it by 1. I first check if the value is <=998 and if so return the value in 3 digits. I had to put this in a Try statement because passing the value 'A00' caused an error.

The code is still breaking once I hit Z99.

Problem: If the next serial number = Z90 and the user wants to print 35 barcodes I need to stop the operation before it begins and warn the user there are only 10 avail serial numbers remaining

Also, I am also hoping for advice on how I could have accomplished this in a better manner, any advice would be greatly appreciated

    Public Shared Function NextSerial(ByVal value As String) As String

    Try
        If value <= 998 Then
            value += 1
            Return ZeroPad(value, 3)
        End If

    Catch ex As Exception

    End Try
    Const chars As String = "ABCDEFGHJKLMNPQRSTUVWXYZ"
    Dim threenumber As String = ZeroPad(value, 3) 'ensure value is 3 digits.
    Dim alpha As String = threenumber.Substring(0, 1).ToUpper() ' 1st digit
    Dim beta As String = threenumber.Substring(1, 2) 'remaining two digits
    Dim newNumber As String
    Dim nextletter As String

    If beta = "99" Then
        beta = "00"
        nextletter = chars.Substring((chars.IndexOf(alpha, System.StringComparison.Ordinal) + 1), 1)
        newNumber = nextletter + beta
        Return newNumber

    Else
        beta += 1
        newNumber = alpha + ZeroPad(beta, 2)
        Return newNumber

    End If
End Function

Private Shared Function ZeroPad(ByVal number As String, ByVal toLength As Integer) As String
    ZeroPad = number

    'add the necessary leading zeroes to build it up to the desired length.
    Do Until Len(ZeroPad) >= toLength
        ZeroPad = "0" & ZeroPad
    Loop
End Function

Upvotes: 3

Views: 4647

Answers (3)

the_lotus
the_lotus

Reputation: 12748

I suggest you use integer for all your check and calculation and only convert to serial number for display. It'll be a lot easier to know how many serial number are remaining.

Your serial number is similar to integer except everything over 100 is a letter instead of a number.

Note: It's very important to add error checking, this assumes that all input are valid.

Module Module1

    Sub Main()

        Console.WriteLine(SerialNumber.ConvertSerialNumberToInteger("D22"))
        Console.WriteLine(SerialNumber.ConvertIntegerToSerialNumber(322))
        Console.WriteLine(SerialNumber.GetAvailableSerialNumber("Z90"))

        For Each sn As String In SerialNumber.GetNextSerialNumber("X97", 5)
            Console.WriteLine(sn)
        Next

        Console.ReadLine()

    End Sub

End Module

Class SerialNumber

    Private Const _firstPart As String = "ABCDEFGHJKLMNPQRSTUVWXYZ"

    Public Shared Function ConvertSerialNumberToInteger(ByVal serialNumber As String) As Integer

        Return (_firstPart.IndexOf(serialNumber(0)) * 100) + Integer.Parse(serialNumber.Substring(1, 2))
    End Function

    Public Shared Function ConvertIntegerToSerialNumber(ByVal value As Integer) As String

        Return _firstPart(value \ 100) & (value Mod 100).ToString("00")
    End Function

    Public Shared Function GetAvailableSerialNumber(ByVal serialNumber As String)

        Dim currentPosition As Integer
        Dim lastPosition As Integer

        currentPosition = ConvertSerialNumberToInteger(serialNumber)
        lastPosition = ConvertSerialNumberToInteger("Z99")

        Return lastPosition - currentPosition
    End Function

    Public Shared Function GetNextSerialNumber(ByVal serialNumber As String, ByVal amount As Integer) As List(Of String)

        Dim newSerialNumbers As New List(Of String)
        Dim currentPosition As Integer

        currentPosition = ConvertSerialNumberToInteger(serialNumber)

        For i As Integer = 1 To amount
            newSerialNumbers.Add(ConvertIntegerToSerialNumber(currentPosition + i))
        Next

        Return newSerialNumbers
    End Function

End Class

Upvotes: 0

theduck
theduck

Reputation: 2617

I think you can do this by assuming your first character is the 'hundreds' and converting to a number and incrementing:

Private Function NextSerial(value As String) As String
    Const chars As String = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"

    Dim numericValue As Integer = 100 * (chars.IndexOf(value.Substring(0, 1))) + Integer.Parse(value.Substring(1, 2))
    numericValue += 1

    Return chars.Substring(numericValue \ 100, 1) + (numericValue Mod 100).ToString.PadLeft(2, "0")
End Function

You should of course perform some error checking at the start of the function to make sure a valid serial number has been handed into the function. I would also put this function into a class and add functions such as isValid, SerialsRemaining and perhaps a function to retrieve a list of multiple serials.

Upvotes: 2

laylarenee
laylarenee

Reputation: 3284

I created constant strings that represent every available character in each digit position. I then used indexing to lookup the positions of the current serial number & moved one number forward to get the next serial. This will always provide the next serial until you run out of numbers.

Note: this code can easily be made more compact, but I left it as-is thinking it might be clearer.

Const charString1 As String = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
Const charString2 As String = "0123456789"
Const charString3 As String = "0123456789"

Public Function NextSerial(ByVal value As String) As String

    ' ensures the input is three chars long
    Dim threenumber As String = Right("000" & value, 3)

    Dim char1 As String = threenumber.Substring(0, 1)
    Dim char2 As String = threenumber.Substring(1, 1)
    Dim char3 As String = threenumber.Substring(2, 1)
    Dim char1Pos As Integer = charString1.IndexOf(char1)
    Dim char2Pos As Integer = charString2.IndexOf(char2)
    Dim char3Pos As Integer = charString3.IndexOf(char3)

    If char1Pos = -1 Or char2Pos = -1 Or char3Pos = -1 Then Throw New Exception("Invalid serial number format")

    ' move to next serial number
    char3Pos += 1

    If char3Pos > charString3.Length() - 1 Then
        char3Pos = 0
        char2Pos += 1
    End If
    If char2Pos > charString2.Length() - 1 Then
        char2Pos = 0
        char1Pos += 1
    End If
    If char1Pos > charString1.Length() - 1 Then Throw New Exception("Out of serial numbers!")

    Return charString1.Substring(char1Pos, 1) & charString2.Substring(char2Pos, 1) & charString3.Substring(char3Pos, 1)

End Function

Upvotes: 1

Related Questions