Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
This code works fine but I am having a nightmare here trying to first; align the text inside the $head_data to the center of the page and also make this header text to show on every pdf page it generates. Also my $footer_data, which displays a date, I can't figure it out how to add this to all the pages. And also I am trying to find how I could add page numbers to the pdf pages generated.
If anyone worked on this type of stuff before it would be great to show me how I can get this done.
Thank you very much, and here is the code:

use strict; use PDF::API2; use PDF::API2::Annotation; use PDF::Table; my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); $mon++; $year += 1900; my $s_date = sprintf '%02d-%02d-%04d', $mon, $mday, $year; my $page_num = 1; my $pdftable = new PDF::Table; my $pdf = new PDF::API2(-file => "pdf_test.pdf"); $pdf->preferences( -thumbs => 1, ); #$pdf->page($page_num); sub newpage { my $page = $pdf->page; $page->mediabox(792,612); my $txt = $page->text; #$page = $pdf->page(1); #my $pagenumber = $pdf->pages #$page->text; #$page = $pdf->pages; #$page->text( 'Page '.$page_num++, align =>'right' ); return $page; } my $page = newpage(); # some data to layout my $some_data =[ # same data as in your code... (not duplicated for brevity) ["Header 1", "Header 2", "Header 3", "Header 4", "Header 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ["Content 1", "Content 2", "Content 3", "Content 4", "Content 5" ], ]; ### Header Starts my $head_data =[ ["My Company Name",], ["List of Users",], ["Welcome User 1",] ]; $pdftable->table( # required params $pdf, $page, $head_data, x => 20, w => 750, start_y => 594, # top od doc on page - 594 next_y => 594, start_h => 100, next_h => 100, #OPTIONAL PARAMS BELOW #justify => 'right', # One of left|right , #max_word_length=> 20, # add a space after every 20th symbol in + long words like serial numbers padding => 2, # cell padding #padding_top => 1, # top cell padding, overides padding padding_right => 10, # right cell padding, overides padding #padding_left => 5, # left cell padding, overides padding #padding_bottom => 5, # bottom padding, overides -padding border => 0, # border width, default 1, use 0 for no +border border_color => 'navy', # default black align => "center", #|right|center|justify|fulljustify", #font => $pdf->corefont("Helvetica", -encoding => "utf8 +"), # default font #font_size => 10, #font_color_odd => 'black', #font_color_even=> 'black', #background_color_odd => "#ffffff", #background_color_even => "#ffffff", #cell background color for e +ven rows #header_props => $hdr_props, #column_props => $col_props, ); ### End Header # build the table layout $pdftable->table( # required params $pdf, $page, $some_data, x => 70, w => 650, start_y => 527, # 550 next_y => 550, start_h => 500, next_h => 500, # some optional params padding => 5, padding_right => 10, background_color_odd => "gray", background_color_even => "lightblue", #cell background color for e +ven rows new_page_func => \&newpage, # as defined above cell_render_hook => sub { # this is our newly introduced callba +ck function my ($page, $row, $col, $x, $y, $w, $h) = @_; if ($col == 0) { # do nothing except for first column my $url = "http://www.anywhere.com?row=$row"; my $annot = $page->annotation(); $annot->url( $url, -rect => [$x, $y, $x+$w, $y+$h], -border => [1,1,1] ); } }, ), ##start footer #=code my $footer_data =[ [ " + + $s_date",] ]; $pdftable->table( # required params $pdf, $page, $footer_data, x => 20, w => 750, start_y => 30, # top od doc on page next_y => 30, start_h => 30, next_h => 30, #OPTIONAL PARAMS BELOW justify => 'right', # One of left|right , #max_word_length=> 20, # add a space after every 20th symbol in + long words like serial numbers padding => 5, # cell padding border => 0, # border width, default 1, use 0 for no +border border_color => 'red', # default black font => $pdf->corefont("Helvetica", -encoding => "utf8" +), # default font font_size => 9, #header_props => $hdr_props, #column_props => $col_props, ); #=cut ## end footer # do other stuff with $pdf $pdf->saveas(); =code #patch PDF/Table.pm like this } # line 615 ### insert this if (ref $arg{cell_render_hook} eq 'CODE') { $arg{cell_render_hook}->( $page, $rows_counter, $j, $cur_x, $cur_y-$row_h, $calc_column_widths->[$j], $row_h ); } ### $cur_x += $calc_column_widths->[$j]; # orig. line 616 }#End of for(my $j.... # orig. line 617 =cut

Replies are listed 'Best First'.
Re: Perl PDF format issue.
by almut (Canon) on Apr 07, 2009 at 20:15 UTC
    align the text inside the $head_data to the center of the page

    The idea would be to use the table option column_props (see "COLUMN PROPERTIES" in the docs, for details):

    column_props => [ { justify => 'center' } ],

    (one hash per column as an array — you only need one entry, though, as your headers/footers don't have more than one column)

    Unfortunately, PDF::Table does currently not allow centering of cell content.  If you look in the source you'll see "#TODO: Implement Center text align"...  Time for another patch.  Locate this piece of code (PDF/Table.pm, line 556)

    if($col_props->[$j]->{justify} eq 'right') { $space = $calc_column_widths->[$j] -($txt->advancewidth($r +ecord->[$j]) + $pad_right); }

    and extend it to read

    if($col_props->[$j]->{justify} eq 'right') { $space = $calc_column_widths->[$j] -($txt->advancewidth($r +ecord->[$j]) + $pad_right); } elsif ($col_props->[$j]->{justify} eq 'center') { $space = ($calc_column_widths->[$j] -$txt->advancewidth($r +ecord->[$j])) / 2; }

    This will make the column_props definition work with "center", too.


    make this header text to show on every pdf page

    That's an easier one.  Just wrap your header and footer code into subroutines, and call them from within your newpage() function (which is being called for every page initialisation)

    sub newpage { my $page = $pdf->page; $page->mediabox(792,612); header($page); footer($page); page_nr($page, $page_num++); return $page; }

    In case you also want to show the table column headers on every page, just specify, for the main table  (see "HEADER ROW PROPERTIES" in the docs):

    header_props => { repeat => 1 },

    add page numbers

    As hinted at above, a page number routine would also be called from within newpage(). Its implementation could look like this (using PDF::API2's textlabel() method — but you could also use PDF::Table's text_block() method)

    $page->gfx->textlabel( # PDF::API2 method 760, 15, # x, y $pdf->corefont("Helvetica"), 11, # font, size "Page $num", # text -color => '#808080', -align => 'right', );

    The entire code would then look as shown below, which produces this PDF.

    (BTW, just in case you came here via Google, you might also want to read Part One).

      That's a big improvement, but any idea why when I am opening the PDF file it is giving me an error saying
      "Illegal Operation inside a path". Did you try it, did you get the same error?

        I can view it fine with several versions of acroread, xpdf, kpdf and evince (all on Linux).  But you don't seem to be the first one to have encountered that error...  In theory, the problem could be either with the PDF format (as generated by PDF::API2), or with the the viewer software, which might well have some subtle bug.  I'm afraid I can't help more.  Maybe try a different viewer?