I had to write a custom PDF to do such a thing for work and people are
always asking how to do it. Here is my solution.


//This is free for anyone's use/modification. I'd like to receive credit
if it gets incorporated into the official itext though.
//Copyright 2005. Michael McCaskill ([EMAIL PROTECTED])
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

/**
 * Class that writes a <code>PdfPTable</code>, and spans it across
multiple pages if the columns won't fit on one page
 */
public class PdfPTableWriter {  
        
        //Instance variables
        private PdfPTable table;
        private PdfWriter writer;
        private Document document;

        //List of how many columns per horizontal page  
        private List numberOfColumnsPerPage;

        //List of how many rows per vertical page
        private List numberOfRowsPerPage;

        //Offsets if given
        private float widthOffset = 0;
        private float heightOffset = 0;

        /**
          * Class Constructor
          */    
        public PdfPTableWriter(Document document, PdfWriter writer, PdfPTable
table) {
                this.document = document;
                this.writer = writer;
                this.table = table;
                calculateColumns();
                calculateRows();
        }
        
        /**
          * Writes the table to the document
          */
        public void writeTable() throws DocumentException {
                //Begin at row 1 (row after the header)
                int rowBegin = 1;
                int rowEnd = 0;
                //Note the size of numberOfRowsPerPage is how many vertical
                //pages there are.
                Iterator rowsIter = numberOfRowsPerPage.iterator();
                while (rowsIter.hasNext()) {
                        rowEnd = ((Integer)rowsIter.next()).intValue();
                        writeSelectedRows(rowBegin, rowEnd);
                        rowBegin = rowEnd;
                }
        }
        
        /**
         * Prints the Report's columns (splitting horizontally if necessary)
and subsequent rows  
         * @param rowBegin
         * @param rowEnd
         * @throws DocumentException
         */
        private void writeSelectedRows(int rowBegin, int rowEnd) throws
DocumentException {
                int colBegin = 0;
                int colEnd = 0;
                float pageHeight = document.getPageSize().height() - 
heightOffset;
                PdfContentByte contentByte = writer.getDirectContent();
                Iterator columnsIter = numberOfColumnsPerPage.iterator();       
        
                while (columnsIter.hasNext()) {
                        colEnd = colBegin + 
((Integer)columnsIter.next()).intValue();
                        //Writer table header
                        writeSelectedRows(colBegin, colEnd, 0, 1, widthOffset, 
pageHeight);
                        //Writes selected rows to the document
                        writeSelectedRows(colBegin, colEnd, rowBegin, rowEnd, 
widthOffset,
pageHeight - table.getHeaderHeight());
                        //Add a new page
                        document.newPage();
                        colBegin = colEnd;
                }
        }
        
        public int getTotalPages() {
                return numberOfColumnsPerPage.size() * 
numberOfRowsPerPage.size();
        }
        
        public void setHeightOffset(float heightOffset) {
                this.heightOffset = heightOffset;
        }
        
        public void setWidthOffset(float widthOffset) {
                this.widthOffset = widthOffset;
        }
        
        private void writeSelectedRows(int colBegin, int colEnd, int rowBegin,
int rowEnd, float x, float y) {
                PdfContentByte cb = writer.getDirectContent();
                table.writeSelectedRows(colBegin, colEnd, rowBegin, rowEnd, x, 
y, cb);
        }
        
        private void calculateColumns() {
                numberOfColumnsPerPage = new ArrayList();
                float pageWidth = document.getPageSize().width() - widthOffset;
                float[] widths = table.getAbsoluteWidths();
                if (table.getTotalWidth() > pageWidth) {
                        //tmp variable for amount of total width thus far
                        float tmp = 0f;
                        //How many columns for this page
                        int columnCount = 0;
                        //Current page we're on
                        int currentPage = 0;
                        //Iterate through the column widths
                        for (int i = 0; i < widths.length; i++) {
                                //Add to the temporary total
                                tmp += widths[i];
                                //If this column will not fit on the page
                                if (tmp > pageWidth) {                          
                                        //Add the current column count to this 
page
                                        numberOfColumnsPerPage.add(new 
Integer(columnCount));
                                        //Since this column won't fit, the tmp 
variable should start
off the next iteration
                                        //as this column's width
                                        tmp = widths[i];
                                        //Set column count to 1, since we have 
moved this column to the
next page
                                        columnCount = 1;
                                }
                                //If this is will fit on the page
                                else {    
                                        //Increase the column count
                                        columnCount++;
                                }
                        }               
                        //Save the remaining columns
                        numberOfColumnsPerPage.add(new Integer(columnCount));
                }
                    
                //All the columns will fit on one horizontal page
                //Note: -1 means all the columns
                else {
                        numberOfColumnsPerPage.add(new Integer(-1));
                }
        }
        
        private void calculateRows() {
                numberOfRowsPerPage = new ArrayList();
                float pageHeight = document.getPageSize().height() - 
heightOffset -
table.getHeaderHeight();
                //If the table won't fit on the first page
                if (table.getTotalHeight() > pageHeight -
table.getHeaderHeight()) {
                        //Temp variables
                        float tmp = 0f;
                        //Determine the start and end rows for each page
                        for (int i = 1; i < table.size(); i++) {
                                //Add this row's height to the tmp total        
                        
                                tmp += table.getRowHeight(i);                   
        
                                if (tmp > pageHeight) {
                                        //This row won't fit so end at previous 
row
                                        numberOfRowsPerPage.add(new 
Integer(i-1));
                                        //Since this row won't fit, the tmp 
variable should start off
the next iteration
                                        //as this row's height
                                        tmp = table.getRowHeight(i);
                                }
                        }
                        //Last page always ends on totalRows
                        numberOfRowsPerPage.add(new Integer(table.size()));
                }
        
                //All the rows will fit on one vertical page
                //Note: -1 means all the rows
                else {
                        numberOfRowsPerPage.add(new Integer(-1));
                }
        }
}



-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
iText-questions mailing list
iText-questions@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions

Reply via email to