Macro to generate random serial number

dudumomo

Board Regular
Joined
Jun 3, 2014
Messages
65
Hi guys,

I need to generate some serial number to provide to our students and I'm looking for a macro to do it.

Ideally, I enter in cell A1 the number of key code to generate and it will generate those in the following format:
3XA7-BC6D-98EF
Can mix letter (Capital only) and number.
But should exclude 0 and O, 5 and S, and 1 and I
(Easier for them)

And cherry on the top, it keeps all the previously generated serial number to make sure it will not generate twice the same.

Do you have some idea to do that?

Thanks!
 
i've edit the line: "For lDivisor = 3 To 5" to "For lDivisor = Range("B1").Value To Range("D1").Value". But it can't work if i choose: 5,12,9 for example
 
Upvote 0

Excel Facts

Why does 9 mean SUM in SUBTOTAL?
It is because Sum is the 9th alphabetically in Average, Count, CountA, Max, Min, Product, StDev.S, StDev.P, Sum, VAR.S, VAR.P.
i've edit the line: "For lDivisor = 3 To 5" to "For lDivisor = Range("B1").Value To Range("D1").Value". But it can't work if i choose: 5,12,9 for example

Sorry I missed the need for those values to be read from the worksheet.

Try modifying this function...
Code:
Private Function sGenerateSerialNbr() As String
'--generates a random string meeting the specified
'    pattern TEST-"#####-#####-#####"
'  where the numbers represented by the group of x's are evenly
'  divisible by the values in specified cells
'
   Dim lDivisor As Long
   Dim rCell As Range
   Dim sReturn As String, sPart As String
   
   sReturn = "TEST"
   
   For Each rCell In ActiveSheet.Range("B1,C1,D1")
      sPart = lGenerateDivisibleNbr(lMin:=0, lMax:=9999, _
         lDivisor:=rCell.Value)
      If Len(sPart) = 0 Then
         sReturn = 0
         GoTo ExitProc
         Exit Function
      Else
         sReturn = sReturn & "-" & sPart
      End If
   Next rCell
   
ExitProc:
   sGenerateSerialNbr = sReturn
End Function
 
Upvote 0
Hi guys,

I'm jumping back on this thread, I'm using frequently this macro (Works great) but I want to add one feature on it.

It generates the serial numbers as expected and keep the records, but I want to be able to add 2 new fields (Product name in B3 and customer name in B5)

At generation step, it won't change anything (Still generate XX serial numbers), but in the sheet, records, it will not only keep the serial number generated, but also for which product and customer name.)

Doable?

Here is the macro I'm using

Code:
Sub MakeSerialNbrs()
'--generates a user specfied number of unique serial numbers
'  serial numbers meet criteria in function: sGenerateSerialNbr
'    eg: 3XA7-BC6D-98EF with excluded characters
'  newly generated serial nbrs are displayed on wksNewNbrs
'    and also appended to list of existing serial nbrs
'
 Dim bUniqueCodeFound
 Dim lNdx As Long, lSerialNbrsToMake As Long
 Dim lLastRowExisting As Long, lLoopCount As Long
 Dim rNewResults As Range
 Dim dctSerialNbrs As Scripting.Dictionary
 Dim sSerialNbr As String
 Dim vExisting As Variant, vNewSerialNbrs As Variant
 Dim wksNewNbrs As Worksheet, wksExistNbrs As Worksheet
  
 On Error GoTo ExitProc
  
 Set dctSerialNbrs = New Scripting.Dictionary
 Set wksNewNbrs = Sheets("Generator")
 Set wksExistNbrs = Sheets("Records")

 With wksNewNbrs
   lSerialNbrsToMake = .Range("B4").Value
   '--optional: clear value from A1
   .Range("B4").ClearContents
   '--location to write results
   Set rNewResults = .Range("A8")
   '--clear previous results
   Range(rNewResults, .Cells(.Rows.Count, rNewResults.Column)).ClearContents
   '--size 2d array to hold new results
   ReDim vNewSerialNbrs(1 To lSerialNbrsToMake, 1 To 1)
 End With

