PDFlib Cookbook

cookbook

pdf_import/fill_imported_form_fields

Import all pages from a PDF document and fill form fields.

Download PHP Code  Switch to Java Code  Show Output 

<?php
/*
 * Fill form fields:
 * Import all pages from a PDF document and fill form fields.
 * Actions and JavaScript are also imported.
 * 
 * We apply the following simplified approach to filling the form fields:
 * - all fields are highlighted with a colorized border
 * - text fields are filled with their names
 * - checkboxes and radiobuttons are activated
 * - comboboxes and listboxes are populated with a few list items
 * - pushbuttons are supplied a new caption
 * - signature fields are highlighted, but could also get a new appearance
 *
 * Required software: PDFlib+PDI or PDFlib Personalization Server (PPS) 10
 * Required data: PDF input file, Noto fonts for field contents
 */

/* This is where the data files are. Adjust as necessary. */
$searchpath =  dirname(__FILE__,3)."/input";

/* By default annotations are also imported. In some cases this
 * requires the Noto fonts for creating annotation appearance streams.
 * We therefore set the searchpath to also point to the font directory.
 */
$fontpath = dirname(__FILE__,3)."/resource/font";
$outfile = "";
$title = "Fill imported form fields ";

$pdffile = "form_fields_pdfua1_input.pdf";
$exitcode = 0;

