自动生成 PDF

发布于 2024-12-19 11:41:49 字数 547 浏览 0 评论 0原文

用于生成 PDF 报告的可靠工具是什么?特别是,我们对创建包含视频的交互式 PDF 感兴趣,例如此处< /a>.

现在我们正在使用Python和reportlab来生成PDF,但还没有完全探索这个库(主要是因为许可证定价有点过高)

我们一直在研究 Adob​​e 的 SDKiText 库,但很难说它们的功能是什么。

能够从 PDF 模板生成文档将是一个优势。

任何指示或评论将不胜感激。

谢谢,

What would be a solid tool to use for generating PDF reports? Particularly, we are interested in creating interactive PDFs that have video, like the example found here.

Right now we are using Python and reportlab to generate PDFs, but have not explored the library completely (mostly because the license pricing is a little prohibitive)

We have been looking at the Adobe's SDK and iText libraries but it's hard to say what the capabilities of either are.

The ability to generate a document from a template PDF would be a plus.

Any pointers or comments will be appreciated.

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨后彩虹 2024-12-26 11:41:49

最近,我需要为 Django 应用程序创建 PDF 报告;可以使用 ReportLab 许可证,但我最终选择了 LaTeX。这种方法的好处是我们可以使用 Django 模板 来生成 LaTeX源,而不必为我们需要创建的许多报告编写大量代码。另外,我们可以利用相对更简洁的 LaTeX 语法(它确实有很多怪癖,并且并不适合所有用途)。

此代码段提供了该方法的总体概述。我发现有必要进行一些更改,我已在本问题末尾提供了这些更改。主要添加的是对 Rerun LaTeX 消息的检测,这表明需要额外的传递。用法很简单:

def my_view(request):
    pdf_stream = process_latex(
        'latex_template.tex',
        context=RequestContext(request, {'context_obj': context_obj})
    )
    return HttpResponse(pdf_stream, content_type='application/pdf')

可以将视频嵌入 LaTeX 生成的 PDF 中,但我没有任何经验。 此处是顶部Google 结果

该解决方案确实需要生成一个新进程 (pdflatex),因此如果您想要纯 Python 解决方案,请继续寻找。

import os
from subprocess import Popen, PIPE
from tempfile import NamedTemporaryFile

from django.template import loader, Context


class LaTeXException(Exception):
    pass


def process_latex(template, context={}, type='pdf', outfile=None):
    """
    Processes a template as a LaTeX source file.
    Output is either being returned or stored in outfile.
    At the moment only pdf output is supported.
    """
    t = loader.get_template(template)
    c = Context(context)
    r = t.render(c)

    tex = NamedTemporaryFile()
    tex.write(r)
    tex.flush()
    base = tex.name
    names = dict((x, '%s.%s' % (base, x)) for x in (
        'log', 'aux', 'pdf', 'dvi', 'png'))
    output = names[type]

    stdout = None
    if type == 'pdf' or type == 'dvi':
        stdout = pdflatex(base, type)
    elif type == 'png':
        stdout = pdflatex(base, 'dvi')
        out, err = Popen(
            ['dvipng', '-bg', '-transparent', names['dvi'], '-o', names['png']],
            cwd=os.path.dirname(base), stdout=PIPE, stderr=PIPE
        ).communicate()

    os.remove(names['log'])
    os.remove(names['aux'])

    # pdflatex appears to ALWAYS return 1, never returning 0 on success, at
    # least on the version installed from the Ubuntu apt repository.
    # so instead of relying on the return code to determine if it failed,
    # check if it successfully created the pdf on disk.
    if not os.path.exists(output):
        details = '*** pdflatex output: ***\n%s\n*** LaTeX source: ***\n%s' % (
            stdout, r)
        raise LaTeXException(details)

    if not outfile:
        o = file(output).read()
        os.remove(output)
        return o
    else:
        os.rename(output, outfile)