'--read existing serial numbers into dictionary
'  also validate there are no duplicates in existing nbrs
 With wksExistNbrs
   lLastRowExisting = .Cells(.Rows.Count, "A").End(xlUp).Row
   vExisting = .Range("A1:A" & lLastRowExisting).Value
   '--handle 0-1 existing items
   If Not IsArray(vExisting) Then vExisting = Array(vExisting)
   For lNdx = 1 To UBound(vExisting, 1)
      sSerialNbr = vExisting(lNdx, 1)
      If Len(sSerialNbr) <> 0 Then
         If Not dctSerialNbrs.Exists(sSerialNbr) Then
            dctSerialNbrs.Add sSerialNbr, lNdx
         Else
            MsgBox "Duplicate found in existing Serial Numbers:" _
               & sSerialNbr
            GoTo ExitProc
         End If
      End If
   Next
 End With

'--generate specified count of new serial numbers.
'  use dictionary to test each number is unique
 For lNdx = 1 To lSerialNbrsToMake
   bUniqueCodeFound = False
   '--prevent endless loop
   lLoopCount = 0
   Do Until bUniqueCodeFound Or lLoopCount > 10
      '--call function to get string meeting criteria
      sSerialNbr = sGenerateSerialNbr()
      If Not dctSerialNbrs.Exists(sSerialNbr) Then
         dctSerialNbrs.Add sSerialNbr, lNdx
         vNewSerialNbrs(lNdx, 1) = sSerialNbr
         bUniqueCodeFound = True
      End If
      lLoopCount = lLoopCount + 1
   Loop
 Next lNdx
   
'--write results to new range and append to existing list
 If lSerialNbrsToMake > 0 Then
   rNewResults.Resize(lSerialNbrsToMake).Value _
      = vNewSerialNbrs
   wksExistNbrs.Cells(lLastRowExisting + 1, "A") _
      .Resize(lSerialNbrsToMake).Value _
      = vNewSerialNbrs
 End If
 
ExitProc:
 If Err.Number <> 0 Then
   Set dctSerialNbrs = Nothing
   MsgBox Err.Number & "-" & Err.Description
 End If
End Sub

Private Function sGenerateSerialNbr() As String
'--generates a random string meeting the specified
'    pattern and character exclusions
'
   Dim bValidCodeFound As Boolean
   Dim lCode As Long, lPos As Long
   Dim sSerialNbr As String
   Const sPattern As String = "xxxx-xxxx-xxxx"
      
   For lPos = 1 To Len(sPattern)
      If Mid$(sPattern, lPos, 1) = "-" Then
         sSerialNbr = sSerialNbr & "-"
      Else
         bValidCodeFound = False 'reset
         Do Until bValidCodeFound
            '--get random nbr representing char code from "0" and "Z"
            lCode = Application.RandBetween(48, 90)
            
            '--test if lCode represents excluded char
            Select Case lCode
               Case 58, 59, 60, 61, 62, 63, 64 'exclude ":" to "@"
               Case 48, 79 'exclude 0,O
               Case 49, 73 'exclude 1,I
               Case 53, 83 'exclude 5,S
               Case Else:
                  bValidCodeFound = True
            End Select
         Loop
         sSerialNbr = sSerialNbr & Chr$(lCode)
      End If
   Next lPos
   
   sGenerateSerialNbr = sSerialNbr
End Function

Thank you!
 
Upvote 0
It generates the serial numbers as expected and keep the records, but I want to be able to add 2 new fields (Product name in B3 and customer name in B5)

At generation step, it won't change anything (Still generate XX serial numbers), but in the sheet, records, it will not only keep the serial number generated, but also for which product and customer name.)

Hello again,

To clarify, if the count of new numbers to generate in Cell B4 is 100, you want to use the same product and customer name (from B3 and B4) for all 100 new numbers. The product and customer will be added to columns B & C on both Generator and Records sheets. Is that correct?
 
Upvote 0
Hi!
To clarify a bit further, the best will be:
If in B4 got 100, to generate, it will simply generate them in Sheet "Generator" as currently, but in sheet "Records", it will add in columns B and C, the value located in Generator.B3 and B5 (Product and customer name) for all records generated.

But if need intermediary step (Columns B and C on both sheets), it's still okay.

Thanks!
 
