Let's learn encoding system.
- The width of a slim bar is named the module.
- There are bars of 1, 2, 3 or 4 modules; equally for the spaces.
- There are 107 patterns, each is coded with 11 modules including 3 bars and 3 spaces (The STOP pattern have 4 bars).
- There are 3 tables giving the character or the function affected to each pattern.
- Table A contains the capital letters, the digits, the punctuations, some control codes and special codes.
- Table B contains capital and lower case letters, the digits, the punctuations and special codes.
- Table C contains pairs of digits (Allowing to double the density) and special codes.
- White zones of at least 10 modules are requested on the left and on the right.
- There is a START character at the beginning of the code. There are 3 START characters fixing the table used for the start.
- The code ends with a STOP character.
- Some special characters (99, 100 & 101) make it possible to pass from one table to an other; the SHIFT character (98) switch the next character between tables A & B.
- The function codes (FNC1 a FNC4) aren't all defined.
- A checksum must be added; its value is calculated by adding up the value of the START then the value of each pattern multiplied by its row; then by taking the remainder of the division of this sum by 103.
- In the following array a bar module is symbolized by "1" and a space module by "0".
- The columns "ASCII Code" and "Character" indicate the place of the patterns in the font "code128.ttf" (See further)
- The character number 0 (Space) is obtained with the code 32 or with the code 212 because some programming tools cannot use code 32.
Value
Table A
Table B
Table C
ASCII code
Character
Pattern
0
Space
Space
00
0032 or 0212
Space or Ô
11011001100
1
!
!
01
0033
!
11001101100
2
"
"
02
0034
"
11001100110
3
#
#
03
0035
#
10010011000
4
$
$
04
0036
$
10010001100
5
%
%
05
0037
%
10001001100
6
&
&
06
0038
&
10011001000
7
'
'
07
0039
'
10011000100
8
(
(
08
0040
(
10001100100
9
)
)
09
0041
)
11001001000
10
*
*
10
0042
*
11001000100
11
+
+
11
0043
+
11000100100
12
,
,
12
0044
,
10110011100
13
-
-
13
0045
-
10011011100
14
.
.
14
0046
.
10011001110
15
/
/
15
0047
/
10111001100
16
0
0
16
0048
0
10011101100
17
1
1
17
0049
1
10011100110
18
2
2
18
0050
2
11001110010
19
3
3
19
0051
3
11001011100
20
4
4
20
0052
4
11001001110
21
5
5
21
0053
5
11011100100
22
6
6
22
0054
6
11001110100
23
7
7
23
0055
7
11101101110
24
8
8
24
0056
8
11101001100
25
9
9
25
0057
9
11100101100
26
:
:
26
0058
:
11100100110
27
;
;
27
0059
;
11101100100
28
<
<
28
0060
<
11100110100
29
=
=
29
0061
=
11100110010
30
>
>
30
0062
>
11011011000
31
?
?
31
0063
?
11011000110
32
@
@
32
0064
@
11000110110
33
A
A
33
0065
A
10100011000
34
B
B
34
0066
B
10001011000
35
C
C
35
0067
C
10001000110
36
D
D
36
0068
D
10110001000
37
E
E
37
0069
E
10001101000
38
F
F
38
0070
F
10001100010
39
G
G
39
0071
G
11010001000
40
H
H
40
0072
H
11000101000
41
I
I
41
0073
I
11000100010
42
J
J
42
0074
J
10110111000
43
K
K
43
0075
K
10110001110
44
L
L
44
0076
L
10001101110
45
M
M
45
0077
M
10111011000
46
N
N
46
0078
N
10111000110
47
O
O
47
0079
O
10001110110
48
P
P
48
0080
P
11101110110
49
Q
Q
49
0081
Q
11010001110
50
R
R
50
0082
R
11000101110
51
S
S
51
0083
S
11011101000
52
T
T
52
0084
T
11011100010
Value
Table A
Table B
Table C
ASCII code
Character
Pattern
53
U
U
53
0085
U
11011101110
54
V
V
54
0086
V
11101011000
55
W
W
55
0087
W
11101000110
56
X
X
56
0088
X
11100010110
57
Y
Y
57
0089
Y
11101101000
58
Z
Z
58
0090
Z
11101100010
59
[
[
59
0091
[
11100011010
60
\
\
60
0092
\
11101111010
61
]
]
61
0093
]
11001000010
62
^
^
62
0094
^
11110001010
63
_
_
63
0095
_
10100110000
64
nul
`
64
0096
`
10100001100
65
soh
a
65
0097
a
10010110000
66
stx
b
66
0098
b
10010000110
67
etx
c
67
0099
c
10000101100
68
eot
d
68
0100
d
10000100110
69
eno
e
69
0101
e
10110010000
70
ack
f
70
0102
f
10110000100
71
bel
g
71
0103
g
10011010000
72
bs
h
72
0104
h
10011000010
73
ht
i
73
0105
i
10000110100
74
lf
j
74
0106
j
10000110010
75
vt
k
75
0107
k
11000010010
76
ff
l
76
0108
l
11001010000
77
cr
m
77
0109
m
11110111010
78
s0
n
78
0110
n
11000010100
79
s1
o
79
0111
o
10001111010
80
dle
p
80
0112
p
10100111100
81
dc1
q
81
0113
q
10010111100
82
dc2
r
82
0114
r
10010011110
83
dc3
s
83
0115
s
10111100100
84
dc4
t
84
0116
t
10011110100
85
nak
u
85
0117
u
10011110010
86
syn
v
86
0118
v
11110100100
87
etb
w
87
0119
w
11110010100
88
can
x
88
0120
x
11110010010
89
em
y
89
0121
y
11011011110
90
sub
z
90
0122
z
11011110110
91
esc
{
91
0123
{
11110110110
92
fs
|
92
0124
|
10101111000
93
gs
}
93
0125
}
10100011110
94
rs
~
94
0126
~
10001011110
95
us
del
95
0200
È
10111101000
96
Fnc 3
Fnc 3
96
0201
É
10111100010
97
Fnc 2
Fnc2
97
0202
Ê
11110101000
98
Shift
Shift
98
0203
Ë
11110100010
99
Code C
Code C
99
0204
Ì
10111011110
100
Code B
Fnc 4
Code B
0205
Í
10111101110
101
Fnc 4
Code A
Code A
0206
Î
11101011110
102
Fnc 1
Fnc 1
Fnc 1
0207
Ï
11110101110
103
Start A
Start A
Start A
0208
Ð
11010000100
104
Start B
Start B
Start B
0209
Ñ
11010010000
105
Start C
Start C
Start C
0210
Ò
11010011100
106
Stop
Stop
Stop
0211
Ó
1100011101011
Example of checksum with use of table B for : ZB65
104 + (1 x 58) + (2 x 34) + (3 x 22) + (4 x 21) = 380
380 / 103 = 3, remainder 71 which is the value of the key.
Bar code making.
Since we can create the bar code pattern it remains us to draw it on the screen and to print it on a paper sheet. Two approaches are possibles :
-
The graphic method where each bar is "drawn" as a full rectangle. This method enable to compute the width of each bar with a one pixel precision and so we can work with widths which
are perfect multiple of the used device pixel. This give us a good accuracy specially if the device have a low density as it's the case with screens and inkjet printers. This method
require special programming routines and does not allow to make bar codes with a current software.
-
The special font in which each character is replaced by a bar code. This method allow the use of any software like a text processing or a spreadsheet. (For example LibreOffice, the
free clone of MSoffice !) The scale settings according to the selected size can bring away small misshaping of the bar drawing. With a laser printer there's no probs.
Most fonts for 128 barcodes found on the net (incomplete demonstration fonts) are paid for (sometimes very expensive) and of dubious quality; the width of the modules is not always
constant in the definition of the font. So I decided to completely design a 128 barcode font and offer it for download. I tested it on a laser printer with size 17, what gives a small barcode with
a width of about 1,7 mm/car, result : reading at 100% ! On a good inkjet printer, we can go down (He yes !) to the size 15 what give a character width of 1,5mm.
The font " code128.ttf "
This font contain the 107 patterns of the code. The START and STOP codes include the margins. The ZIP contains two versions : normal height and reduced height.
Copy this file in the font directory, often named : \Windows\Fonts
Structure of a 128 barcode.
A 128 barcode will be build up in the following way :
- One of the three START code, generally START B.
- As many characters as necessary, special codes makes it possible to pass from one table to an other. An intelligent algorithm will allow to use one or more tables giving the barcode shortest possible.
- A checksum.
- A STOP code.
A small program to test all that..
Note optimization of "3754" to "EV" of the table C
Here is a small program written with Visual Basic 6 ; The
setup file copy the program, Visual Basic
dependencies, source files and the font.
Setup file :
ZIP file without setup :

