Advanced Barcode Support

With XML Publisher 5.6.2 you now have the ability to execute pre processing on your data prior to applying a barcode font to the data in the output document. For example you may need to calculate checksum values or start and end bits for the data before formatting them.


In lieu of Oracle not having the barcode fonts available I have worked with the popular IDAutomation fonts, they provide the necessary java code support for their fonts.
Information on their fornts can be found here: http://www.idautomation.com/fonts/

Information on their java source code here: http://www.idautomation.com/fonts/tools/sourcecode/FontIDAutomation.txt


The solution requires that you register a barcode encoding class with XML Publisher that can then be instantiated at runtime to carry out the formatting in the template. This is covered in <<link to class description and sample and setup>>
In the template there are two new commands that need to be used to enable the formatting feature.


<?register-barcode-vendor:java_class_name;barcode_vendor_id?>


This command registers the barcode encoding class. It requires a java class name, this will carry out the encoding and a barcode vendor ID as defined by the class. This command needs to appear before the commands to encode the data in the template. For example:
<?register-barcode-vendor:弛racle.apps.xdo.template.rtf.util.barcoder.BarcodeUtil?;'XMLPBarVendor'?>


So the class is defined as 双racle.apps.xdo.template.rtf.util.barcoder.BarcodeUtil? and the vendor id as 'XMLPBarVendor'


For the data to be encoded the following command is required:


<?format-barcode:data;barcode_type;barcode_vendor_id?>


This accepts:
?    data ? the element in the XML to be encoded
?    barcode_type ? this is the method in the encoding class used to format the data e.g. Code128a
?    barcode_vendor_id ? this is the ID as defined in the register-barcode-vendor field.


At runtime the barcode_type method will be called to format the data value and the barcode font will then be applied to the data in the final output. So in the template create the field and highlight it with you chosen bardcode (make sure the font is available at runtime) and you're done .. for the template anyway. Now you'll need to write the class to carry out the encoding ... dont panic we have an example you can copy.


Advanced Barcode Font Formatting Implementation


For the advanced formatting to work in the template a java class is required that will have the appropriate methods to format the data at runtime. Many font vendors offer the code with their fonts to carry out the formatting, these need to be incorporated as methods into a class that is available to the XML Publisher formatting libraries at runtime. There are some specific interfaces that need to be provided in the class for the library to call the correct method for encoding.
This class has to have the following 3 methods implemented:


/**
 * Return a unique ID for this bacode encoder
 * @return the id as a string
 */
  public String getVendorID();


/**
 * Return true if this encoder support a specific type of barcode
 * @param type the type of the barcode
 * @return true if supported
 */
  public boolean isSupported(String type);


/**
 * Encode a barcode string by given a specific type
 * @param data the original data for the barcode
 * @param type the type of the barcode
 * @return the formatted data
 */
  public String encode(String data, String type);


The class should located in the classpath for the middle tier JVM in which XML Publisher is running.


Note: For EBS users the class needs to be in the classpath for the middle tier and any concurrent tiers that are present.


If in the <?register-barcode-vendor:...?> command, the barcode_vendor_id is not provided. XML Publisher will call the getVendorID() and use the result of the method as ID for the vendor.


An example class that supports the code128 a, b and c encodings follows. You'll need to compile the class and to do that you'll need the XMLP java libraries in the classpath to compile. Once you have that you can simply copy the following code and add your encoding methods.


--------------------------------------------------------------------------------


package oracle.apps.xdo.template.rtf.util.barcoder;


import java.util.Hashtable;
import java.lang.reflect.Method;
import oracle.apps.xdo.template.rtf.util.XDOBarcodeEncoder;
import oracle.apps.xdo.common.log.Logger;
// This class name will be used in the register vendor field in the template.


