/*
* 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;
}