在Perl中制作PDF报告?

时间:2011-09-23 21:11:14

标签: perl pdf charts reporting

Perl的所有PDF库看起来都有些野蛮 - 卡在1980年代。您必须指定PostScript点才能进行布局。 Java有JasperReports,Ruby有Prawn,Python有ReportLab。是否有一个非灭绝的库/模块可以让我在不到一周的编码时制作漂亮的PDF? (我对PDF :: API2,PDF :: Table等有点沮丧)我不想生成HTML并将其转换。 Perl非常适合报告,但主报告文件格式无法以可用的方式提供。人们使用哪些图书馆?

我需要:

  • 表格
  • 图表(图片)
  • 颜色
  • 格式化(理想情况下是自动,不是逐个像素)
  • 页眉/页脚

如果绝对需要,我对包装外部(非Perl)开源工具略显开放。但对主要的Java服务器方法并不感兴趣。对于赏金,我想要一个纯粹的Perl方法,因为我想在一个我无法添加模块的服务器上运行它。如果你有一个运作良好的公开示例,请指出我。

3 个答案:

答案 0 :(得分:10)

使用Perl生成LaTeX,也许使用Template::Toolkit,然后调用编译器,TeXLive或MikTeX或您的操作系统所需的任何分发。有一个名为Template::LaTeX的扩展名,但您可能不需要它来管理构建过程。

LaTeX支持您需要的所有内容。表格有点有趣但是有一些现代的表格包可以简化事情(我认为它叫做ltxtable)。对于图表(你的意思是图表),有一种名为TikZ的子语言非常强大。

这确实是一个非常简单的工作流程,特别是如果您希望每次结果都相似(即可以使用模板)。事实上,它与从模板创建HTML并将其提供给浏览器的方式完全不同。

这样做的另一个好处是,如果您需要使用其他语言构建报告,模板(和准备好的源代码)将是可移植的。

答案 1 :(得分:5)

如果LaTeX太大,也许可以使用Inline::Python来包装ReportLab,每个人似乎都非常喜欢(我没有使用过它而且对Python不太熟练)。

编辑3: 这是编辑2,除了拆分为模块化风格,如果人们喜欢它(如果它是一种健壮的),也许我可以发布到CPAN。现在将.pm文件放在Inline/Python/ReportLab.pm中的@INC文件结构中(脚本自己的基本目录通常在@INC中)。

# Inline/Python/ReportLab.pm
package Inline::Python::ReportLab;

use strict;
use warnings;

use Carp;

use Inline::Python qw/py_eval/;
our @ISA = 'Inline::Python::Object';

sub import {
  py_eval('from reportlab.pdfgen.canvas import Canvas');
}

sub new {
  my $class = shift;
  my $filename = shift || croak "Must specify file name to contructor";
  return bless(Inline::Python::Object->new('__main__', 'Canvas', $filename), $class);
}

1;

然后脚本可能是这样的:

#!/usr/bin/env perl

use strict;
use warnings;

use Inline::Python::ReportLab;

my $c = Inline::Python::ReportLab->new('hello.pdf');
$c->drawString(100,100,"Hello World");
$c->showPage();
$c->save();

编辑2: 虽然编辑1仍然有用,但似乎(告诉我,如果我不正确!)我已经想出如何创建一个'Canvas'实例并直接公开它的方法:

#!/usr/bin/env perl

use strict;
use warnings;

use Inline::Python qw/py_eval/;

py_eval('from reportlab.pdfgen.canvas import Canvas');

my $c = Inline::Python::Object->new('__main__', 'Canvas', 'hello.pdf');
$c->drawString(100,100,"Hello World");
$c->showPage();
$c->save();

编辑2/3:此部分留作更多手动界面的示例。我认为编辑2/3提供了一个更好的界面,这使得原始的Python类没有(太多)包装的重任。

编辑1:我现在通过手动黑客攻击方法暴露了一些功能。这意味着对于每个想要使用的方法,必须添加包装器方法。虽然这已经是一个可行的解决方案,但我想知道是否有一些更简单的方法来公开整个python'canvas'类,但是现在我就是这样:

#!/usr/bin/env perl

use strict;
use warnings;

use Inline Python => <<END_PYTHON;
from reportlab.pdfgen import canvas

class Canvas:
  def __init__(self,filename):
    self.canvas = canvas.Canvas(filename)
  def drawString(self,x,y,text):
    self.canvas.drawString(x,y,text)
  def save(self):
    self.canvas.showPage()
    self.canvas.save()

END_PYTHON

my $c = Canvas->new('hello.pdf');
$c->drawString(100,100,"Hello World");
$c->save();

答案 2 :(得分:0)

经过深思熟虑和实验,我最终编写了大量代码来包装PDF :: API2。不幸的是,这是一个公司内部的项目,所以不会发布开源,但坦率地说,我建议使用不同的语言(Python / Ruby),也许通过JSON或其他东西传递数据。我的最终结果是有效的,但它需要大量的编码。在CPAN上正在进行PDF :: API2的重构,但它似乎停滞不前。