public class BarcodeUtil  implements XDOBarcodeEncoder
// The class implements the XDOBarcodeEncoder interface
{
// This is the barcode vendor id that is used in the register vendor field and format-barcode fields
  public static final String BARCODE_VENDOR_ID = "XMLPBarVendor";
// The hastable is used to store references to the encoding methods
  public static final Hashtable ENCODERS = new Hashtable(10);
// The BarcodeUtil class needs to be instantiated
  public static final BarcodeUtil mUtility = new BarcodeUtil();
// This is the main code that is executed in the class, it is loading the methods for the encoding into the hashtable. In this case we are loading the three code128 encoding methods we have created.
  static {
    try {
      Class[] clazz = new Class[] { "".getClass() };
     
      ENCODERS.put("code128a",mUtility.getClass().getMethod("code128a", clazz));
      ENCODERS.put("code128b",mUtility.getClass().getMethod("code128b", clazz));
      ENCODERS.put("code128c",mUtility.getClass().getMethod("code128c", clazz));
     
     } catch (Exception e) {
 // This is using the XML Publisher logging class to push errors to the XMLP log file.
      Logger.log(e,5);
    }
  }


// The getVendorID method is called from the template layer at runtime to ensure the correct encoding method are used
    public final String getVendorID()
    {
        return BARCODE_VENDOR_ID;
    }
//The isSupported method is called to ensure that the encoding method called from the template is actually present in this class. If not then XMLP will report this in the log.
    public final boolean isSupported(String s)
    {
        if(s != null)
            return ENCODERS.containsKey(s.trim().toLowerCase());
        else
            return false;
    }


// The encode method is called to then call the appropriate encoding method, in this example the code128a/b/c methods.


   public final String encode(String s, String s1)
    {
        if(s != null && s1 != null)
        {
            try
            {
                Method method = (Method)ENCODERS.get(s1.trim().toLowerCase());
                if(method != null)
                    return (String)method.invoke(this, new Object[] {
                        s
                    });
                else
                    return s;
            }
            catch(Exception exception)
            {
                  Logger.log(exception,5);
            }
            return s;
        } else
        {
            return s;
        }
    }


  /** This is the complete method for Code128a */


  public static final String code128a( String DataToEncode )
  {
    char C128_Start = (char)203;
    char C128_Stop = (char)206;
    String Printable_string = "";
    char CurrentChar;
    int CurrentValue=0;
    int weightedTotal=0;
    int CheckDigitValue=0;
    char C128_CheckDigit='w';
 
    DataToEncode = DataToEncode.trim();
    weightedTotal = ((int)C128_Start) - 100;
    for( int i = 1; i <= DataToEncode.length(); i++ )
      {
    //get the value of each character
    CurrentChar = DataToEncode.charAt(i-1);
    if( ((int)CurrentChar) < 135 )
      CurrentValue = ((int)CurrentChar) - 32;
    if( ((int)CurrentChar) > 134 )
      CurrentValue = ((int)CurrentChar) - 100;
 
    CurrentValue = CurrentValue * i;
    weightedTotal = weightedTotal + CurrentValue;
      }
    //divide the WeightedTotal by 103 and get the remainder,
    //this is the CheckDigitValue
    CheckDigitValue = weightedTotal % 103;
    if( (CheckDigitValue < 95) && (CheckDigitValue > 0) )
      C128_CheckDigit = (char)(CheckDigitValue + 32);
    if( CheckDigitValue > 94 )
      C128_CheckDigit = (char)(CheckDigitValue + 100);
    if( CheckDigitValue == 0 ){
      C128_CheckDigit = (char)194;
    }
 
    Printable_string = C128_Start + DataToEncode + C128_CheckDigit + C128_Stop + " ";
    return Printable_string;
  }



  /** This is the complete method for Code128b ***/


  public static final String code128b( String DataToEncode )
  {
    char C128_Start = (char)204;
    char C128_Stop = (char)206;
    String Printable_string = "";
    char CurrentChar;
    int CurrentValue=0;
    int weightedTotal=0;
    int CheckDigitValue=0;
    char C128_CheckDigit='w';


    DataToEncode = DataToEncode.trim();
    weightedTotal = ((int)C128_Start) - 100;
    for( int i = 1; i <= DataToEncode.length(); i++ )
      {
    //get the value of each character
    CurrentChar = DataToEncode.charAt(i-1);
    if( ((int)CurrentChar) < 135 )
      CurrentValue = ((int)CurrentChar) - 32;
    if( ((int)CurrentChar) > 134 )
      CurrentValue = ((int)CurrentChar) - 100;
 
    CurrentValue = CurrentValue * i;
    weightedTotal = weightedTotal + CurrentValue;
      }
    //divide the WeightedTotal by 103 and get the remainder,
    //this is the CheckDigitValue
    CheckDigitValue = weightedTotal % 103;
    if( (CheckDigitValue < 95) && (CheckDigitValue > 0) )
      C128_CheckDigit = (char)(CheckDigitValue + 32);
    if( CheckDigitValue > 94 )
      C128_CheckDigit = (char)(CheckDigitValue + 100);
    if( CheckDigitValue == 0 ){
      C128_CheckDigit = (char)194;
    }
 
    Printable_string = C128_Start + DataToEncode + C128_CheckDigit + C128_Stop + " ";
    return Printable_string;
  }



  /** This is the complete method for Code128c **/


  public static final String code128c( String s )
  {
    char C128_Start = (char)205;
    char C128_Stop = (char)206;
    String Printable_string = "";
    String DataToPrint = "";
    String OnlyCorrectData = "";
    int i=1;
    int CurrentChar=0;
    int CurrentValue=0;
    int weightedTotal=0;
    int CheckDigitValue=0;
    char C128_CheckDigit='w';
    DataToPrint = "";
    s = s.trim();
    for(i = 1; i <= s.length(); i++ )
      {
    //Add only numbers to OnlyCorrectData string
    CurrentChar = (int)s.charAt(i-1);
    if((CurrentChar < 58) && (CurrentChar > 47))
      {
        OnlyCorrectData = OnlyCorrectData + (char)s.charAt(i-1);
      }
      }
    s = OnlyCorrectData;
    //Check for an even number of digits, add 0 if not even
    if( (s.length() % 2) == 1 )
      {
    s = "0" + s;
      }
    //<<<< Calculate Modulo 103 Check Digit and generate DataToPrint >>>>
    //Set WeightedTotal to the Code 128 value of the start character
    weightedTotal = ((int)C128_Start) - 100;
    int WeightValue = 1;
    for( i = 1; i <= s.length(); i += 2 )
      {
    //Get the value of each number pair (ex: 5 and 6 = 5*10+6 =56)
    //And assign the ASCII values to DataToPrint
    CurrentChar = ((((int)s.charAt(i-1))-48)*10) + (((int)s.charAt(i))-48);
    if((CurrentChar < 95) && (CurrentChar  > 0))
      DataToPrint = DataToPrint + (char)(CurrentChar + 32);
    if( CurrentChar > 94 )
      DataToPrint = DataToPrint + (char)(CurrentChar + 100);
    if( CurrentChar == 0)
      DataToPrint = DataToPrint + (char)194;
    //multiply by the weighting character
    //add the values together to get the weighted total
    weightedTotal = weightedTotal + (CurrentChar * WeightValue);
    WeightValue = WeightValue + 1;
      }
    //divide the WeightedTotal by 103 and get the remainder,
    //this is the CheckDigitValue
    CheckDigitValue = weightedTotal % 103;
    if((CheckDigitValue < 95) && (CheckDigitValue > 0))
      C128_CheckDigit = (char)(CheckDigitValue + 32);
    if( CheckDigitValue > 94 )
      C128_CheckDigit = (char)(CheckDigitValue + 100);
    if( CheckDigitValue == 0 ){
      C128_CheckDigit = (char)194;
    }
    Printable_string = C128_Start + DataToPrint + C128_CheckDigit + C128_Stop + " ";
    Logger.log(Printable_string,5);
    return Printable_string;
  }
}



