Writing reports with PostScript::Report

Christopher J. Madsen

An example report

Available Components

Components:

  • Checkbox
  • Field
  • FieldTL
  • Image
  • LinkField
  • Spacer

Containers:

  • HBox
  • VBox

PostScript::Report is still young

But already useful

Report Sections: Report Header

Report Sections: Page Header

Report Sections: Detail

Report Sections: Page Footer

Report Sections: Report Footer

A simple report description

# Describe the report:
my $report_desc = {
  columns => {
    data => [
      [ 'Line' =>  25 ],
      [ 'Text' => 443 ], # 25 + 443 = 468pt = 6.5in
    ], # end data
  }, # end columns
}; # end $report_desc

A simple report description with data

# Describe the report:
my $report_desc = {
  columns => {
    data => [
      [ 'Line' =>  25 ],
      [ 'Text' => 443 ], # 25 + 443 = 468pt = 6.5in
    ], # end data
  }, # end columns
}; # end $report_desc

# Data for the report:
my @rows = (
  [ 1, 'Hello, world!' ],
  [ 2, 'This is a simple report.' ],
);

Running the report

# Build the report and run it:
my $rpt = PostScript::Report->build($report_desc);

$rpt->run(\@rows)->output("hello_world.ps");

And the result is:

Passing data to the report

run actually takes two parameters:

# Data global to the report:
my %data = (
  customer => 'John Doe',
  address  => '123 Main St.',
);

# Line-based data for the report:
my @rows = (
  [ 1, 'Hello, world!' ],
  [ 2, 'This is a simple report.' ],
);

$rpt->run(\%data, \@rows);

Both parameters are optional.

Component values

Most Components have a value attribute. This can be 1 of 3 things:

Component styles

Components have a number of attributes that control how they are displayed, for example:

   align        border   height
   background   font     width

These attributes can be inherited much like CSS styles are in HTML. (Thanks to Jesse Luehrs, who explained how I could write MooseX::AttributeTree to do that.)

Back to the simple report

# Describe the report:
my $report_desc = {
  columns => {
    data => [
      [ 'Line' =>  25 ],
      [ 'Text' => 443 ], # 25 + 443 = 468pt = 6.5in
    ], # end data
  }, # end columns
}; # end $report_desc

# Data for the report:
my @rows = (
  [ 1, 'Hello, world!' ],
  [ 2, 'This is a simple report.' ],
);

A simple report dump

$rpt->dump prints a description for debugging purposes:

align     : left    padding_bottom: 4
border    : 1       padding_side  : 3
line_width: 0.5     row_height    : 15


page_header:                      detail:
 PSR::HBox:                        PSR::HBox:
  children:                         children:
   PSR::Field:                       PSR::Field:
    value : PSR::Value::Constant      value     : 0
     value : Line
    width : 25                        width     : 25
   PSR::Field:                       PSR::Field:
    value : PSR::Value::Constant      value     : 1
     value : Text
    width : 443                       width     : 443

An example section description

  # The report_header is one line with text fields
  # All values are constant.
  report_header => [
    HBox => { border => 0,
              font => 'boldText',
              height => 12,
              padding_side   => 0,
              _default => 'Field',
            },
    { width  => 200,
      align  => 'left',
      value  => \'AIRPLANE COMPONENT FIXING INC.' },
    { width  => 351,
      value  => \'WORK ORDER' },
    { width  => 200,
      align  => 'right',
      value  => \'F.A.A REPAIR STATION NO. L3PF428Q' },
  ],

Font specifications

You must declare all fonts used at the report level:

  fonts => {
    label     => 'Helvetica-6',
    text      => 'Helvetica-9',
    boldText  => 'Helvetica-Bold-9',
    pageNum   => 'Helvetica-8',
    bottomRow => 'Helvetica-6',
    disclaimerText => 'Helvetica-Bold-8',
  },

Then refer to them by the names you picked:

  font       => 'text',
  label_font => 'label',

Colors

There are 3 ways to specify a color:

Zebra striping

For zebra striping, add stripe or stripe_page to your report description. This is an an arrayref of background colors for the detail section to cycle through.

If you use stripe_page, the pattern restarts on each page of the report.

For more complex striping, you can set the report’s detail_background attribute directly. This coderef is called each time the detail section is printed, and returns the background color to use.

Alternate output formats

You can use the PostScript::Convert module to process the report through Ghostscript to generate a PDF file or PNG images.

use PostScript::Convert;

psconvert($rpt->run(\@data), 'report.pdf');

I used that to make these slides:

psconvert($rpt, 'slides/pix/hello_world.png',
          gs_param => [qw(-r150)]);

system qw(mogrify -trim -bordercolor white -border 2x2
          slides/pix/hello_world.png);

Q & A

Questions?

Goodbye

Thanks for coming!

You can find these slides at:
    http://www.cjmweb.net/perl/yapc2010/

Or, if you want to see how I made these slides:
    http://github.com/madsen/yapc2010-postscript-report

I’d also like to thank Micro Technology Services, Inc. (www.mitsi.com), who sponsored development of PostScript::Report, and fREW Schmidt, who recommended me for the job. It wouldn’t have happened without them.