def pdflatex(file, type='pdf'):
    out, err = Popen(
        ['pdflatex', '-interaction=nonstopmode', '-output-format', type, file],
        cwd=os.path.dirname(file), stdout=PIPE, stderr=PIPE
    ).communicate()

    # If the output tells us to rerun, do it by recursing over ourself.
    if 'Rerun LaTeX.' in out:
        return pdflatex(file, type)
    else:
        return out

Recently, I needed to create PDF reports for a Django application; a ReportLab license was available, but I ended up choosing LaTeX. The benefit of this approach is that we could use Django templates to generate the LaTeX source, and not get over encumbered writing lots of code for the many reports we needed to create. Plus, we could take advantage of the relatively much more concise LaTeX syntax (which does have it's many quirks and is not suitable for every purpose).

This snippet provides a general overview of the approach. I found it necessary to make some changes, which I have provided at the end of this question. The main addition is detection for Rerun LaTeX messages, which indicates an additional pass is required. Usage is as simple as:

def my_view(request):
    pdf_stream = process_latex(
        'latex_template.tex',
        context=RequestContext(request, {'context_obj': context_obj})
    )
    return HttpResponse(pdf_stream, content_type='application/pdf')

It is possible to embed videos in LaTeX generated PDFs, however I do not have any experience with it. Here is a top Google result.

This solution does require spawning a new process (pdflatex), so if you want a pure Python solution keep looking.

import os
from subprocess import Popen, PIPE
from tempfile import NamedTemporaryFile

from django.template import loader, Context


class LaTeXException(Exception):
    pass


def process_latex(template, context={}, type='pdf', outfile=None):
    """
    Processes a template as a LaTeX source file.
    Output is either being returned or stored in outfile.
    At the moment only pdf output is supported.
    """
    t = loader.get_template(template)
    c = Context(context)
    r = t.render(c)

    tex = NamedTemporaryFile()
    tex.write(r)
    tex.flush()
    base = tex.name
    names = dict((x, '%s.%s' % (base, x)) for x in (
        'log', 'aux', 'pdf', 'dvi', 'png'))
    output = names[type]

    stdout = None
    if type == 'pdf' or type == 'dvi':
        stdout = pdflatex(base, type)
    elif type == 'png':
        stdout = pdflatex(base, 'dvi')
        out, err = Popen(
            ['dvipng', '-bg', '-transparent', names['dvi'], '-o', names['png']],
            cwd=os.path.dirname(base), stdout=PIPE, stderr=PIPE
        ).communicate()

    os.remove(names['log'])
    os.remove(names['aux'])

    # pdflatex appears to ALWAYS return 1, never returning 0 on success, at
    # least on the version installed from the Ubuntu apt repository.
    # so instead of relying on the return code to determine if it failed,
    # check if it successfully created the pdf on disk.
    if not os.path.exists(output):
        details = '*** pdflatex output: ***\n%s\n*** LaTeX source: ***\n%s' % (
            stdout, r)
        raise LaTeXException(details)

    if not outfile:
        o = file(output).read()
        os.remove(output)
        return o
    else:
        os.rename(output, outfile)


def pdflatex(file, type='pdf'):
    out, err = Popen(
        ['pdflatex', '-interaction=nonstopmode', '-output-format', type, file],
        cwd=os.path.dirname(file), stdout=PIPE, stderr=PIPE
    ).communicate()

    # If the output tells us to rerun, do it by recursing over ourself.
    if 'Rerun LaTeX.' in out:
        return pdflatex(file, type)
    else:
        return out
奈何桥上唱咆哮 2024-12-26 11:41:49

我建议使用 https://github.com/mreiferson/py-wkhtmltox 将 HTML 渲染为PDF。

并使用您选择的任何工具将报告呈现为 HTML。我喜欢 http://www.makotemplates.org/

I suggest to use https://github.com/mreiferson/py-wkhtmltox to render HTML to PDF.

And use any tool you choose to render reports as HTML. I like http://www.makotemplates.org/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文