Donavon Lerman
Donavon Lerman

Reputation: 433

perl: Creating PDF Avery lables on linux?

Which would a the best and most flexible process for creating formatted PDF's of Avery labels on a linux machine with perl?

The labels need to include images and will have formatting similar to spanned rows and columns in an html table. And example would be several rows of text on the left hand side and an image on the right hand side that spans the text.

These are my thoughts but if you have additional ideas please let me know.

Has anybody done this and have any pointers, examples or links that may be of assistance?

Thank You, ~Donavon

Upvotes: 2

Views: 436

Answers (2)

boobie_goodness
boobie_goodness

Reputation: 104

Great you have found an answer you like.

Another option, which may or may not have suited you, would be to prepare the sheet that will be printed as labels as an open/libreoffice document, with pictures, layout, non-variant text ... (and can do all your testing runs through open/libreoffice).

Then:

use OpenOffice::OODoc;

then: read you data from a database

then:

my $document = odfDocument( file => "$outputFilename", 
                    create => "text",
                    template_path => $myTemplateDir );

then:

for (my $r = 0; $r < $NumOfTableRows; $r++ ) {
    for (my $c = 0; $c < $NumOfTableCols; $c++) {
          :
        $document->cellValue($theTableName, $r, $c, $someText);
        # test: was written properly ?
        my $writtenTest =  $document->cellValue($theTableName, $r, $c);
        chomp $writtenTest;
        if ($someText ne $writtenTest) {
             :
         }
     }
  }

then:

$document->save($outputFilename );

# save (convert to) a pdf
#   -f format; 
#   -n no start new listener; use existing
#   -T timeout to connect to its *OWN* listener (only); 
#   -e exportFilterOptions

`unoconv -f pdf -n  -T 60 -e PageRange=1-2  $outputFilename `;
# I remove the open/libreoffice doc, else clutter and confusion
`rm $outputFilename `;

As a quick overview of the practical issues:

  • name the layout tables
  • place your nice, correct open/libreoffice doc in "/usr/local/lib/site_perl/myNewTemplateDir/" say. You will need this (I think that this is the default, but I pass it anyway as $myTemplateDir
  • gotcha: the modules routines to wait for Open/Libreoffice to start (for the unoconv converter to start) do NOT work - unoconv will still not work after they say it will. I create dummy pdfs until one actually works - exists and has a non-zero size.

Upvotes: 0

harvey
harvey

Reputation: 2953

They are all viable options.

I found wkhtmltopdf to be too resource intensive and slow. If you do want to go down that route there are existing html templates already which can be found by a quick google search.

PDF::API2 performs very well, and I run it on a server system with no problems. Here's an example script I use for laying out elements in a grid format;

#!/usr/bin/env perl
use strict 'vars';

use FindBin;
use PDF::API2;

# Min usage, expects bank.pdf to exist in same location
render_grid_pdf(
  labels        => ['One', 'Two', 'Three', 'Four'],

  cell_width    => 200,
  cell_height   => 50,

  no_of_columns => 2,
  no_of_rows    => 2,
);

# Advanced usage
render_grid_pdf(
  labels        => ['One', 'Two', 'Three', 'Four'],

  cell_width    => 200,
  cell_height   => 50,

  no_of_columns => 2,
  no_of_rows    => 2,

  font_name     => "Helvetica-Bold",
  font_size     => 12,

  template      => "blank.pdf",
  save_as       => "my_labels.pdf",

  # Manually set coordinates to start prinding
  page_offset_x => 20, # Acts as a left margin
  page_offset_y => 600,
);


sub render_grid_pdf {
  my %args = @_;

  # Print data
  my $labels   = $args{labels} || die "Labels required";

  # Template, outfile and labels
  my $template = $args{template}  || "$FindBin::Bin/blank.pdf";
  my $save_as  = $args{save_as}   || "$FindBin::Bin/out.pdf";

  # Layout Properties
  my $no_of_columns = $args{no_of_columns} || die "Number of columns required";
  my $no_of_rows    = $args{no_of_rows}    || die "Number of rows required";

  my $cell_width    = $args{cell_width}    || die "Cell width required";
  my $cell_height   = $args{cell_height}   || die "Cell height required";

  my $font_name     = $args{font_name}     || "Helvetica-Bold";
  my $font_size     = $args{font_size}     || 12;

  # Note: PDF::API2 uses cartesion coordinates, 0,0 being
  # bottom. left. These offsets are used to set the print
  # reference to top-left to make things easier to manage
  my $page_offset_x = $args{page_offset_x} || 0;
  my $page_offset_y = $args{page_offset_y} || $no_of_rows * $cell_height;

  # Open an existing PDF file as a templata
  my $pdf = PDF::API2->open("$template");

  # Add a built-in font to the PDF
  my $font = $pdf->corefont($font_name);
  my $page = $pdf->openpage(1);

  # Add some text to the page
  my $text = $page->text();
  $text->font($font, $font_size);

  # Print out labels
  my $current_label = 0;
  OUTERLOOP: for (my $row = 0; $row < $no_of_columns; $row++) {
    for (my $column = 0; $column < $no_of_columns; $column++) {
      # Calculate label x, y positions
      my $label_y = $page_offset_y - $row     * $cell_height;
      my $label_x = $page_offset_x + $column  * $cell_width;

      # Print label
      $text->translate( $label_x, $label_y );
      $text->text( $labels->[$current_label]);


      # Increment labels index
      $current_label++;

      # Exit condition
      if ( $current_label > scalar @{$labels}) {
        last OUTERLOOP;
      }
    }
  }

  # Save the PDF
  $pdf->saveas($save_as);
}

Upvotes: 3

Related Questions