try {
    $p = new pdflib();

    $p->set_option("searchpath={" . $searchpath . "}");

    $p->set_option("searchpath={" . $fontpath . "}");

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

    if ($p->begin_document($outfile, "") == 0)
        throw new Exception("Error: " . $p->get_apiname() . ": "
                . $p->get_errmsg());

    $p->set_info("Creator", "PDFlib Cookbook");
    $p->set_info("Title", $title);

    $font = $p->load_font("NotoSerif-Regular", "", "");
    if ($font == 0){
        throw new Exception("Error: " . $p->get_apiname() . ": "
                . $p->get_errmsg());
    }

    /* Open the input PDF */
    $indoc = $p->open_pdi_document($pdffile, "usejavascript");
    if ($indoc == 0)
        throw new Exception("Error: " . $p->get_apiname() . ": "
                . $p->get_errmsg());

    $endpage = $p->pcos_get_number($indoc, "length:pages");

    /* Loop over all pages of the input document */
    for ($pageno = 1; $pageno <= $endpage; $pageno++) {

        $page = $p->open_pdi_page($indoc, $pageno, "");

        if ($page == 0)
        {
            print("Error: " . $p->get_errmsg());
            continue;
        }
        /* Dummy page size; will be adjusted by $p->fit_pdi_page() */
        $p->begin_page_ext(100, 100, "");

        /* Place the imported page on the output page and
        * adjust the page size. If the page contains form fields
        * these are also imported.
        */
        $p->fit_pdi_page($page, 0, 0, "adjustpage usefields=all useactions");

        /* Enumerate imported form fields */
        $fieldcount = (int) $p->pcos_get_number($indoc, "length:pages[" . ($pageno-1) . "]/fields");

        if ($fieldcount == 0){
            fwrite(STDERR, "no form fields found on page " . $pageno . "\n");
        }else{
            fwrite(STDERR, "processing page " . $pageno . "\n");
        }

        for ($f = 0; $f < $fieldcount; $f++) {

            $fieldname = $p->pcos_get_string($indoc, "pages[" . ($pageno-1) . "]/fields[" . $f . "]/fullname");
            $fieldtype = $p->pcos_get_string($indoc, "pages[" . ($pageno-1) . "]/fields[" . $f . "]/type");

            /* Process field depending on its type */
            switch ($fieldtype) {
                case "textfield":
                    $output = sprintf("filling %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                    fwrite(STDERR, $output);

                    // Fill the field with its own name
                    $optlist = "currentvalue={" . $fieldname . "} font=" . $font . " bordercolor=pink";
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    break;
                
                case "radiobutton":
                    // Highlight the field
                    $optlist = "bordercolor=pink";

                    if (strlen($fieldname) > 2 && substr($fieldname, -2) == "#0")
                    {
                        $output = sprintf("Activating %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                        fwrite(STDERR, $output);

                        // Activate the first button in the group
                        $optlist .= " currentvalue=On";
                    }
                    else
                    {
                        $output = sprintf("Highlighting %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                        fwrite(STDERR, $output);
                    }
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    break;
                    
                case "checkbox":
                    $output = sprintf("activating %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                    fwrite(STDERR, $output);

                    // Activate all boxes
                    $optlist = "currentvalue=On bordercolor=pink";
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    break;
                    
                case "combobox":
                    $output = sprintf("highlighting and popluating %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                    fwrite(STDERR, $output);
                    
                    // Highlight the field
                    $optlist = "itemtextlist={item1 item2 item3} currentvalue=item1 bordercolor=pink font=" . $font;
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    break;

                case "listbox":
                    $output = sprintf("highlighting and popluating %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                    fwrite(STDERR, $output);
                    
                    // Highlight the field
                    $optlist = "itemtextlist={item1 item2 item3} currentvalue={1} bordercolor=pink font=" . $font;
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    break;
                    
                case "pushbutton":
                    $output = sprintf("adding caption for %s field %d: '%s'\n", $fieldtype, $f, $fieldname);
                    fwrite(STDERR, $output);
                    
                    // Add caption (descriptive text) and highlight field border
                    $optlist = "caption={push me} bordercolor=pink font=" . $font;
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    break;
                    
                case "signature":
                    // Highlight field border
                    // Use "fieldcontents" to change the appearance
                    $optlist = "bordercolor=pink";
                    $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    /*
                     * Invisible signature fields are ignored upon import.
                     * In this case we risk an error message from PDF_create_field()
                     * since the selected field isn't available for filling.
                     * Therefore we must detect and skip empty signature fields here.
                     */
                    $llx = $p->pcos_get_number($indoc, "pages[" . ($pageno-1) . "]/fields[" . $f . "]/Rect[0]");
                    $lly = $p->pcos_get_number($indoc, "pages[" . ($pageno-1) . "]/fields[" . $f . "]/Rect[1]");
                    $urx = $p->pcos_get_number($indoc, "pages[" . ($pageno-1) . "]/fields[" . $f . "]/Rect[2]");
                    $ury = $p->pcos_get_number($indoc, "pages[" . ($pageno-1) . "]/fields[" . $f . "]/Rect[3]");
                    
                    if ($llx == $urx || $lly == $ury)
                    {
                        $output = sprintf("ignoring empty signature field %d: '%s'\n", $f, $fieldname);
                        fwrite(STDERR, $output);
                    }
                    else
                    {
                        // Highlight field border
                        // Use "fieldcontents" to change the appearance
                        $output = sprintf("hightlighting %s field %d: '%s'\n", $fieldtype, $f, $fieldname);
                        fwrite(STDERR, $output);
                        $optlist = "bordercolor=pink";
                        $p->create_field(0, 0, 0, 0, $fieldname, "", $optlist);
                    }
                    break;
                    
                // The remaining pCOS types don't designate usable fields; nothing to do
                case "container":		// node in the form tree which is not a form itself
                case "radiogroup":		// parent of a group of radio buttons
                default:
                    $output = sprintf("skipping %s %d: '%s'\n", $fieldtype, $f, $fieldname);
                    fwrite(STDERR, $output);
                    break;
            }
        }
        $p->close_pdi_page($page);
        $p->end_page_ext("");
    }


    $p->end_document("");
    $buf = $p->get_buffer();
    $len = strlen($buf);

    header("Content-type: application/pdf");
    header("Content-Length: $len");
    header("Content-Disposition: inline; filename=fill_imported_form_fields.pdf");
    print $buf;


}

catch (PDFlibException $e) {
    echo("PDFlib exception occurred in fill_imported_form_fields sample:\n" .
        "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
        $e->get_errmsg() . "\n");
    exit(1);
}
catch (Throwable $e) {
    echo($e);
    exit(1);
}

$p = 0;

?>