--------------------------------------------------------------------------------


Once the class is created and placed in the correct class path your template creators can start using it to format the data for barcodes. You will need to communicate to them the following:
1.    The class name and path. In this example: oracle.apps.xdo.template.rtf.util.barcoder.BarcodeUtil
2.    The barcode vendor id you created. In this example 噌MLPBarVendor?
3.    The available encoding methods, in this example, code128a, code128b and code128c
They can then use this information to sucessfully encode their data for barcode output.

Comments:

hi tim, I can see in the java code, char C128_Start = (char)204; Why here the start code is 204, not 104?

Posted by parpa_zhang on May 17, 2009 at 08:01 PM MDT #

Hi Tim, We are looking to use IDAutomation's Code 128 Barcode in the Oracle Apps with the PO Output for Communication report. We are wondering what to expect for the required number of font licenses: 1 per server, 1 per potential user, etc... Obviously we will work with the vendor on the number of licenses, but I was hoping you might be able to shed some insight on this. I'm not sure how well the vendor understands Oracle applications and I'd like to be prepped for the potential automatic response of "1 font license per Oracle user" that I may receive. Best regards, Suzanne

Posted by Suzanne Camyre on May 22, 2009 at 02:16 AM MDT #

Hi Tim, Is it possible to have vertical barcode in BIP? We are using horizontal barcodes but have a requirement to display few barcodes vertically. I do not see any feature/documentation regarding this. Can you suggest if it is possible? Regards, Pratul

