Search code examples
phppdflib

Why PDFLib returns "[2100] fit_table: Function must not be called in 'template' scope"?


I'm trying to define a template to create a nested table using PDFLib. To get started I'm using the example code of the cookbook for nested tables (https://www.pdflib.com/pdflib-cookbook/table/nested_tables/) and just added some additional features to the table cells (loading custom font, adding form fields to the table cell). The example states that you have to use begin_template_ext() and end_template_ext(), and that you have to first add cells via add_table_cell(), then call the fit_table() method to get the boundaries of the table, finally passing width/height to the end_template_ext() call to finalize the template.

However as soon as I'm calling this code the libary throws an exception:

[2100] fit_table: Function must not be called in 'template' scope

I really don't understand why this is happening. The original cookbook code works fine, but as soon as I'm adding my own definition I get the exception. What I'm doing wrong here?

Here the's the code snippet from the nested_tables code slightly modified to match my modifications. For better readability I've striped the code to handle only the template definition.

<?php

$outfile = "";
$taboptlist1 = "stroke={{line=other linewidth=0.1 }} "
    . "fill={{area=table fillcolor={rgb 1 0.9 0.9}}} "
    . "position={left bottom}";

$searchpath = "./pdfdata";
$fontsize = 14.0;
$margin = 5.0;
$pagewidth = 595;
$pageheight = 500;

$title = "TEST";

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");

    $daxot_font = $p->load_font("DaxOT_Regular","unicode","embedding=true");
    $comment_font = $p->load_font("DaxOT_Regular","winansi","simplefont embedding nosubsetting");
    $textflow = "font=" . $daxot_font . " fontsize=10";

    if ($p->begin_document($outfile, "openmode=bookmarks optimize=true inmemory=true viewerpreferences={fitwindow=false displaydoctitle}") == 0)
        throw new Exception("Error: " . $p->get_errmsg());

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

      /**
       * This code part is not working, if I comment it out everything is fine
       */

      $trigdesc = "Some description";
      $tfdesc = $p->create_textflow($trigdesc,$textflow);
      $row = 1;
      $taboptlist1 = "stroke={{line=other linewidth=0.1 }} "."fill={{area=table fillcolor={rgb 1 0.9 0.9}}} position={left bottom}";
      $templ  = $p->begin_template_ext(0,0,"");

      $itbl   = 0;    // Start sub table, will be added to template and later template is assigned to colspan cell
      $itbl   = $p->add_table_cell($itbl,1,$row,"","margin=1 textflow=".$tfdesc." fittextflow={verticalalign=top}");
      $itbl   = $p->add_table_cell($itbl,2,$row,"","margintop=4 marginbottom=4 fieldtype=checkbox fieldname=check_ok$row fitfield={ fillcolor={#17a83f} backgroundcolor={#ffffff} strokecolor={#eeeeee} bordercolor={#eeeeee} }");
      $itbl   = $p->add_table_cell($itbl,3,$row,"","margintop=4 marginbottom=4 fieldtype=checkbox fieldname=check_nok$row fitfield={ buttonstyle=cross fillcolor={#c21a1a} backgroundcolor={#ffffff} strokecolor={#eeeeee} bordercolor={#eeeeee} }");
      $itbl   = $p->add_table_cell($itbl,4,$row,"","margintop=4 marginbottom=4 fieldtype=textfield fieldname=comment$row fitfield={font=".$comment_font."  fontsize=10 multiline=true}");
      $p->fit_table($itbl,0,0,1000,1000,$taboptlist1);
      $tabwidth1 = $p->info_table($itbl, "width");
      $tabheight1 = $p->info_table($itbl, "height");
      $p->end_template_ext($tabwidth1,$tabheight1);


    /**
     * Below is the striped down orginal code from cookbook, which works fine?
     */

    $templ = $p->begin_template_ext(0, 0, "");
    $addoptlist1 = "fittextline={fontname=Courier fontsize=". $fontsize . "} margin=" . $margin;

    $tbl = $p->add_table_cell(0, 1, 1, "tab 1, cell A", $addoptlist1);
    $tbl = $p->add_table_cell($tbl, 2, 1, "tab 1, cell B", $addoptlist1);
    $tbl = $p->add_table_cell($tbl, 1, 2, "tab 1, cell C", $addoptlist1);
    $tbl = $p->add_table_cell($tbl, 2, 2, "tab 1, cell D", $addoptlist1);
    $tbl = $p->add_table_cell($tbl, 1, 3, "tab 1, cell E", $addoptlist1);
    $tbl = $p->add_table_cell($tbl, 2, 3, "tab 1, cell F", $addoptlist1);
    $p->fit_table($tbl, 0, 0, 1000, 1000, $taboptlist1);

    /* Retrieve the width and height of the template sub-table */
    $tabwidth1 = $p->info_table($tbl, "width");
    $tabheight1 = $p->info_table($tbl, "height");

    /* Finish the template while specifying the size of it */
    $p->end_template_ext($tabwidth1, $tabheight1);



    /* Start page */
    $p->begin_page_ext($pagewidth, $pageheight, "");

    // HERE THE TABLE WOULD BE OUTPUT ...SHORTED FOR BETTER READABILITY

    $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=nested_tables.pdf");
    print $buf;

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

$p = 0;

The exception is always thrown when $p->fit_table() is called in my template definition.

What I'm doing wrong here?


Solution

  • This depends to the form fields in the table.

    From the PDFlib 10.0.2 API reference, chapter 5.3:

    Generally page, pattern, template, glyph; however, if the table contains form fields,annotations or tags only page scope is allowed

    Form Fields can only be placed directly, not via a template. That's the reason, why the scope for the create_field() function is also just page. (see PDFlib 10 API Reference, chapter 12.3 "Form fields"

    Scope page; if a rendition action is supplied which has been created with the target option this method can only be called on the page where the target annotation is located

    I hope this explain this exception message and you can work around.

    Solution: place the table directly to the page. (fit_table() between begin_page_ext() and end_page_ext() )

    HTH, Rainer