2
votes

I have been using PDF::API2 module to program a PDF. I work at a warehousing company and we are trying switch from text packing slips to PDF packing slips. Packing Slips have a list of items needed on a single order. It works great but I have run into a problem. Currently my program generates a single page PDF and it was all working fine. But now I realize that the PDF will need to be multiple pages if there are more than 30 items in an order. I was trying to think of an easy(ish) way to do that, but couldn’t come up with one. The only thing I could think of involves creating another page and having logic that redefines the coordinates of the line items if there are multiple pages. So I was trying to see if there was a different method or something I was missing that could help but I wasn’t really finding anything on CPAN.

Basically, i need to create a single page PDF unless there are > 30 items. Then it will need to be multiple.

I hope that made sense and any help at all would be greatly appreciated as I am relatively new to programming.

4

4 Answers

3
votes

Since you already have the code working for one-page PDFs, changing it to work for multi-page PDFs shouldn't be too hard.

Try something like this:

use PDF::API2;

sub create_packing_list_pdf {
    my @items = @_;
    my $pdf = PDF::API2->new();
    my $page = _add_pdf_page($pdf);

    my $max_items_per_page = 30;
    my $item_pos = 0;
    while (my $item = shift(@items)) {
        $item_pos++;

        # Create a new page, if needed
        if ($item_pos > $max_items_per_page) {
            $page = _add_pdf_page($pdf);
            $item_pos = 1;
        }

        # Add the item at the appropriate height for that position
        # (you'll need to declare $base_height and $line_height)
        my $y = $base_height - ($item_pos - 1) * $line_height;

        # Your code to display the line here, using $y as needed
        # to get the right coordinates
    }

    return $pdf;
}

sub _add_pdf_page {
    my $pdf = shift();

    my $page = $pdf->page();

    # Your code to display the page template here.
    #
    # Note: You can use a different template for additional pages by
    # looking at e.g. $pdf->pages(), which returns the page count.
    #
    # If you need to include a "Page 1 of 2", you can pass the total
    # number of pages in as an argument:
    # int(scalar @items / $max_items_per_page) + 1

    return $page;
}

The main thing is to split up the page template from the line items so you can easily start a new page without having to duplicate code.

2
votes

PDF::API2 is low-level. It doesn't have most of what you would consider necessary for a document, things like margins, blocks, and paragraphs. Because of this, I afraid you're going to have to do things the hard way. You may want to look at PDF::API2::Simple. It might meet your criteria and it's simple to use.

1
votes

I use PDF::FromHTML for some similar work. Seems to be a reasonable choice, I guess I am not too big on positioning by hand.

1
votes

The simplest method is to use PDF-API2-Simple

my @content;
my $pdf = PDF::API2::Simple->new(file => "$name");
$pdf->add_font('Courier');
$pdf->add_page();
foreach $line (@content)
{
    $pdf->text($line, autoflow => 'on');
}
$pdf->save();