Posted by Pratul on July 02, 2009 at 09:59 PM MDT #

Need help start bits and stop bits are coming out as CAP using EBS R12 XML Publisher

Posted by Kerry on September 14, 2009 at 11:44 AM MDT #

Hi, Need on the Java Encoder part. I copied the encoding code and compiled the code into java Class as requested javac -g -Xlinit BarcodeUtil.java I getting BarcodeUtil.java:32: warning: [unchecked] unchecked call to put(K,V) as a member of the raw type java.util.Hashtable ENCODERS.put("code128a",mUtility.getClass().getMethod("code128a", clazz)); Any help with this

Posted by Steve on September 24, 2009 at 02:01 AM MDT #

Hi Tim, Thanks for your info in the blog. Can we encode application identifiers using the approach you have mentioned in this blog? If not, please suggest a menthod to encode data string containing application identifiers. Thank You

Posted by Surya on November 10, 2009 at 03:18 PM MST #

I must mention, that in all the time I have spent on the internet, browsing blogs, forums, I’ve never read one as helpful and well written as this one, I do not as a rule comment on web logs however for yourself I felt the need to make an exception, this really is unquestionably outstanding work and entirely opposite to the drivel, i spend a lot of my time on line, reading. Thanks a lot with regard to finding the time and expending the effort to supply your readers with a 1st class piece. I count on reading much more of your work, just as before thanks. Angela

Posted by Jacinto Ace on August 03, 2010 at 06:55 AM MDT #

Hi Tim (or anyone else), Do you know of anyone successfully using the PDF417 barcode feature of Adobe Acrobat Pro 9 Extended. I loaded the PDF template with this barcode. Unfortunately, the barcode value is not updated by the query results. The associated fields used to calculate the barcode are updated, but not the barcode calculated value itself. I can go ahead with the IDAutomation/PDF417 encoder class solution, but Adobe would be much easier as I'm starting with Adobe templates. My understanding is that the IDAutomation/PDF417 class will require RTF (or similar) templates and I cannot use PDF templates. Thanks for the great articles on barcoding in XML publisher -- they are highly useful. Sincerely, James Wilson bayshorecomputing@yahoo.com

Posted by James Wilson on August 26, 2010 at 01:01 AM MDT #

It could be their writing style, the passion for the subject they write about or that they post on a frequent basis.

Posted by Johana on September 12, 2010 at 07:48 PM MDT #

Hi All, I am not able generate PDF417 font barcode for my client.. Can anyone send me a live snapshot for the same
anoop.jain88@gmail.com

Thanks in advance
Anoop Jain

Posted by guest on August 09, 2011 at 08:58 PM MDT #

Hi
Tim,

