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, "") == 0) throw new Exception("Error: " . $p->get_errmsg()); $p->set_info("Creator", "PDFlib Cookbook"); $p->set_info("Title", $title); /* Load the bold and regular styles of a font */ $boldfont = $p->load_font("NotoSerif-Bold", "unicode", ""); if ($boldfont == 0) throw new Exception("Error: " . $p->get_errmsg()); $regularfont = $p->load_font("NotoSerif-Regular", "unicode", ""); if ($regularfont == 0) throw new Exception("Error: " . $p->get_errmsg()); /* Start the output page */ $p->begin_page_ext($pagewidth, $pageheight, ""); /* Output the heading */ $p->setfont($boldfont, $fontsize); $p->fit_textline("Time Sheet", $llx, $yheading, ""); /* ----------------------------------------------------------------- * In the first row, add the text line cells containing the headings * ----------------------------------------------------------------- */ $col = 1; $row = 1; /* Prepare the option list: * "colwidth" defines a fixed column width. * "rowheight" defines a fixed row height. * "margin" adds some empty space between the text and the cell borders. */ $tlcell_opts = "fittextline={font=" . $boldfont . " fontsize={capheight=" . $capheight . "} position={left top}} " . " colwidth=" . $cwfirst . " rowheight=" . $rwfirst . " margin=" . $margin; /* Add the "Day" heading */ $tbl = $p->add_table_cell($tbl, $col++, $row, "Day", $tlcell_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $cwsum += $cwfirst; /* Add the "hours" heading */ $tbl = $p->add_table_cell($tbl, $col++, $row, "Hours", $tlcell_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $cwsum += $cwfirst; /* Add the project headings. Those columns evenly share the remaining * width of the table's fitbox. */ for ($i = 0; $i < count($projects); $i++) { $tlcell_opts = "fittextline={font=" . $boldfont . " fontsize={capheight=" . $capheight . "} position={left top}}" . " rowheight=" . $rwfirst . " colwidth=" . (($tablewidth - $cwsum) / count($projects)) . " margin=" . $margin; $tbl = $p->add_table_cell($tbl, $col++, $row, $projects[$i], $tlcell_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); } /* -------------------------------------------------------------- * In the first column add the text line cells containing the day * -------------------------------------------------------------- */ $col = 1; $row = 2; /* Loop over all days */ for ($i = 1; $i <= $maxdays; $i++) { /* Prepare the option list for adding the text line cell */ $tlcell_opts = "fittextline={font=" . $boldfont . " fontsize={capheight=" . $capheight . "} position={left top}} " . " colwidth=" . $cwfirst . " rowheight=" . $rwother . " margin=" . $margin; /* We want to spread the table over two pages. The last row placed * on the first page should be the one representing a defined day, * e.g. the 15th. To accomplish this use the "return" * option of add_table_cell() when adding the respective cell. This * signals to fit_table() to return after having placed the * corresponding table row, and we can fit the following table rows * in a subsequent call on the second page. */ if ($i == $dbreak) $tlcell_opts .= " return break"; /* Add the text line cell */ $tbl = $p->add_table_cell($tbl, $col, $row++, $i . ".", $tlcell_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); } /* ------------------------------------------------------------------- * Add the Textflow cell containing the individual times spent for the * different projects * ------------------------------------------------------------------- */ $col = 3; $row = 2; /* Prepare the option list for adding a Textflow. * "leading" specifies the distance between to text lines. */ $tf_opts = "font=" . $regularfont . " fontsize={capheight=" . $capheight . "} leading=" . $leading; for ($i = 0; $i < count($times); $i++) { for ($j = 0; $j < count($times[$i]); $j++) { /* Add the Textflow */ $tf = $p->add_textflow(0, $times[$i][$j], $tf_opts); if ($tf == 0) throw new Exception("Error: " . $p->get_errmsg()); /* Prepare the option list for adding the Textflow cell * The first line of the Textflow should be aligned with the * baseline of the text lines. At the same time, the text lines * should have the same distance from the top cell border as the * Textflow. To avoid any space from the top add the Textflow * cell using "fittextflow={firstlinedist=capheight}". * "fitmethod=auto" scales the text until it entirely fits into * the cell. (You can use the "minfontsize" option to define a * lower limit when scaling the text, if required.) * Note that if "fitmethod=auto" is not used the row height will * be increased until the text fits completely into the cell. * "verticalalign=top" will place the text at the top of the * cell. * "rowheight" defines the row height. * "margin" adds some empty space between the text and the cell * borders. */ $tfcell_opts = "textflow=" . $tf . " fittextflow={firstlinedist=capheight verticalalign=top" . " fitmethod=auto}" . " rowheight=" . $rwother . " margin=" . $margin; /* Add the table cell */ $tbl = $p->add_table_cell($tbl, $col + $j, $row + $i, "", $tfcell_opts); if ($tbl == 0) throw new Exception("Error: " . $p->get_errmsg()); } } /* ------------------------------------ * Place the table on one or more pages * ------------------------------------ */ /* Prepare the option list for fitting the table. * "header=1" will repeat the first row at the beginning of each new * page. The "stroke" option will stroke lines with two different line * widths. The table frame as well as each vertical line to the right of * a day-of-the-week cell is stroked with a line width of 1, all other * lines are stroked with a line width of 0.3. */ $fittab_opts = "header=1 stroke={" . "{line=frame linewidth=1} {line=other linewidth=0.3} " . "{line=vert2 linewidth=1}}"; /* Loop until all of the table is placed; create new pages as long as * more table instances need to be placed */ do { /* Place the table instance */ $result = $p->fit_table($tbl, $llx, $lly, $urx, $ury, $fittab_opts); if ($result == "_error") throw new Exception ("Couldn't place table: " . $p->get_errmsg()); /* A return value of "break" has been explicitly specified in * add_table_cell() when adding the cell for a certain time interval * after which a new page shall be started. */ if ($result == "_boxfull" || $result == "break") { $p->setfont($regularfont, $fontsize); $p->fit_textline("-- Continued --", $urx, $ycontinued, "position {right top}"); $p->end_page_ext(""); $p->begin_page_ext($pagewidth, $pageheight, ""); } } while ($result == "_boxfull" || $result == "break"); $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=table_timesheet.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; ?>