PDFlib Cookbook

cookbook

table/align_decimals

Align decimal numbers in a table.

Download Java Code  Switch to PHP Code  Show Output 

/**
 * Align decimals:
 * 
 * Create a table with Textlines and Textflows containing decimal numbers,
 * which are be aligned at the decimal point/comma.
 * 
 * Required software: PDFlib/PDFlib+PDI/PPS 10
 * Required data: none
 */
package com.pdflib.cookbook.pdflib.table;

import com.pdflib.pdflib;

import java.text.NumberFormat;
import java.util.Locale;

import com.pdflib.PDFlibException;
public class align_decimals {
    public static void main(String argv[]) {
        /* This is where the data files are. Adjust as necessary. */
        String searchpath = "../input";
        
        String outfile = "align_decimals.pdf";
        String title = "Align decimals";

        pdflib p = null;
        int row, tbl = -1;
        String optlist, result;

        int margin = 3;
        int fontsize = 12;
        int exitcode = 0;

        double pagewidth = 500, pageheight = 500;
        
        /*
         * Height of a table row which is the sum of a font size of 12 and the
         * upper and lower cell margin of 3 each
         */
        double rowheight = fontsize + 2 * margin;

        double tablewidth = 240;
        
        /* Width of the first and second column of the table */
        double c1 = tablewidth / 2, c2 = tablewidth / 2;
        
        /* How many rows to put in the table */
        int textline_rowcount = 7, textflow_rowcount = 7;

        try {
            p = new pdflib();

            p.set_option("searchpath={" + searchpath + "}");

            /* This means we must check return values of load_font() etc. */
            p.set_option("errorpolicy=return");

            if (p.begin_document(outfile, "") == -1)
                throw new Exception("Error: " + p.get_errmsg());

            p.set_info("Creator", "PDFlib Cookbook");
            p.set_info("Title", title);

            p.begin_page_ext(0, 0,
                "width=" + pagewidth + " height=" + pageheight);


            /* Set the current row */
            row = 1;

            String header_optlist =
                "fittextline={fontname=NotoSerif-Regular "
                + "fontsize=" + fontsize + " position=center} rowheight=" 
                + rowheight + " margin=" + margin + " colspan=2 colwidth=" 
                + tablewidth;

            /* Add a heading line spanning two columns. */
            tbl = p.add_table_cell(tbl, 1, row,
                "Decimal alignment with Textlines in table cells",
                header_optlist);
            if (tbl == -1)
                throw new Exception("Error: " + p.get_errmsg());

            row += 1;
            
            /* Format the numbers according to the US locale. */
            NumberFormat decimalFormat = NumberFormat.getInstance(Locale.US);
            decimalFormat.setMaximumFractionDigits(2);
            decimalFormat.setMinimumFractionDigits(2);

            /*
             * Add two cells per row for subsequent rows. The first column
             * contains a consecutive number, the second column an
             * arbitrary floating point number formatted with two digits
             * after the decimal point.
             */
            int factor;
            int i;
            for (i = 0, factor = 1; i < textline_rowcount;
                row += 1, i += 1, factor *= 10) {
                
                /* Add a cell in the first column of the current row. */
                optlist = 
                    "fittextline={fontname=NotoSerif-Regular " 
                    + " fontsize=" + fontsize + " position={center center}} " 
                    + "rowheight=" + rowheight + " margin=" + margin 
                    + " colwidth=" + c1;

                tbl = p.add_table_cell(tbl, 1, row, "" + (i + 1), optlist);
                if (tbl == -1)
                    throw new Exception("Error: " + p.get_errmsg());

                /*
                 * Add a cell where the decimal numbers are aligned at the
                 * decimal point. The decimal point is placed at 80% of the cell
                 * width.
                 */
                optlist = 
                    "fittextline={fontname=NotoSerif-Regular "
                    + "fontsize=" + fontsize
                    + " position={80 center} alignchar={.}} colwidth=" + c2
                    + " margin=" + margin;

                /* Generate a decimal number and put into a table cell */
                String number = decimalFormat
                    .format(1.33 * (i + 1) * factor + 1.71 * (i + 1));
                tbl = p.add_table_cell(tbl, 2, row, number, optlist);
                if (tbl == -1)
                    throw new Exception("Error: " + p.get_errmsg());
            }

            tbl = p.add_table_cell(tbl, 1, row,
                "Decimal alignment with Textflows in table cells",
                header_optlist);
            if (tbl == -1)
                throw new Exception("Error: " + p.get_errmsg());
            
            row += 1;
            
            for (i = 0, factor = 1; i < textflow_rowcount;
                row += 1, i += 1, factor *= 10) {
                
                /* Add a cell in the first column of the current row. */
                optlist = 
                    "fittextline={fontname=NotoSerif-Regular " 
                    + " fontsize=" + fontsize
                    + " position={center center}} rowheight=" + rowheight
                    + " margin=" + margin + " colwidth=" + c1;

                tbl = p.add_table_cell(tbl, 1, row, "" + (i + 1), optlist);
                if (tbl == -1)
                    throw new Exception("Error: " + p.get_errmsg());

                /* Generate two decimal numbers and per table cell */
                String number1 = decimalFormat
                    .format(1.13 * (i + 1) * factor + 1.21 * (i + 1));
                String number2 = decimalFormat
                    .format(1.52 * (i + 1) * factor + 1.17 * (i + 1));

                /*
                 * Create the text content from the two numbers, separated
                 * by a newline, and aligned with the TAB character.
                 */
                String tftext = "\t" + number1 + "\n" + "\t" + number2;

                /*
                 * Prepare the option list for adding the Textflow.
                 * 
                 * Set the tab alignment character and set the tab position at
                 * 80% of the formatted Textflow width. We explicitly set the
                 * "tabalignchar" to the default ".", because it potentially
                 * would have to be changed for other locales.
                 */
                optlist = "fontname=NotoSerif-Regular " + 
                    " fontsize=" + fontsize + " hortabmethod=ruler "
                    + "ruler={80%} tabalignment={decimal} tabalignchar={.}";

                /* Add the Textflow to be placed in a table cell. */
                int tf = p.add_textflow(-1, tftext, optlist);
                if (tf == -1)
                    throw new Exception("Error: " + p.get_errmsg());

                /* Prepare the option list for adding the Textflow table cell.*/
                optlist = "textflow=" + tf + " colwidth=" + c2
                    + " margin=" + margin;

                tbl = p.add_table_cell(tbl, 2, row, "", optlist);
                if (tbl == -1)
                    throw new Exception("Error: " + p.get_errmsg());
            }
            
            /* Fit the table centered on the page. */
            optlist = "header=1 stroke={{line=other linewidth=0.3}}";

            double llx = (pagewidth - tablewidth) / 2;
            double tableheight =
                (2 + textline_rowcount + 2 * textflow_rowcount) * rowheight;
            double lly = (pageheight - tableheight) / 2;
            
            result = p.fit_table(tbl, llx, lly, llx + tablewidth,
                lly + tableheight, optlist);

            /* Check the result; "_stop" means all is ok */
            if (!result.equals("_stop")) {
                if (result.equals("_error"))
                    throw new Exception("Error: " + p.get_errmsg());
                else {
                    /*
                     * Other return values require dedicated code to deal with
                     */
                }
            }
            
            p.delete_table(tbl, "");
            
            p.end_page_ext("");

            p.end_document("");
        }
        catch (PDFlibException e) {
            System.err.println("PDFlib exception occurred:");
            System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
                ": " + e.get_errmsg());
            exitcode = 1;
        }
        catch (Exception e) {
            System.err.println(e);
            exitcode = 1;
        }
        finally {
            if (p != null) {
                p.delete();
            }
            System.exit(exitcode);
        }
    }
}