/* * PDFLabels.java * * Created on January 14, 2007, 12:31 PM * This class handles the gory details of formatting, calculating and building a table for the specified lable sheet dimensions, placing data in the table and actually generating a pdf file. Creates one table based on the constructor and allows you call various add() methods which places data * in a cell, formats the cell based on certain class fields and adds the cell to the table. * Currently only supports 8.5" x 11" Avery TM style label sheets in portrait orientation. * * * DEFAULT LABEL: Page Layout fields in inches Default is 1" High by 2.6" Wide - Three across Label Sheet protected float H = 1.0f * 72; //height protected float W = 2.6f * 72; //width protected float LRM = .17f * 72; //Left Right Margin protected float TBM = .50f * 72; //Top Bottom Margin protected float GAP = .17f * 72; // Gap between labels new float [] = {1.0f, 2.6f, .17f, .50f, .17f} ; <-- sample constructor value Default Font: new Font (Font.COURIER, 10, Font.NORMAL); Default Label Alignment: Vertical = MIDDLE ~ Horizontal = LEFT * CONSTRUCTOR EXAMPLES: * //AVERY Part No. PDFLabels pl = new PDFLabels (new float [] = {1.0f, 2.6f, .17f, .50f, .17f},"c:\\labels.pdf"); //5160 || 8160 PDFLabels pl = new PDFLabels (1.33f, 4.0f, .16f, .83f, .17f,"c:\\labels.pdf"); //5162 PDFLabels pl = new PDFLabels (1.0f, 4.0f, .16f, .50f, .17f,"c:\\labels.pdf"); //5161 PDFLabels pl = new PDFLabels (1.5f, 4.0f, .13f, .25f, .13f,"c:\\labels.pdf"); //5159 PDFLabels pl = new PDFLabels (.75f, 2.25f, .38f, .63f, .5f,"c:\\labels.pdf"); //3261R * iText required, visit: iText Website * */ /** * * @author Sean K Anderson - * * * * Use how you wish. Pirate away. AARRRH!! * * Send an email to 'software@datavirtue.com' or link to 'http://www.datavirtue.com' if this class helps you. * Send an email if you need help. 01-17-2007 * *iText required, visit: iText Website * */ //package com. //import com.lowagie.text.BadElementException; import java.util.StringTokenizer; import com.lowagie.text.DocumentException; import java.io.FileNotFoundException; import java.io.FileOutputStream; import com.lowagie.text.Cell; import com.lowagie.text.Document; //import com.lowagie.text.ExceptionConverter; import com.lowagie.text.PageSize; //import com.lowagie.text.Paragraph; import com.lowagie.text.Rectangle; import com.lowagie.text.pdf.PdfPTable; import com.lowagie.text.pdf.PdfPCell; import com.lowagie.text.Phrase; import com.lowagie.text.Table; //import com.lowagie.text.pdf.PdfPageEventHelper; import com.lowagie.text.pdf.PdfWriter; //import com.lowagie.text.Chunk; import com.lowagie.text.Font; import com.lowagie.text.FontFactory; //import com.lowagie.text.pdf.BaseFont; //import com.lowagie.text.pdf.PdfGState; import com.lowagie.text.Image; import com.lowagie.text.Element; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.Barcode39; import com.lowagie.text.pdf.Barcode; import com.lowagie.text.pdf.BarcodeEAN; import com.lowagie.text.pdf.BarcodePostnet; import com.lowagie.text.pdf.Barcode128; import com.lowagie.text.pdf.ColumnText; import java.io.UnsupportedEncodingException; //import java.io.IOException; //import java.net.MalformedURLException; //import java.awt.Color; public class PDFLabels { /** Simple constructor uses the DEFAULT LABEL 2.6"W by 1.0"H three across. Creates a new instance of PDFLabels. */ public PDFLabels (String file) { /* this constructor is good to use the default labels */ this.PDF = file; init(); checkStatus(); } /** Provide custom label dimensions in a float array. new float [] = {1.0f, 2.6f, .17f, .50f, .17f} Values are in inches. Creates a new instance of PDFLabels. */ public PDFLabels (float [] gaps, String filename){ /* H W LRM TBM GAP */ this(gaps[0], gaps[1], gaps[2], gaps[3], gaps[4], filename); } /** Custom label dimensions - in inches. Creates a new instance of PDFLabels. */ public PDFLabels(float H, float W, float LRM, float TBM, float GAP, String file) { /* Multiply by 72 to convert inches to points */ this.H = H * 72; this.W = W * 72; this.LRM = LRM * 72; this.TBM = TBM * 72; this.GAP = GAP * 72; this.PDF = file; init(); checkStatus(); } public static void main(String[] args) { String nl = System.getProperty("line.separator"); PDFLabels pl = new PDFLabels (1.0f, 2.6f, .16f, .50f,.17f,"labels.pdf"); //5160 || 8160 pl.setAlignment(9,1); //sets the defalut alignment properties for the cells String text = "Sean Anderson" + nl + "11851 Golden Hill Drive" + nl + "Hillsboro, Ohio 45133"; for (int r = 0; r < 60; r++){ //two pages of labels pl.appendPostnet(text, "45140-8778"); //regular label with postnet barcode } pl.finnish(); } protected void init (){ try { writer = PdfWriter.getInstance(document, new FileOutputStream(PDF)); } catch (Exception ex) { STATUS_GOOD = false; ex.printStackTrace(); } document.addAuthor("Data Virtue"); //change this or create fields with get/set to change this document.addCreationDate(); //these statements must be called or set before calling open() document.addSubject("Nevitium Labels - datavirtue.com"); document.open(); cb = writer.getDirectContent(); //direct writer for rendering the table manually - NOT IN USE ct = new ColumnText(cb); //column text to render table easily - IN USE ct.setSimpleColumn(0, TBM, PageSize.LETTER.width(), PageSize.LETTER.height() - TBM*2, 0, Element.ALIGN_MIDDLE); ACROSS = ( PageSize.LETTER.width() - (LRM * 2) ) / W; //how many labels across based on supplied dims ACROSS -= ACROSS % 1; // trim the fat DOWN = ( PageSize.LETTER.height() - (TBM * 2) ) / H; //how many labels up/down based on supplied dims DOWN -= DOWN % 1; //trim the fat COLS = new float [(int)ACROSS + 1 + ((int)ACROSS)]; float cols = 0; //total size of all COLS table = new PdfPTable ( COLS.length );//table with gaps and margins included /* kill the border on default cells */ if (!DEBUG) table.getDefaultCell().setBorder(Rectangle.NO_BORDER); for (int i = 0; i < COLS.length; i++){ //if (DEBUG) System.out.println("COLS WIDTH BL :"+cols); if (i == 0 || i == COLS.length-1) { COLS[i] = LRM; cols += LRM; continue; } /* Ypu do ont reach this staeament if i == 1 */ if ((i+1) % 2 != 0 && i != COLS.length-1){ //if odd its a gap COLS[i] = GAP; cols += GAP; continue; }else { COLS[i] = W; cols += W; continue; } } if (DEBUG) System.out.println("COLS TOTAL WIDTH :"+cols); try { table.setTotalWidth(cols); //tried removing this, not good table.setWidths(COLS); table.setLockedWidth(true); table.getDefaultCell().setPaddingBottom(0.0f); table.getDefaultCell().setPaddingTop(0.0f); } catch (DocumentException ex) { STATUS_GOOD = false; } /* Last command for init() */ STATUS_GOOD = true; } /** Called by all other add() methods to place a PdfPCell into the label table. This method also sets the height, padding, border and alignment of the PdfPCell. */ public void add (PdfPCell cell){ /* adds the actual cell to the table */ /* Every add() calls this method */ cell.setFixedHeight(H); cell.setNoWrap(NO_CELL_WRAP); cell.setPaddingLeft(CELL_LEFT_PADDING); cell.setVerticalAlignment(VALIGNMENT); cell.setHorizontalAlignment(HALIGNMENT); if (!DEBUG) cell.setBorder(Rectangle.NO_BORDER); //show table borders in DEBUG mode how_many++; //total amount of labels counter++; // 'int counter' keeps track of how many times // this method is called within a range of X (X = ACROSS) table.addCell(""); table.addCell(cell); if (counter == ACROSS) table.addCell(""); //at the end if (counter == ACROSS) counter = 0; //if at the end reset the counter } public void add (PdfPTable nt){ /* adds the actual cell to the table */ /* Every add() calls this method */ //nt.setSpacingBefore(0.0f); //nt.setSpacingAfter(0.0f); how_many++; //total amount of labels counter++; // 'int counter' keeps track of how many times // this method is called within a range of X (X = ACROSS) table.addCell(""); table.addCell(nt); if (counter == ACROSS) table.addCell(""); //at the end if (counter == ACROSS) counter = 0; //if at the end reset the counter } /** Each call to this method places the string into a proper PdfPCell object and adds it to the table. */ public void add (String s){ if (DEBUG) System.out.println("add(Cell) Counter :" + counter); if (DEBUG) System.out.println(s + nl+"----------------------"); /* Build cell and call add(cell); */ PdfPCell cell = new PdfPCell(); cell = new PdfPCell (new Phrase(s, DOC_FONT)); add(cell); } /** Calls add(String s) for each element */ public void add (String [] sa){ /* repeatedly call add(String) */ for (int r = 0; r < sa.length; r++){ add( sa[r] ); } } /** Provide an ArrayList of Strings only. */ public void add (java.util.ArrayList al){ /* repeatedly call add(String) */ al.trimToSize(); for (int r = 0; r < al.size(); r++){ try { add( (String) al.get(r) ); } catch (Exception e) { STATUS_GOOD=false; } } } /** Barcode method to add a EAN UPCA barcode exclusivly (by itself) to a label. */ public void addEAN12 (String UPCA){ /* adds the barcode exclusivly to the label */ /* Calls add(cell) */ BarcodeEAN code = new BarcodeEAN(); code.setCodeType(Barcode.UPCA); //regular 12 digit code.setCode(UPCA); add(new PdfPCell (code.createImageWithBarcode(cb, null,null)) ); } /** Standard 13 digit barcode seen on retail items; especially newer items. */ public void addEAN13 (String EAN) { /* adds the barcode exclusivly to the label */ /* Calls add(cell) */ /* Regular 13 digit */ BarcodeEAN code = new BarcodeEAN(); code.setCode(EAN); add(new PdfPCell (code.createImageWithBarcode(cb, null,null)) ); } /** EAN/UCC-14 digit number barcode. Your 14 digit code gets the AI '(01)' prefixed. */ public void addEAN14 (String EAN) { /* adds the barcode exclusivly to the label */ /* Calls add(cell) */ /* Regular 13 digit */ Barcode128 code = new Barcode128(); code.setCodeType(Barcode.CODE128_UCC); code.setCode("(01)" + EAN); add(new PdfPCell (code.createImageWithBarcode(cb, null,null)) ); } /** Plain Code 128 barcode */ public void addCode128 (String s){ Barcode128 code = new Barcode128(); code.setCode(s); add(new PdfPCell (code.createImageWithBarcode(cb, null,null)) ); } /** Convenience method provides the FNC char(s) to markup/demarc Code 128 fields. */ public char getFNCx (int f){ if (f == 1) return Barcode128.FNC1; if (f == 2) return Barcode128.FNC2; if (f == 3) return Barcode128.FNC3; if (f == 4) return Barcode128.FNC4; return Barcode128.FNC1; //default } /** RAW Code 128 barcode, specify a Title and code */ public void addCode128Raw (String title, String cde){ Barcode128 code = new Barcode128(); code.setCode(cde + "\uffff" + title); code.setCodeType(Barcode.CODE128_RAW); add (new PdfPCell (code.createImageWithBarcode(cb, null,null)) ); } /** Barcode method to add a Code 3 of 9 barcode exclusivly (by itself) to a label. */ public void addCode39(String s){ /* adds the barcode exclusivly to the label */ /* Calls add(cell) */ Barcode39 code39 = new Barcode39(); code39.setCode( s.toUpperCase() ); //Only uppercase (base 3 of 9) //insert other modification methods for barcode here: add(new PdfPCell (code39.createImageWithBarcode(cb, null,null)) ); } /** Generates a postnet barcode and adds it to the label set but it first tries to remove any hyphen it detects. Most will want to use appendPostnet(String label, String post) instead. */ public void addPostnet (String post){ if (post.length() < 5 || post.length() > 11) return; post = removeHyphen(post); BarcodePostnet pnbc = new BarcodePostnet(); pnbc.setCode(post); add(new PdfPCell (pnbc.createImageWithBarcode(cb, null,null)) ); } protected String removeHyphen (String s){ if (s.contains("-")){ int idx = s.indexOf("-"); try { /* Strip hyphen */ return s.substring(0, idx) + s.substring(idx+1); } catch (Exception e) { return s; } } return s; } /** Takes a regular label and slaps a US postal barcode at the bottom. If you provide a crap code it will skip the barcode */ public void appendPostnet (String label, String post){ post = removeHyphen(post); /* *Construct 1 col table *add cell with a fixed height of H * .85 *add cell with a fixed height of H * .15 *label in first cell *zip in the secind cell *add cell **/ PdfPTable t = new PdfPTable (1); //t.setSpacingBefore(0.0f); //t.setSpacingAfter(0.0f); PdfPCell cell = new PdfPCell (new Phrase(label, DOC_FONT)); cell.setFixedHeight(H * .85f); this.formatCell(cell); t.addCell(cell); if (post.length() > 4) { BarcodePostnet pnbc = new BarcodePostnet(); pnbc.setCode(post); cell = new PdfPCell(pnbc.createImageWithBarcode(cb, null,null)); cell.setFixedHeight(H * .15f); //cell.setVerticalAlignment(Element.ALIGN_TOP); this.formatCell(cell); t.addCell(cell); } t.setTotalWidth(W); add(t); } /** Set the fixedHieght before calling this method.*/ protected void formatCell (PdfPCell cell){ //cell.setFixedHeight(H); cell.setNoWrap(NO_CELL_WRAP); cell.setPaddingLeft(CELL_LEFT_PADDING); cell.setVerticalAlignment(VALIGNMENT); cell.setHorizontalAlignment(HALIGNMENT); if (!DEBUG) cell.setBorder(Rectangle.NO_BORDER); //show table borders in DEBUG mode } /** The label to start from on the sheet. Set this property before generating labels. This method immediatly adds x amount of blank labels to the table. */ public void setStartLabel (int start) { if (start > 1){ start_label = start; for (int i = 1; i < start; i++){ this.add(" "); } } } /** Use iText FontFactory or provide your own font for the labels. Default: new Font (Font.COURIER, 10, Font.NORMAL) */ public void setFont (Font f){ DOC_FONT = f; } /** Lets you access the amount of labels across on a page ?? */ public float getAcrossCount() { return ACROSS; } /** Lets you access the amount of labels up/down on a page ?? */ public float getDownCount() { return DOWN; } private void checkStatus () { if (DEBUG){ System.out.println("ACROSS :"+ACROSS); System.out.println("DOWN :"+DOWN); System.out.println("COLS LENGTH :"+COLS.length); } if (!STATUS_GOOD) { System.out.println( "PDFLabels object is corrupt!" ); } } /** Toggles DEBUG which prints various information to the console/terminal. */ public void setDebug (boolean tf) { DEBUG = tf; } protected boolean writeLabels () { try { //this could actually be put in finnish() document.add(table); } catch (DocumentException ex) { STATUS_GOOD = false; } return true; } /** Call finnish() when you are done adding labels. Catch the boolean return value to make sure everything went as planned. */ public boolean finnish () { /* Fill out lat row */ if (counter < ACROSS){ for (int i = counter; i < ACROSS ; i++){ table.addCell(""); table.addCell(""); counter++; } table.addCell(""); //last cell } STATUS_GOOD = writeLabels(); if (DEBUG) System.out.println("LABELS ADDED :" + (how_many - start_label) ); document.close(); return STATUS_GOOD; } /** * Changes alignment values for the cells added to the table. *You can call this once or before each add(?). * A value of 9 leaves the ALIGNMENT unchanged ALIGN_BASELINE 7 ALIGN_BOTTOM 6 ALIGN_CENTER 1 ALIGN_JUSTIFIED 3 ALIGN_JUSTIFIED_ALL 8 ALIGN_LEFT 0 *DEFAULT H* ALIGN_MIDDLE 5 *DEFAULT V* ALIGN_RIGHT 2 ALIGN_TOP 4 ALIGN_UNDEFINED -1 */ public void setAlignment (int vertical, int horizontal) { /* if 9 don't change */ if (horizontal != 9) HALIGNMENT = horizontal; if (vertical != 9) VALIGNMENT = vertical; } /** Default behavior is to NOT wrap text ~ setNoWrap(true) */ public void setNoWrap (boolean tf){ NO_CELL_WRAP = tf; } /** Any left padding the labels may need ~ default is 8.0f */ public void setCellLeftPad (float padding){ CELL_LEFT_PADDING = padding; } protected void newPage () { try { document.newPage(); } catch (DocumentException ex) { STATUS_GOOD = false; ex.printStackTrace(); } } /* Page Layout fields - inches */ /** Label height defaults to 1" High each */ protected float H = 1.0f * 72; /** Label width defaults to 2.6" Wide each */ protected float W = 2.6f * 72; /** LEFT and RIGHT margins Default: .17f each */ protected float LRM = .17f * 72; //The PdfPCells are left-padded by add(PdfPCell cell) to 8.0f points /** TOP and BOTTOM margins Default: .50f each */ protected float TBM = .50f * 72; /** The gap in between the labels, default is .17f each */ protected float GAP = .17f * 72; /** The default font: new Font (Font.COURIER, 10, Font.NORMAL) */ protected Font DOC_FONT = new Font (Font.COURIER, 10, Font.NORMAL); /* These fields are set by init() */ protected int start_label = 0; protected float ACROSS = 0; protected float DOWN = 0; protected int how_many = 0; protected int ROWS = 0; /** Status values */ protected boolean STATUS_GOOD = false; protected boolean DEBUG = false; /** The PDF filename. */ protected String PDF = "Labels.pdf"; /* GLOBAL SCRAP */ protected int counter = 0; protected float [] COLS ; protected String nl = System.getProperty("line.separator"); /* PDF iText Stuff */ protected Document document = new Document(PageSize.LETTER); //potrait protected ColumnText ct; protected PdfContentByte cb; protected PdfWriter writer; /** Single PdfPTable to hold and format the labels. Each call to add() adds a PdfPCell. You need to make sure you specify JVM options to provide adequate memory for large tables. Check JVM tuning on Sun website. */ protected PdfPTable table; /** Stores vertical alignment value for PdfPCells, see: setAlignment(int vertical, int horizontal) */ protected int VALIGNMENT = Element.ALIGN_MIDDLE; /** Stores horizontal alignment value for PdfPCells, see: setAlignment(int vertical, int horizontal) */ protected int HALIGNMENT = Element.ALIGN_LEFT; protected boolean NO_CELL_WRAP = true; protected float CELL_LEFT_PADDING = 8.0f; }