This test program does not manage the ASCII control codes, it use the tables B & C with optimization length of the code obtained.
The Code128$ function can be re-used in an other program written with Visual Basic 6 ; it can also be copied as it is in a VBA macro linked to an Office document.
Public Function Code128$(chaine$)
'V 2.0.0
'Paramètres : une chaine
'Parameters : a string
'Retour : * une chaine qui, affichée avec la police CODE128.TTF, donne le code barre
' * une chaine vide si paramètre fourni incorrect
'Return : * a string which give the bar code when it is dispayed with CODE128.TTF font
' * an empty string if the supplied parameter is no good
Dim i%, checksum&, mini%, dummy%, tableB As Boolean
Code128$ = ""
If Len(chaine$) > 0 Then
'Vérifier si caractères valides
'Check for valid characters
For i% = 1 To Len(chaine$)
Select Case Asc(Mid$(chaine$, i%, 1))
Case 32 To 126, 203
Case Else
i% = 0
Exit For
End Select
Next
'Calculer la chaine de code en optimisant l'usage des tables B et C
'Calculation of the code string with optimized use of tables B and C
Code128$ = ""
tableB = True
If i% > 0 Then
i% = 1 'i% devient l'index sur la chaine / i% become the string index
Do While i% <= Len(chaine$)
If tableB Then
'Voir si intéressant de passer en table C / See if interesting to switch to table C
'Oui pour 4 chiffres au début ou à la fin, sinon pour 6 chiffres / yes for 4 digits at start or end, else if 6 digits
mini% = IIf(i% = 1 Or i% + 3 = Len(chaine$), 4, 6)
GoSub testnum
If mini% < 0 Then 'Choix table C / Choice of table C
If i% = 1 Then 'Débuter sur table C / Starting with table C
Code128$ = Chr$(210)
Else 'Commuter sur table C / Switch to table C
Code128$ = Code128$ & Chr$(204)
End If
tableB = False
Else
If i% = 1 Then Code128$ = Chr$(209) 'Débuter sur table B / Starting with table B
End If
End If
If Not tableB Then
'On est sur la table C, essayer de traiter 2 chiffres / We are on table C, try to process 2 digits
mini% = 2
GoSub testnum
If mini% < 0 Then 'OK pour 2 chiffres, les traiter / OK for 2 digits, process it
dummy% = Val(Mid$(chaine$, i%, 2))
dummy% = IIf(dummy% < 95, dummy% + 32, dummy% + 105)
Code128$ = Code128$ & Chr$(dummy%)
i% = i% + 2
Else 'On n'a pas 2 chiffres, repasser en table B / We haven't 2 digits, switch to table B
Code128$ = Code128$ & Chr$(205)
tableB = True
End If
End If
If tableB Then
'Traiter 1 caractère en table B / Process 1 digit with table B
Code128$ = Code128$ & Mid$(chaine$, i%, 1)
i% = i% + 1
End If
Loop
'Calcul de la clé de contrôle / Calculation of the checksum
For i% = 1 To Len(Code128$)
dummy% = Asc(Mid$(Code128$, i%, 1))
dummy% = IIf(dummy% < 127, dummy% - 32, dummy% - 105)
If i% = 1 Then checksum& = dummy%
checksum& = (checksum& + (i% - 1) * dummy%) Mod 103
Next
'Calcul du code ASCII de la clé / Calculation of the checksum ASCII code
checksum& = IIf(checksum& < 95, checksum& + 32, checksum& + 105)
'Ajout de la clé et du STOP / Add the checksum and the STOP
Code128$ = Code128$ & Chr$(checksum&) & Chr$(211)
End If
End If
Exit Function
testnum:
'si les mini% caractères à partir de i% sont numériques, alors mini%=0
'if the mini% characters from i% are numeric, then mini%=0
mini% = mini% - 1
If i% + mini% <= Len(chaine$) Then
Do While mini% >= 0
If Asc(Mid$(chaine$, i% + mini%, 1)) < 48 Or Asc(Mid$(chaine$, i% + mini%, 1)) > 57 Then Exit Do
mini% = mini% - 1
Loop
End If
Return
End Function
Excel sample file
Libre Office sample file
Since the first publication of this page, I'd received numbered versions in different languages. (Be careful, before 2008 in a first version of the font the codes > 94 were different.)
Language
Author
WinDev 5.5
Laurent PERICAUD
L4G Progress
André SEJOURNET
Visual Foxpro
Emile MAITREJEAN
Delphi
Jean-Camille POPULUS
Delphi
Francisco FERNANDEZ
PL/SQL pour Oracle
Nicolas FANCHAMPS
PLpgSQL
Nicolas FANCHAMPS
Crystal Report
Sébastien REZÉ
Python
Michel CLAVEAU
Java
Virginie LHUILLIER
Java
Jean-Luc BLOECHLE
ASP
G!L
PHP
F. Odouard & P. Guizard
C #
Joffrey VERDIER
The EAN.UCC 128 codes.
These are codes 128 whose content is standardized and correspond to a use in the field of logistic. An EAN128 code starts with the Fnc1 character followed by one or several
fields of data. Each field starts with an
AI (Application Identifier) which announce the field content
(Number of parcel or durability date for examples) followed by the data themselves. These datas are length fixed or variable, numerical or alphanumeric, with or without
checksum and all this according to each AI.
If a field is with variable length, that the maximum length isn't used and that it is not the last field, then it must be followed by a Fnc1 character. Some AI requires
that the datas are followed by a checksum; this one is computed in the following way :
- The digits are numbered from right to left, then we compute x the sum of even digits
and y the sum of odd digits.
-
Let's calculate z = x + 3 * y
-
Let m be the number divisible by 10 immediately superior to z
-
The checksum is : m - z
I have written a small program allowing to create easily EAN128 codes and holding account of these characteristics.
Setup file
ZIP file wihout setup