Excel VBA Barcode Generator

Tetra201

MrExcel MVP
Joined
Oct 14, 2016
Messages
4,121
I encountered a need to generate barcodes from alphanumeric strings from within Excel (by the way, Word has a built-in capability for this). So I wrote a piece of VBA code shown below. It was inspired by the posts of yakovleff from this forum.

The resulting barcode is a group of rectangular shapes, so it can be handled as a single object – moved, rotated, etc. It can also be stretched/shrunk as needed without losing the barcode structure. The EncStr argument in the barcode drawing sub is a string of ones and zeros that can be generated by a desired encoding function. I am attaching my Code128B function as an example. Everything else is pretty much self-explanatory.

If you find this barcode generator useful, please provide a feedback.

Code:
Type BarParams
    Pos As Long
    Width As Byte
End Type
Sub DrawBarcode(EncStr As String, Left As Single, Top As Single, _
    SingleWidth As Single, Height As Single, Optional Color As Long)
'
' Parameters:
'
' EncStr - a string of ones and zeros, e.g., "11001011"
' Left - the position (in points) of the upper-left corner of the barcode
'        relative to the upper-left corner of the worksheet.
' Top - the position (in points) of the upper-left corner of the barcode
'       relative to the upper-left corner of the worksheet.
' SingleWidth - the width (in points) of a single-wide bar or space.
' Height - the height of the bars, in points.
' Color - (optional) the color of bars; if omitted, the color vill be black.
'
Dim TgtSht As Worksheet
Dim Bars() As BarParams
Dim NextBar As Boolean
Dim i, j As Long
Dim BarColl() As Variant
'
Set TgtSht = ActiveSheet
'
ReDim Bars(1 To 1)
Bars(1).Width = 0
NextBar = False
j = 1
'
For i = 1 To Len(EncStr) Step 1
    If Mid(EncStr, i, 1) = "1" Then
        If Not NextBar Then Bars(j).Pos = i
        Bars(j).Width = Bars(j).Width + 1
        NextBar = True
    Else
        If NextBar Then
            j = j + 1
            ReDim Preserve Bars(1 To j)
            Bars(j).Width = 0
        End If
        NextBar = False
    End If
Next i
'
ReDim BarColl(1 To j)
'
For i = 1 To j Step 1
    With TgtSht.Shapes.AddShape(msoShapeRectangle, _
        Left + (Bars(i).Pos - 1) * SingleWidth, Top, _
        Bars(i).Width * SingleWidth, Height)
        .Line.Visible = msoFalse
        .Fill.ForeColor.RGB = Color
        BarColl(i) = .Name
    End With
Next i
'
TgtSht.Shapes.Range(BarColl).Group
'
End Sub

Code:
Function Code128B(TxtStr As String) As String
'
' Parameters
'
' TxtSrt - an alphanumeric string; Chr(32) to Chr(106) can be used.
'
Const MaxChB = 94
'
Dim i, j As Long
Dim SymChB(0 To MaxChB) As String * 1
Dim SymEnc As Variant
Dim WgtSum As Long
Dim EncStr As String
'
For i = 0 To 94
    SymChB(i) = Chr(i + 32)
