Home
Analytics
Commercial 2 of 5 Barcode Packages for BIRT
lenburt
<p>Hello out there - we have been attempting to use some 'free' 2 of 5 Interleaved barcode fonts with but but have not had good success in finding one that can be read by our scanners. I have tried several commercial barcode packages for BIRT which work. I am wondering if anyone could recommend one distribution over another. We will be deploying our solution to AIX but doing the BIRT development on Windows.</p>
<p> </p>
<p>Thanks, len</p>
<p> </p>
Find more posts tagged with
Comments
Matthew L.
<p>Hello Len,</p>
<p> </p>
<p>I suspect the reason the scanner isn't reading the barcode correctly is because "2 of 5 interleaved barcodes" require the input value to be encoded: <a data-ipb='nomediaparse' href='
http://idautomation.blogspot.com/2011/07/top-5-reasons-why-barcode-font-wont.html'>http://idautomation.blogspot.com/2011/07/top-5-reasons-why-barcode-font-wont.html</a></p>
;
<p>Some detail about 2 of 5 interleaved barcodes can be found here: <a data-ipb='nomediaparse' href='
http://www.barcodeisland.com/int2of5.phtml'>http://www.barcodeisland.com/int2of5.phtml</a></p>
;
<p> </p>
<p> </p>
<p> </p>
<p>So for example, using the free 2 of 5 interleaved font found here: <a data-ipb='nomediaparse' href='
http://grandzebu.net/informatique/codbar-en/code25I.htm'>http://grandzebu.net/informatique/codbar-en/code25I.htm</a></p>
;
<p>the string ' 0123456789 ' would need to be encoded to the text ' É"8NdzÊ ' in order for the barcode reader to understand the barcode.</p>
<p> </p>
<p>Looking over the VB encoding logic for the free 2 of 5 interleaved font, this should be able to translate into either a Java class or even a JavaScript function that can be added to the report design to dynamically encode the barcodes.</p>
lenburt
<p>Matthew - thanks -- i will take a look at that. Some of the commercial solutions seem to support out-of-the-box rotating which i know you got to work by tweaking the font.</p>
<p> </p>
<p>So for example, one of our strings would be 04040014035775 -- you are saying we need to encode that into some hex values that the open source font would render properly?</p>
<p> </p>
<p>The client i am working with just wants to have this issue put to rest so we were looking into commercial solutions. Thanks again for your help. -- len</p>
<p> </p>
<p> </p>
Matthew L.
<p>I decided to translate the example encoding scheme from: <a data-ipb='nomediaparse' href='
http://grandzebu.net/informatique/codbar-en/code25I.htm'>http://grandzebu.net/informatique/codbar-en/code25I.htm</a></p>
;
<p>Attached is an example report that will encode standard numbers into the '2 of 5 interleaved' encoding scheme.</p>
<p>The '2 of 5 interleaved' barcode font used is from: <a data-ipb='nomediaparse' href='
http://grandzebu.net/informatique/codbar-en/code25I.htm'>http://grandzebu.net/informatique/codbar-en/code25I.htm</a></p>
;
<p> </p>
<p>To use, drop the following function into your reports initialize method.</p>
<p>Then in each element you would like to encode, call the function and set the element to its returning value.</p>
<p> </p>
<p>Drop this code into the initialize method of a BIRT report:</p>
<pre class="_prettyXprint _lang-js">
//
//This custom code is untested and needs to be tested thoroughly before using in a production environment.
//This function encodes a standard number string into a '2 of 5 interleaved code' Barcode encoded compatable
//string and returns the results.
//The font used with this encoder is located: http://grandzebu.net/informatique/codbar-en/code25I.htm
//
//Example use:
//In a Label's onCreate script method use the following code to encode text to 'Code 2 of 5 interleaved':
// this.text = encodeCode2Of5i(this.text);
//
//To add a checksum value:
// this.text = encodeCode2Of5i(this.text,true);
//
//*Notes*:
//Make sure to set the font style to 'Code 2 of 5 interleaved'.
//The '2 of 5 interleaved' barcode font requires an even number of numbers in the string.
//However if you want to include a checksum value, the number string must be an odd number in length as
//the checksum value adds one character to the length of the string.
//
function encodeCode2Of5i(textToEncode, addChecksum){
textToEncode = "" + textToEncode; //Convert input to string
var checksum = 0; //Set checksum
var dummy = 0; //Set dummy
var code25i = ""; //Set output
if(textToEncode.length){ //If value exists
//Check to ensure the string contains only numbers
for(var i=0;i<textToEncode.length;i++) //For each character in the string
if(textToEncode[i].charCodeAt() < 48 || textToEncode[i].charCodeAt() > 57){ //Check to ensure its a number
java.util.logging.Logger.getLogger("birt.report.logger").warning ("Error: Char not supported"); //If not, output to log file
return "Error: Char not supported"; //Return message
}
//Checksum calculation
if(addChecksum){ //If wanting to add a checksum
for(i=textToEncode.length-1; i>=0; i-=2) //For each character in the string from the end to the beginning
checksum += parseInt(textToEncode[i]); //Add number to checksum
checksum = checksum * 3; //Multiply checksum by 3
for(i=(textToEncode.length-2); i>=0; i-=2) //For each character in the string from the second to the end, to the beginning
checksum += parseInt(textToEncode[i]); //Add number to checksum
textToEncode += ((10 - (checksum % 10)) % 10); //Append checksum to end of string
}
//Check for even number of characters
if(textToEncode.length % 2){ //If string is not an even number of characters
java.util.logging.Logger.getLogger("birt.report.logger").warning ("Error: Not even number of characters"); //Output error to log file
return "Error: Not even number of characters"; //Return message
}
//Encode string
for(var i=0;i<textToEncode.length;i+=2){ //For each pair of characters
dummy = textToEncode[i] + textToEncode[i+1] //Get 2 digets
dummy = (dummy<94)?(parseInt(dummy)+33):(parseInt(dummy)+101); //Determine encoding value
code25i += String.fromCharCode(dummy); //Append encoded character to output string
}
code25i = String.fromCharCode(201) + code25i + String.fromCharCode(202); //Add start and stop values
return code25i; //Return encoded string
}
}
</pre>
<p>Use the following code in a Label or Data element to return the encoded value:</p>
<pre class="_prettyXprint _lang-js">
//Use the following line in a Label elements onRender method
this.text = encodeCode2Of5i(this.text); //Set to encoded value
//Use the following line in a Data elements onRender method
this.setDisplayValue(encodeCode2Of5i(this.getValue())); //Set to encoded value
//Call the encodeCode2Of5i() function with a second parameter 'true' to include a checksum
this.text = encodeCode2Of5i(this.text, true); //Set to encoded value with checksum
</pre>
lenburt
<p>Awesome! -- i was looking at that VB code trying to make sense out of it...i will try this out tonight.</p>
<p> </p>
<p>One question; on a previous post, you said you had to tweak the Code 2 of 5 font which you downloaded by editing it with FontForge -- is that still necessary in order to place this in the RotatedText control and have it render correctly?</p>
Matthew L.
<p>Referring to this post: <a data-ipb='nomediaparse' href='
http://developer.actuate.com/community/forum/index.php?/topic/36636-properly-displaying-a-barcode-when-rotated-90-degrees/?p=136535'>http://developer.actuate.com/community/forum/index.php?/topic/36636-properly-displaying-a-barcode-when-rotated-90-degrees/?p=136535</a></p>
;
<p> </p>
<p>Yes, in order to use the rotation plugin with this font, the font must be modified as described in the referenced post due to the font not displaying properly.</p>
<p> </p>
<p>However once you have "fixed" the font, then you must encode your text so that a barcode reader can read the barcode.</p>
<p> </p>
<p>So for example (attached), I "fixed" the font and saved it as "Code 2 of 5 interleaved_Mod".</p>
<p>Then using the rotation plugin instead of changing the value in the onRender method, I wrapped the expression call with the function: encodeCode2Of5i(row["Test"]);</p>
<p> </p>
<p>This allows the returned value (or static numeric text) to be encoded into a format that barcode readers can understand, then by applying the "Code 2 of 5 interleaved_Mod" font to the rotation element, the result is both scannable and rotatable.</p>
<p> </p>
<p>Also note that you could name the fixed font to its original name "Code 2 of 5 interleaved" and just override the original one when your confident that the "fixed" font works for you.</p>
<p> </p>
lenburt
<p>Ok, great...that makes sense....</p>
lenburt
<p>Matthew - i tried out your function...this is without the rotating object complexity...it generates a barcode but it is not readable by my scanner.</p>
<p> </p>
<p>I am attaching my resulting pdf and the simple rptdesign. If you see something obvious let me know. I am using the download 2of5 font that you pointed me to.</p>
Matthew L.
<p>During your test with the scanner did you scan from a monitor or from a paper print out?</p>
<p>I tested your design with a phone app against the monitor and my scanner couldn't read it.</p>
<p>However when printing it out on paper, the same scanner could easily read it.</p>
<p>My theory is that the monitor's PPI resolution isn't sharp enough for the scanner to properly read the barcode.</p>
<p>If you increase the size of your barcode font (30+ points) it should be readable on the screen.</p>
<p> </p>
<p>Attached is a modified version of your example that has the font increased to 50 points in size.</p>
<p>It is easily readable by the phone scanner on a monitor.</p>
<p>I also removed the onRender code and just used the function call in the Expression Builder of the Data Element itself, which should make it easier to use.</p>
<p> </p>
<p>ex: encodeCode2Of5i("04040014035775");</p>
<p> </p>
<p> </p>
lenburt
Ah....good to know...I did just scan my screen. I will print it out this weekend.
lenburt
<p>Matthew - that worked quite well...i even add a reference to a dataset since that is what we need to do. The rotated barcode scanned fine when i printed it out. FYI - i did not even have to transform the font...i worked fine as is -- i wonder if encoding it somehow corrected the glyph problem.</p>
<p> </p>
<p>One other thing, we will be depoying this on AIX; i am assuming i need to copy the jars for the rotated tect object and also the font over to AIX. I was reading something about truetype not being supported on AIX but i will research more. Again, thanks for all of your help. -- len</p>
cathyben
<p>I only found <a data-ipb='nomediaparse' href='
http://www.businessrefinery.com/products/barcode_birt/main.html'>barcode
genertion resource for BIRT</a>, and didn't find barcode reading resource for birt. Matthew's guide is good, but my target barcode is code 128, rather than 2 of 5 Interleaved barcode, I don't know whether this tutorial suitable for code 128?</p>
lenburt
<p>I did look at this vendor and they only have a streaming product for their BIRT extension which does not work for us. -- len</p>
Matthew L.
<p>cathyben,</p>
<p> </p>
<p>Here is an Code 128 version based on the font from: <a data-ipb='nomediaparse' href='
http://grandzebu.net/informatique/codbar-en/code128.htm'>http://grandzebu.net/informatique/codbar-en/code128.htm</a></p>
;
<p> </p>
<p>See example attached for more information.</p>
<p> </p>
<p>Drop this code into the initialize method of a BIRT report to call the encoding function of the input string:</p>
<pre class="_prettyXprint _lang-js">
//
//This custom code is untested and needs to be tested thoroughly before using in a production environment.
//This function encodes standard text into a Barcode Code 128 encoded compatable string and returns the result.
//The font used with this encoder is located: http://grandzebu.net/informatique/codbar-en/code128.htm
//
//Example use:
//In a Label's onCreate script method use the following code to encode text to Code 128:
// this.text = encodeCode128(this.text);
//
//*Note*:
//Make sure to set the font style to Code 128.
//
function encodeCode128(textToEncode){
textToEncode = "" + textToEncode; //Convert input to string
var tableB = true; //Set variable
var code128 = ""; //Set variable
var char2 = ""; //Set variable
var checksum = ""; //Set variable
var mini = 0; //Set variable
if(!textToEncode){ //If no text to encode
java.util.logging.Logger.getLogger("birt.report.logger").warning ("encodeCode128() Error: No text to encode"); //Log message
return "encodeCode128() Error: No text to encode"; //Return message
}
var charArray = textToEncode.split(''); //Place each character into an array
for (var i=0;i<charArray.length;i++) //Loop through array
if(charArray[i].charCodeAt() < 32 || charArray[i].charCodeAt() > 126){ //If a character is not supported
java.util.logging.Logger.getLogger("birt.report.logger").warning ("encodeCode128() Error: Char not supported"); //Log message
return "encodeCode128() Error: Char not supported"; //Return message
}
for (var i=0;i<charArray.length;i++){ //Loop through array
if(tableB){ //If Code TableB
mini = (i==0 || (i+3)==charArray.length)?4:6; //Get 4 or 6 digits
mini = testNumeric(charArray, i, mini); //Are they numbers?
if(mini < 0){ //If not numbers
code128 += (i==0)?String.fromCharCode(210):String.fromCharCode(204); //Add starting code
tableB = false; //Use Code tableC
}else //If numbers
if (i == 0) //If begining
code128 += String.fromCharCode(209); //Add starting code
}
if(!tableB){ //Code TableC
mini = 2; //Set 2 digits
mini = testNumeric(charArray, i, mini); //Are they numbers?
if(mini > 0){ //If numbers
char2 = parseInt(charArray[i] + "" + charArray[i+1]); //Get 2 characters
char2 += (char2<95)?32:105; //Add 32 or 105
code128 += String.fromCharCode(char2); //Add code to output
i++;
}else{ //If not numbers
code128 += String.fromCharCode(205); //Add code
tableB = true; //Use Code TableB
}
}
if(tableB) //Code TableB
code128 += charArray[i]; //Add code to output
}
//Calculate checksum
var codeArray = code128.split(''); //Place each character into an array
for (var i=0; i<codeArray.length; i++){ //Loop through array
char2 = codeArray[i].charCodeAt(); //Get character code
char2 -= (char2<127)?32:105; //Subtract 32 or 105
if(i==0) //If first character
checksum = char2; //Use character
checksum = (checksum + i * char2) % 103; //Get mod of checksum value
}
checksum += (checksum<95)?32:105; //Add 32 or 105
return code128 += "" + String.fromCharCode(checksum) + String.fromCharCode(211); //Add end code
return code128; //Return new string
}
//Test for numbers
function testNumeric(charArray2, i, mini){
mini--; //Subtract 1
if ((i + mini) < charArray2.length) //If valid length
while (mini >= 0){ //Loop
if ((charArray2[i + mini].charCodeAt() < 48) || (charArray2[i + mini].charCodeAt() > 57)) //If not a number
break; //break
mini--; //If number, subtract 1
}
return mini; //Return value
}
//
</pre>