if you have step by step instruction to install code128 for XML Publisher, can you please with us.

Thanks
Surendra

Posted by Surendra on December 21, 2011 at 03:42 AM MST #

Surendra
I believe its covered in the user docs.
Tim

Posted by Tim on December 21, 2011 at 05:06 AM MST #

I am new to XML Publisher font installation, we bought the software code 128 after that I don't know how to install class file. I never write a class file.

Please help me with this issue.

Posted by Surendra on December 21, 2011 at 05:10 AM MST #

Surendra
You'll need some java experience, not much thou. I suggest you get something like jdeveloper installed and open up the java class you have and check to see whats its doing. Its going to be very similar to the one above.
Check the docs and see what the requirements are from BIPs side and then create a wrapper class to call the font vendors encoding functions as needed. Its all out there, you just need to put it together.
Tim

Posted by guest on December 21, 2011 at 05:24 AM MST #

Hi surendra

I am also trying to use code128b font in XML publisher, if you are able to get the steps then can you please share with am also new to java thing

Thanks,
Param

Posted by Param on April 19, 2012 at 12:04 PM MDT #

Surendra
Check out the other barcode posts.

https://blogs.oracle.com/xmlpublisher/entry/barcoding_102

Best way to test is to first not apply the font in the RTF template ie leave it as a readable font. That way you can test if your data is being encoded correctly.
Make sure BIP is in debug mode so you can see any error messages.
Tim

Posted by guest on April 20, 2012 at 06:18 AM MDT #

Hi Tim,

I have tried it without applying font ,it seems data is being encoded properly. But barcode does not show in final output

Thanks,
Param

Posted by Param on April 20, 2012 at 07:02 AM MDT #

So your java is working, thats good!
Im guessing your font is not mapped onto the server correctly. The font needs to be mapped for the PDF output because we embed a sub set into the PDF document.
The UI is pretty straightforward to do the mapping. The font file itself needs to be copied into the server fonts directory.
Check the docs for font mapping. You did not say what version you are running so I can not provide exact links:
Jump off page is
http://www.oracle.com/technetwork/middleware/bi-foundation/documentation/bi-pub-096318.html
Tim

Posted by Tim on April 20, 2012 at 07:24 AM MDT #

Hi Tim,

I am not sure what's wrong here , I followed the steps mentioned here.
I copied this packaged and created a java file name BarcodeUtil.java and compiled it , but i placed it on our custom folder in JAVA TOP,

Then i added following two tags in my rtf template

<?register-barcode-vendor: arrow.oracle.apps.xxvas.wip.jobtraveler.BarcodeUtil;XMLPBarVendor?>

and field as
<?format-barcode:SAMPLE;code128b;XMLPBarVendor?>

where SAMPLE is test fiel from XML file, which has value as " Sample Test", now whenever I run report it simply gives me out
put as "Sample Test", No barcodes. IT seems that it is not even calling the class. PLease help

Thanks,
Param

Posted by Param on April 23, 2012 at 02:43 PM MDT #

Hey Tim,

Do you have some stuff for .NET barcodes?

Posted by guest on November 26, 2012 at 08:40 PM MST #

I have followed the steps you mention I can get a scanable barcode but it will not encode the space character I used the Code128 font from http://www.idautomation.com/fonts/ which you describe above as well as others. However, none of them will encode the space. Is there an additional step I am missing to do?

Posted by guest on October 28, 2013 at 11:26 AM MDT #

Hi Tim,

I have followed the steps you mention I can get a scanable barcode but it will not encode the space character I used the Code128 font which you describe above as well as others. However, none of them will encode the space. Is there an additional step I am missing to do?

Thanks

Joe

Posted by Joe on October 28, 2013 at 11:33 AM MDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Follow bipublisher on Twitter Find Us on Facebook BI Publisher Youtube ChannelDiscussion Forum

Join our BI Publisher community to get the most and keep updated with the latest news, How-to, Solutions! Share your feedback and let us hear your voice @bipublisher on Twitter, on our official Facebook page, and Youtube!

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today