Next i
'
SymEnc = Array( _
    "11011001100", "11001101100", "11001100110", "10010011000", "10010001100", _
    "10001001100", "10011001000", "10011000100", "10001100100", "11001001000", _
    "11001000100", "11000100100", "10110011100", "10011011100", "10011001110", _
    "10111001100", "10011101100", "10011100110", "11001110010", "11001011100", _
    "11001001110", "11011100100", "11001110100", "11101101110", "11101001100", _
    "11100101100", "11100100110", "11101100100", "11100110100", "11100110010", _
    "11011011000", "11011000110", "11000110110", "10100011000", "10001011000", _
    "10001000110", "10110001000", "10001101000", "10001100010", "11010001000", _
    "11000101000", "11000100010", "10110111000", "10110001110", "10001101110", _
    "10111011000", "10111000110", "10001110110", "11101110110", "11010001110", _
    "11000101110", "11011101000", "11011100010", "11011101110", "11101011000", _
    "11101000110", "11100010110", "11101101000", "11101100010", "11100011010", _
    "11101111010", "11001000010", "11110001010", "10100110000", "10100001100", _
    "10010110000", "10010000110", "10000101100", "10000100110", "10110010000", _
    "10110000100", "10011010000", "10011000010", "10000110100", "10000110010", _
    "11000010010", "11001010000", "11110111010", "11000010100", "10001111010", _
    "10100111100", "10010111100", "10010011110", "10111100100", "10011110100", _
    "10011110010", "11110100100", "11110010100", "11110010010", "11011011110", _
    "11011110110", "11110110110", "10101111000", "10100011110", "10001011110", _
    "10111101000", "10111100010", "11110101000", "11110100010", "10111011110", _
    "10111101110", "11101011110", "11110101110", "11010000100", "11010010000", _
    "11010011100", "11000111010")
ReDim Preserve SymEnc(0 To 106)
'
WgtSum = 104 ' START-B
EncStr = EncStr + SymEnc(104)
For i = 1 To Len(TxtStr) Step 1
    j = 0
    Do While (Mid(TxtStr, i, 1) <> SymChB(j)) And (j <= MaxChB)
        j = j + 1
    Loop
    If j > MaxChB Then j = 0
    WgtSum = WgtSum + i * j
    EncStr = EncStr + SymEnc(j)
Next i
Code128B = EncStr + SymEnc(WgtSum Mod 103) + SymEnc(106) + "11"
'
End Function
 
What are you expecting the results to be? What are the barcode form that you are using?
 
Upvote 0

Excel Facts

Add Bullets to Range
Select range. Press Ctrl+1. On Number tab, choose Custom. Type Alt+7 then space then @ sign (using 7 on numeric keypad)
... Why is the barcode generated by the online barcode generator relatively short?..
It depends on the barcode system that you are using. If you are talking about Code 128 -- yes, it can be compacted to use one barcode symbol for two adjacent digits.

Unfortunately, at the moment, I have no bandwidth to update my Code 128 encoding function.
 
Upvote 0
What are you expecting the results to be? What are the barcode form that you are using?

I use code128B, but the resulting barcode is too long. My barcode content is 1231234567890; ABCDEFG12345670123
There are 32 codes that cannot be printed on an 80mm sticker for reading.
Recently I found code128 auto. How do I change it?
 
Upvote 0
I use code128B, but the resulting barcode is too long. My barcode content is 1231234567890; ABCDEFG12345670123
There are 32 codes that cannot be printed on an 80mm sticker for reading.
Recently I found code128 auto. How do I change it?

Obtain the following code 128 B+C from yakovleff for modification.
Is there a better way to write it?
The following code provides everyone
And thanks to yakovleff and Tetra201

Code:
Function Code128(Content As String)
' Supports B and C charsets only; values 00-94, 99,101, 103-105 for B, 00-101, 103-105 for C
' X in mm (0.351)
' Y in mm (0.351) 1mm = 2.8 pt
' Height in mm
' LineWeight in pt


Dim WeightSum As Single
Const XmmTopt As Single = 0.351
Const YmmTopt As Single = 0.351
Const XCompRatio As Single = 0.9


Const Tbar_Symbol As String * 2 = "11"
Dim CurBar As Integer
Dim i, j, k, CharIndex, SymbolIndex As Integer
Dim tstr2 As String * 2
Dim tstr1 As String * 1
Dim ContentString As String ' bars sequence
Const Asw As String * 1 = "A" ' alpha switch
Const Dsw As String * 1 = "D" 'digital switch
Const Arrdim As Byte = 30


Dim Sw, PrevSw As String * 1  ' switch
Dim BlockIndex, BlockCount, DBlockMod2, DBlockLen As Byte


Dim BlockLen(Arrdim) As Byte
Dim BlockSw(Arrdim) As String * 1


