To generate a valid Code 128 barcode you need to follow some rules. It must contain a start chararacter, that indicates which character set you want to represent; the data characters, the characters that will be encoded; the checksum, a single character for error checking; and finally, a stop character, to indicate the end of the barcode.
In the ID Automation Code 128 Barcode Font User Manual
you can find detailed instructions on what those characters (Start and Stop) are and how to generate a checksum for the data you want to encode.
For most applications Set B or C is what you want. Set B contains digits, uppercase and lowercase letters, and some special characters. Set C is used to represent numbers from 00 to 99, which is useful when you want to represent huge strings of numbers. Set A contains digits, uppercase letters, and a bunch of control characters, which might be useful in some specific applications.
You can also switch between the three code sets in the same barcode, as there are control characters for that purpose in each set. However, this will not be covered in this post.
To generate the valid code we must pass the text to be encoded to the encodeToCode128
function.
const checkbox = document.getElementById('withtext')
function toSetC(text) {
return text.match(/\d{2}/g).map((ascii, index) => {
var codeC = Number(ascii);
var charCode = codeC > 94 ? codeC + 100 : codeC + 32;
return String.fromCharCode(charCode)
}).join('');
}
function checkSum128(data, startCode) {
var sum = startCode;
for (var i = 0; i < data.length; i++) {
var code = data.charCodeAt(i);
var value = code > 199 ? code - 100 : code - 32;
sum += (i + 1) * (value);
}
var checksum = (sum % 103) + 32;
if (checksum > 126) checksum = checksum + 68 ;
return String.fromCharCode(checksum);
}
function encodeToCode128(text, codeABC = "B") {
var startCode = String.fromCharCode(codeABC.toUpperCase().charCodeAt() + 138);
var stop = String.fromCharCode(206);
text = codeABC == 'C' && toSetC(text) || text;
var check = checkSum128(text, startCode.charCodeAt(0) - 100);
text = text.replace(" ", String.fromCharCode(194));
return startCode + text + check + stop;
}
function renderBarcodes(withText = true) {
var barcodeElements = document.querySelectorAll(".barcode");
var codes = [];
barcodeElements.forEach((e) => {
var code = e.attributes["data-barcode"]?.value;
if (!code) return;
var set = e.attributes["data-set"]?.value;
e.innerHTML = encodeToCode128(code, set);
e.classList.toggle('with-text', withText)
});
}
renderBarcodes();
checkbox.addEventListener('change', (event) => {
renderBarcodes(event.currentTarget.checked)
});
To generate the valid barcode we just add the barcode
class to an empty div
and pass the data-barcode
attribute with the data we want. This is a completely arbitrary parameter name, but it is the parameter the renderBarcodes
function will look for.
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Libre+Barcode+128">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Libre+Barcode+128+Text">
<input type="checkbox" id="withtext" name="Show Barcode With Text" checked>
<label for="withtext">Show Barcode With Text</label>
<br /> <br />
<div class="barcode" data-barcode="https://dev.to/saulodias"></div>
<br />
This code contains only digits, and can have a shorter barcode when using Set C
<div class="barcode" data-barcode="0123456789"></div>
<br />
Same data as the barcode above but with a shorter barcode.
<div class="barcode" data-barcode="0123456789" data-set="C"></div>
Here are is the CSS to apply correctly apply the Libre Barcode fonts used.
.barcode {
font-family: "Libre Barcode 128", "Courier New", Courier, monospace;
font-weight: normal;
font-size: 52px;
white-space: nowrap;
}
.with-text {
font-family: "Libre Barcode 128 Text";
}
See the JS Fiddle Example here.
Length Optimization
Here is an example switching code set for optimization
The challenge is to find the best combination to optimize the number of characters used, making the barcode shorter. This is explained in [more details on Wikipedia.]
To decide when switch to code C I have used the criteria in this Wikipedia Page
Additional notes
If you prefer, the fonts used in the example can be downloaded here:
On Stack Overflow Taw implemented this in C#. I used his implementation as reference.
P.S. When generating server-side PDFs, which is something I needed to do you might need to install the fonts to the server, if you have any trouble with font-face and/or the CDN fonts. In any case I do not like to use CDN fonts for several reasons out of the scope of this post.
Top comments (7)
There is an error in your short barcode has the number is 95, 96, 97, 98 og 99.
Then the barcode is formated with a wrong char.
/Cheers
This bug had been caught but I only corrected it in the version with the dynamic optimization. I have updated the jsfiddle and the code in the post. Thanks for reporting!
Thanks so much, this code is extremely helpful.
I am having a problem where Libre Barcode 128 Text is showing the checksum character in the text.
When I scan the barcode it is read correctly, but the checksum text is showing.
Any ideas?
Hello Rob. I'm glad this has been helpful to you. Can you give me a reproduction of the error on jsfiddle? You can fork the example given, make changes and send it back here. I'll see what I can do.
no es 199 es 194 en el checkSum:
var value = code > 194 ? code - 100 : code - 32;
Muchas gracias, estaba como loco buscando esto, cuando me di cuenta que usar el code128 es un poco mas complejo, si quieres leer los códigos desde el html con un app movil. Dios te bendiga siempre.
Nota: .charCodeAt()= charCodeAt(0) :=>
var startCode = String.fromCharCode(codeABC.toUpperCase().charCodeAt(0) + 138);
Nota: renderBarcodes(event.currentTarget.checked)
=>
renderBarcodes((event.target as HTMLInputElement).checked)