Upvote 0
Here's a modified version of the Sub MakeSerialNbrs. Replace the version you have with this, but leave the Function sGenerateSerialNbr unchanged.

Code:
Sub MakeSerialNbrs()
'--generates a user specfied number of unique serial numbers
'  serial numbers meet criteria in function: sGenerateSerialNbr
'    eg: 3XA7-BC6D-98EF with excluded characters
'  newly generated serial nbrs are displayed on wksNewNbrs
'    and also appended to list of existing serial nbrs
'
 Dim bUniqueCodeFound
 Dim lNdx As Long, lSerialNbrsToMake As Long
 Dim lLastRowExisting As Long, lLoopCount As Long
 Dim rNewResults As Range
 Dim dctSerialNbrs As Scripting.Dictionary
 Dim sSerialNbr As String, sProduct As String, sCustomer As String
 Dim vExisting As Variant, vNewSerialNbrs As Variant
 Dim wksNewNbrs As Worksheet, wksExistNbrs As Worksheet
  
 On Error GoTo ExitProc
  
 Set dctSerialNbrs = New Scripting.Dictionary
 Set wksNewNbrs = Sheets("Generator")
 Set wksExistNbrs = Sheets("Records")

 With wksNewNbrs
   sProduct = .Range("B3").Value
   lSerialNbrsToMake = .Range("B4").Value
   sCustomer = .Range("B5").Value
   '--optional: clear input values
   .Range("B3:B5").ClearContents
   '--location to write results
   Set rNewResults = .Range("A8")
   '--clear previous results
   Range(rNewResults, .Cells(.Rows.Count, rNewResults.Column)).ClearContents
   '--size 2d array to hold new results
   ReDim vNewSerialNbrs(1 To lSerialNbrsToMake, 1 To 1)
 End With

'--read existing serial numbers into dictionary
'  also validate there are no duplicates in existing nbrs
 With wksExistNbrs
   lLastRowExisting = .Cells(.Rows.Count, "A").End(xlUp).Row
   vExisting = .Range("A1:A" & lLastRowExisting).Value
   '--handle 0-1 existing items
   If Not IsArray(vExisting) Then vExisting = Array(vExisting)
   For lNdx = 1 To UBound(vExisting, 1)
      sSerialNbr = vExisting(lNdx, 1)
      If Len(sSerialNbr) <> 0 Then
         If Not dctSerialNbrs.Exists(sSerialNbr) Then
            dctSerialNbrs.Add sSerialNbr, lNdx
         Else
            MsgBox "Duplicate found in existing Serial Numbers:" _
               & sSerialNbr
            GoTo ExitProc
         End If
      End If
   Next
 End With

'--generate specified count of new serial numbers.
'  use dictionary to test each number is unique
 For lNdx = 1 To lSerialNbrsToMake
   bUniqueCodeFound = False
   '--prevent endless loop
   lLoopCount = 0
   Do Until bUniqueCodeFound Or lLoopCount > 10
      '--call function to get string meeting criteria
      sSerialNbr = sGenerateSerialNbr()
      If Not dctSerialNbrs.Exists(sSerialNbr) Then
         dctSerialNbrs.Add sSerialNbr, lNdx
         vNewSerialNbrs(lNdx, 1) = sSerialNbr
         bUniqueCodeFound = True
      End If
      lLoopCount = lLoopCount + 1
   Loop
 Next lNdx
   
'--write results to new range and append to existing list
 If lSerialNbrsToMake > 0 Then
   rNewResults.Resize(lSerialNbrsToMake).Value _
      = vNewSerialNbrs
   With wksExistNbrs.Cells(lLastRowExisting + 1, "A") _
      .Resize(lSerialNbrsToMake)
      .Value = vNewSerialNbrs
      .Offset(0, 1).Value = sProduct
      .Offset(0, 2).Value = sCustomer
   End With
   '--add product and customer data to appended records
   
 End If
 
ExitProc:
 Set dctSerialNbrs = Nothing
 If Err.Number <> 0 Then
   MsgBox Err.Number & "-" & Err.Description
 End If
End Sub
 
Upvote 0

Forum statistics

Threads
1,221,417
Messages
6,159,789
Members
451,589
Latest member
Harold14

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top