Dim SymbolValue(0 To 106) As Integer ' values
Dim SymbolString(0 To 106) As String * 11 'bits sequence
Dim SymbolCharB(0 To 106) As String * 1  'Chars in B set
Dim SymbolCharC(0 To 106) As String * 2  'Chars in B set


For i = 0 To 106 ' values
    SymbolValue(i) = i
Next i


' Symbols in charset B
For i = 0 To 94
    SymbolCharB(i) = Chr(i + 32)
Next i


' Symbols in charset C
SymbolCharC(0) = "00"
SymbolCharC(1) = "01"
SymbolCharC(2) = "02"
SymbolCharC(3) = "03"
SymbolCharC(4) = "04"
SymbolCharC(5) = "05"
SymbolCharC(6) = "06"
SymbolCharC(7) = "07"
SymbolCharC(8) = "08"
SymbolCharC(9) = "09"
For i = 10 To 99
    SymbolCharC(i) = CStr(i)
Next i


' bit sequences
SymbolString(0) = "11011001100"
SymbolString(1) = "11001101100"
SymbolString(2) = "11001100110"
SymbolString(3) = "10010011000"
SymbolString(4) = "10010001100"
SymbolString(5) = "10001001100"
SymbolString(6) = "10011001000"
SymbolString(7) = "10011000100"
SymbolString(8) = "10001100100"
SymbolString(9) = "11001001000"
SymbolString(10) = "11001000100"
SymbolString(11) = "11000100100"
SymbolString(12) = "10110011100"
SymbolString(13) = "10011011100"
SymbolString(14) = "10011001110"
SymbolString(15) = "10111001100"
SymbolString(16) = "10011101100"
SymbolString(17) = "10011100110"
SymbolString(18) = "11001110010"
SymbolString(19) = "11001011100"
SymbolString(20) = "11001001110"
SymbolString(21) = "11011100100"
SymbolString(22) = "11001110100"
SymbolString(23) = "11101101110"
SymbolString(24) = "11101001100"
SymbolString(25) = "11100101100"
SymbolString(26) = "11100100110"
SymbolString(27) = "11101100100"
SymbolString(28) = "11100110100"
SymbolString(29) = "11100110010"
SymbolString(30) = "11011011000"
SymbolString(31) = "11011000110"
SymbolString(32) = "11000110110"
SymbolString(33) = "10100011000"
SymbolString(34) = "10001011000"
SymbolString(35) = "10001000110"
SymbolString(36) = "10110001000"
SymbolString(37) = "10001101000"
SymbolString(38) = "10001100010"
SymbolString(39) = "11010001000"
SymbolString(40) = "11000101000"
SymbolString(41) = "11000100010"
SymbolString(42) = "10110111000"
SymbolString(43) = "10110001110"
SymbolString(44) = "10001101110"
SymbolString(45) = "10111011000"
SymbolString(46) = "10111000110"
SymbolString(47) = "10001110110"
SymbolString(48) = "11101110110"
SymbolString(49) = "11010001110"
SymbolString(50) = "11000101110"
SymbolString(51) = "11011101000"
SymbolString(52) = "11011100010"
SymbolString(53) = "11011101110"
SymbolString(54) = "11101011000"
SymbolString(55) = "11101000110"
SymbolString(56) = "11100010110"
SymbolString(57) = "11101101000"
SymbolString(58) = "11101100010"
SymbolString(59) = "11100011010"
SymbolString(60) = "11101111010"
SymbolString(61) = "11001000010"
SymbolString(62) = "11110001010"
SymbolString(63) = "10100110000"
SymbolString(64) = "10100001100"
SymbolString(65) = "10010110000"
SymbolString(66) = "10010000110"
SymbolString(67) = "10000101100"
SymbolString(68) = "10000100110"
SymbolString(69) = "10110010000"
SymbolString(70) = "10110000100"
SymbolString(71) = "10011010000"
SymbolString(72) = "10011000010"
SymbolString(73) = "10000110100"
SymbolString(74) = "10000110010"
SymbolString(75) = "11000010010"
SymbolString(76) = "11001010000"
SymbolString(77) = "11110111010"
SymbolString(78) = "11000010100"
SymbolString(79) = "10001111010"
SymbolString(80) = "10100111100"
SymbolString(81) = "10010111100"
SymbolString(82) = "10010011110"
SymbolString(83) = "10111100100"
SymbolString(84) = "10011110100"
SymbolString(85) = "10011110010"
SymbolString(86) = "11110100100"
SymbolString(87) = "11110010100"
SymbolString(88) = "11110010010"
SymbolString(89) = "11011011110"
SymbolString(90) = "11011110110"
SymbolString(91) = "11110110110"
SymbolString(92) = "10101111000"
SymbolString(93) = "10100011110"
SymbolString(94) = "10001011110"
SymbolString(95) = "10111101000"
SymbolString(96) = "10111100010"
SymbolString(97) = "11110101000"
SymbolString(98) = "11110100010"
SymbolString(99) = "10111011110"
SymbolString(100) = "10111101110"
SymbolString(101) = "11101011110"
SymbolString(102) = "11110101110"
SymbolString(103) = "11010000100"
SymbolString(104) = "11010010000"
SymbolString(105) = "11010011100"
SymbolString(106) = "11000111010"


