I was contacted today by someone looking for my old notes on generating barcodes using PCL from UniBasic. I hope folks here will find this information useful as well.
The Code 39 (aka 3 of 9) Barcode uses 9 bars for each character: five black and four white. Of these 3 are "wide" bars, while the rest are "narrow" bars (hence, 3 of 9).
This function will convert an alphanumeric string to a PCL string that will generate the barcode.
* Converts TXT to the PCL5 string to print as a 3 of 9 Barcode
* Input: TXT - Original Text
* HIGH - Height in Dots
* WIDE - Narrow Bar Width
* Output: STR - Return String
* Define Valid Characters and corresponding 3 Wide Bar Sets
CMAP = "* $%+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
MAP = "218.104.22.1688.268.222.214.171.1247.149.349.134.459.145.345."
MAP := "479.147.347.169.369.136.569.156.356.679.167.367.567.189.389"
MAP := ".138.589.158.358.789.178.378.5126.96.36.199.259.125.235"
CONVERT "." TO @AM IN MAP
E = CHAR(27)
* STR1 Saves the current Cursor position, STRZ Restores it.
* Force Text to Upper Case and remove asterisks, since they
* are used to denote the start and end of the barcode.
STR1 = E:"&f0S":E:"*p+":WIDE*10:"X"
STRZ = E:"&f1S"
STR = ""
NTXT = OCONV(TXT,"MCU")
CONVERT "*" TO "" IN NTXT
NTXT = "*":NTXT:"*"
IX = LEN(NTXT)
* Convert each character to a set of 5 solid rectangles. The
* character must be in the valid character set.
* BWIDE is the width of each bar, which is tripled for 3 of
* the 9 bars in the code. Even bars are white, odd are black.
* The 10th bar is the space between characters.
* PCL Commands draw a bar, then move the drawing cursor the
* width of that bar plus the space afterwards.
IF IX > 2 THEN
FOR I = 1 TO IX
LOC = INDEX(CMAP,NTXT[I,1],1)
IF LOC # 0 THEN
BMAP = MAP<LOC>
MAT BWIDE = WIDE
FOR J = 1 TO 3
BWIDE(BMAP[J,1]) *= 3
FOR J = 1 TO 9 STEP 2
STR := E:"*c":BWIDE(J):"a":HIGH:"b0P"
STR := E:"*p+":BWIDE(J)+BWIDE(J+1):"X"
STR = STR1:STR:STRZ
I have compiled this under the name CEI.HP.3OF9
but that can be changed. Just make certain you use the cataloged name in the DEFFUN
statement in the program that calls this function.
Here is a sample program I use to print the codes needed to set up our scanners. I also use PC-8 Line Draw characters to outline each item in a chart.
* Print Setup Code Barcodes for LS1900 Barcode Reader
* CLIST is the command list. TLIST is the Display Text.
DEFFUN BAR39(TXT,HIGH,WIDE) CALLING "CEI.HP.3OF9"
CLIST = "D2C8;C015;C050;C107;C208;C300;C401;C51"
TLIST = "Defaults;IBM Terminal;ASCII Mode;38400 Baud;8 Data Bits"
TLIST := ";No Parity;1 Stop Bit;XON/XOFF Enabled"
CONVERT ";" TO @AM IN CLIST
CONVERT ";" TO @AM IN TLIST
* Define Horizontal Lines using Line Draw characters.
* TLINE is the top line
* DLINE has "T" connectors
* FLINE is the footer
* BLINE is a blank line with end characters
HLINE = STR(CHAR(196),78)
TLINE = CHAR(218):HLINE:CHAR(191)
DLINE = CHAR(195):HLINE:CHAR(180)
FLINE = CHAR(192):HLINE:CHAR(217)
BLINE = CHAR(179):SPACE(78):CHAR(179)
* Print text and barcode below in boxes. Note that we print
* the Line Draw line, then a carriage return, then position
* the Bar Code. The Bar Code uses the current print line as
* the TOP of the code, so it actually appears in the line
* below the one on which it is written.
PRINT "LS1900 Barcode Reader Setup - Scan All Codes in Order"
FOR I = 1 TO 8
BTEXT = "$+$-":CLIST<I>:"EE"
PRINT CHAR(179):" ":TLIST<I> "L#76":CHAR(179)
IF I = 8 THEN PRINT FLINE ELSE PRINT DLINE
Please note that the barcode prints DOWN from the current page location, which is the character baseline. You effectively need to print the barcode on the line above where you want it to appear. I also recommend printing the regular text, then a Carriage Return/CHAR(13) before positioning and printing the barcode.
Also, please note that I use AIX, and have my print queues set so they don't automatically wrap long lines. This is very important, since each character in the barcode becomes about 15 characters of PCL.