Recently, I wrote and deployed a component for a Point Of Sale (POS) application that takes advantage of the preprinted Universal Product Code (UPC) in retail items. However, the client wanted the ability to allow clerks to transparently enter and scan either the UPCs or the company's own item numbers. The client wanted both capabilities because the company prints pricing labels that contain a barcode that represents the item number and price, rather than a UPC number barcode. To create a test application that would accept either item number or UPC, I wrote a small program that accepts the client's item number or UPC and prints a pricing label on a Zebra printer. Fortunately, the company recently purchased the T.L. Ashford barcode software. While I expected to need some level of rocket science to print a barcode, it turned out to be remarkably simple.
UPC numbers are (currently) 12 digits in length, including the check digit. The client's item number is up to 15 positions and may contain either characters or numbers. So the only potential conflict was if an item number was 12 positions long and all digits. But I worked around that by checking the input value against a 400,000+ record UPC file the company received from its supplier.
The input screen uses a 15-position character field that accepts either UPC or item number. Upon entry, I check the input value for all digits. If it is all numeric and the length of the number is 12 or 14 (for GTIN numbers in the future), I chain out to the UPC file for validation. If the number is found, I use the corresponding item number in the UPC file and chain back to the item master for the item's price. Then, I call the T.L. Ashford API, and the barcode pricing labels pop right out.
To check for all numbers in an input field, I use the CHECK opcode or the %CHECK built-in function as follows:
D szItem S 15A
C if %Check(NUMBERS:%TrimR(szItem)) = 0
** szItem is all digits
The %CHECK built-in scans the szItem field for anything that is not a digit and returns the position of that value if it finds one. Therefore, if this %CHECK built-in operation returns a value of zero, the szItem field contains all digits. This is similar to the IsDigits() routine in some other languages. Also note that I use %TRIMR to avoid scanning past the end of the input value. This bypasses the trailing blanks that will no doubt exist in each value entered.
If the input value is not a 12- or 14-position number, then it must be an item number. So I simply chain out to the item master file and when the item is found, I call the T.L. Ashford API and print the pricing labels.
An application that I thought would take at least a week to create took about fours hours, including designing the input screen and interfacing it with the Zebra barcode printer (thanks to the easy-to-use T.L. Ashford APIs).
Oh, and the barcode scanner interface? Not an issue. The APIs interface with the keyboard and send the data to the application as if the end users had typed it in themselves. So you don't need a specialist or special programming techniques to add scanner support to your applications; you just need to plug in the scanners.
Bob Cozzi is a programmer/consultant, writer/author, and software developer. His popular RPG xTools add-on subprocedure library for RPG IV is fast becoming a standard with RPG developers. His book The Modern RPG Language has been the most widely used RPG programming book for more than a decade. He, along with others, speaks at and produces the highly popular RPG World conference for RPG programmers.