X = X / XmmTopt 'mm to pt
Y = Y / YmmTopt 'mm to pt
Height = Height / YmmTopt 'mm to pt


If IsNumeric(Content) = True And Len(Content) Mod 2 = 0 Then 'numeric, mode C
   WeightSum = SymbolValue(105) ' start-c
   ContentString = ContentString + SymbolString(105)
   i = 0 ' symbol count
   For j = 1 To Len(Content) Step 2
      tstr2 = Mid(Content, j, 2)
      i = i + 1
      k = 0
      Do While tstr2 <> SymbolCharC(k)
         k = k + 1
      Loop
      WeightSum = WeightSum + i * SymbolValue(k)
      ContentString = ContentString + SymbolString(k)
   Next j
   ContentString = ContentString + SymbolString(SymbolValue(WeightSum Mod 103))
   ContentString = ContentString + SymbolString(106)
   ContentString = ContentString + Tbar_Symbol
   
Else ' alpha-numeric
   
   ' first digit
   Select Case IsNumeric(Mid(Content, 1, 1))
   Case Is = True 'digit
      Sw = Dsw
   Case Is = False 'alpha
      Sw = Asw
   End Select
   BlockCount = 1
   BlockSw(BlockCount) = Sw
   BlockIndex = 1
   BlockLen(BlockCount) = 1 'block length


   
   i = 2 ' symbol index
   
   Do While i <= Len(Content)
      Select Case IsNumeric(Mid(Content, i, 1))
      Case Is = True 'digit
         Sw = Dsw
      Case Is = False 'alpha
         Sw = Asw
      End Select
      
      If Sw = BlockSw(BlockCount) Then
         BlockLen(BlockCount) = BlockLen(BlockCount) + 1
      Else
         BlockCount = BlockCount + 1
         BlockSw(BlockCount) = Sw
         BlockLen(BlockCount) = 1
         BlockIndex = BlockIndex + 1


      End If
      
      i = i + 1
   Loop
   


   'encoding
   CharIndex = 0 'index of Content character
   SymbolIndex = 0
   
   For BlockIndex = 1 To BlockCount ' encoding by blocks
      
      CharIndex = CharIndex + 1
      
      If BlockSw(BlockIndex) = Dsw And BlockLen(BlockIndex) >= 4 Then ' switch to C
         Select Case BlockIndex
         Case Is = 1
            WeightSum = SymbolValue(105) ' Start-C
            ContentString = ContentString + SymbolString(105)
         Case Else
            SymbolIndex = SymbolIndex + 1
            WeightSum = WeightSum + SymbolIndex * SymbolValue(99) 'switch c
            ContentString = ContentString + SymbolString(99)
         End Select
         PrevSw = Dsw
         
         ' encoding even amount of chars in a D block
         DBlockMod2 = BlockLen(BlockIndex) Mod 2
         If DBlockMod2 <> 0 Then 'even chars always to encode
            DBlockLen = BlockLen(BlockIndex) - DBlockMod2
         Else
            DBlockLen = BlockLen(BlockIndex)
         End If
         
         
         For j = 1 To DBlockLen / 2 Step 1
            tstr2 = Mid(Content, CharIndex, 2)
            CharIndex = CharIndex + 2
            SymbolIndex = SymbolIndex + 1
            k = 0
            Do While tstr2 <> SymbolCharC(k)
               k = k + 1
            Loop
            WeightSum = WeightSum + SymbolIndex * SymbolValue(k)
            ContentString = ContentString + SymbolString(k)
         Next j
         CharIndex = CharIndex - 1
         
         If DBlockMod2 <> 0 Then ' switch to B, encode 1 char
            PrevSw = Asw
            SymbolIndex = SymbolIndex + 1
            WeightSum = WeightSum + SymbolIndex * SymbolValue(100) 'switch b
            ContentString = ContentString + SymbolString(100)
            
            CharIndex = CharIndex + 1
            SymbolIndex = SymbolIndex + 1
            tstr1 = Mid(Content, CharIndex, 1)
            k = 0
            Do While tstr1 <> SymbolCharB(k)
               k = k + 1
            Loop
            WeightSum = WeightSum + SymbolIndex * SymbolValue(k)
            ContentString = ContentString + SymbolString(k)
         End If
         
      
      Else 'alpha in B mode
         Select Case BlockIndex
         Case Is = 1
         '   PrevSw = Asw
            WeightSum = SymbolValue(104) ' start-b
            ContentString = ContentString + SymbolString(104)
         Case Else
            If PrevSw <> Asw Then
               SymbolIndex = SymbolIndex + 1
               WeightSum = WeightSum + SymbolIndex * SymbolValue(100) 'switch b
               ContentString = ContentString + SymbolString(100)
               
            End If
         End Select
         PrevSw = Asw
         
         For j = CharIndex To CharIndex + BlockLen(BlockIndex) - 1 Step 1
            tstr1 = Mid(Content, j, 1)
            SymbolIndex = SymbolIndex + 1
            k = 0
            Do While tstr1 <> SymbolCharB(k)
               k = k + 1
            Loop
            WeightSum = WeightSum + SymbolIndex * SymbolValue(k)
            ContentString = ContentString + SymbolString(k)
         Next j
         CharIndex = j - 1
         
      End If
   Next BlockIndex
   ContentString = ContentString + SymbolString(SymbolValue(WeightSum Mod 103))
   ContentString = ContentString + SymbolString(106)
   ContentString = ContentString + Tbar_Symbol
   Code128 = ContentString
End If


On Error GoTo 0


End Function

Barcode Generator
Code:
Sub test()
    DrawBarcode Code128("2811607100010;CBD708AD1010010012"), 100, 240, 0.65, 22
End Sub
[h=1][/h]
 
Upvote 0
Hello, @Tetra201,

Your code is very cute. It is pointing to exactly what I am trying to achieve.

One down side is, the bars become very small that my scanner can't pick them up unless I manually enlarge the shape by dragging out. - I am scanning from phone app. I am sure there is a line right inside the code doing the size thing, but I can't see it.

I will be very glad if you can show me how to do that. Thanks
 
Upvote 0
Try playing with (increasing?) the sub's 4th argument (the width (in points) of a single-wide bar or space) and 5th argument (the height of the bars, in points).

Great, I was able to play around it and got it accessible by my scanner. 1.5, 25 worked for me.

So if my guess is correct, then the 3rd and 3rd arguments are for the position of the object.

Few questions here:
1. Is there a way I can delete just that shape after I generate the barcode ?
2. If yes, then what should be the way?
3. If I am looking at a range, C2:H25, can I place the object at bottom right of the said range ?
 
Upvote 0

Forum statistics

Threads
1,224,832
Messages
6,181,235
Members
453,026
Latest member
cknader

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