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?
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