如何在 PDF 上进行邮件合并?

发布于 2024-07-09 21:57:35 字数 404 浏览 10 评论 0原文

我经常从我们的设计师(在 Adob​​e InDesign 中构建)那里收到 PDF,该 PDF 应该发送给数千人。

我已经得到了所有人员的名单,并且在 OpenOffice.org 中进行邮件合并很容易。 但是,OpenOffice.org 不支持高级 PDF。 我只想在每一页上输出一些文本并将其打印出来。

我现在是这样做的:打印出 6000 份 PDF,然后再次将它们全部放入打印机,然后在上面打印出姓名、地址和其他信息。 但那很贵。

遗憾的是,我无法将 PDF 转换为图像并在 OpenOffice.org 中使用它,因为它会使计算机停止运行。 将此作业发送到打印机也需要很长时间。

那么,有没有一种简单的方法可以在不支付第三方封闭解决方案费用的情况下进行邮件合并(最好使用Python)?

I often get a PDF from our designer (built in Adobe InDesign) which is supposed to be sent out to thousands of people.

I've got the list with all the people, and it's easy doing a mail merge in OpenOffice.org. However, OpenOffice.org doesn't support the advanced PDF. I just want to output some text onto each page and print it out.

Here's how I do it now: print out 6.000 copies of the PDF, then put all of them into the printer again and just print out name, address and other information on top of it. But that's expensive.

Sadly, I can't make the PDF to an image and use that in OpenOffice.org because it grinds the computer to a halt. It also takes extremely long time to send this job to the printer.

So, is there an easy way to do this mail merge (preferably in Python) without paying for third party closed solutions?

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

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

发布评论

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

评论(11

笨笨の傻瓜 2024-07-16 21:57:35

现在我已经注册了一个帐户。 我使用巧妙的 pdftk 修复了它。

在我的探索中,我完全忽略了“背景”和“覆盖”功能。 我的解决方案是这样的:

pdftk names.pdf background boat_background.pdf output out.pdf

创建 names.pdf,您可以使用 Python reportlab 或类似的 PDF 创建脚本轻松完成。 最好使用代码来做到这一点,在 LibreOffice/OpenOffice 中创建 6k 页面需要几个小时,而使用 Python 只需几秒钟。

Now I've made an account. I fixed it by using the ingenious pdftk.

In my quest I totally overlook the feature "background" and "overlay". My solution was this:

pdftk names.pdf background boat_background.pdf output out.pdf

Creating the names.pdf you can easily do with Python reportlab or similar PDF-creation scripts. It's best using code to do that, creating 6k pages took several hours in LibreOffice/OpenOffice, while it took just a few seconds using Python.

静待花开 2024-07-16 21:57:35

您可以查看 PDF 库,例如 iText。 如果您有一些编程知识和一点时间,您可以编写一些代码将联系信息添加到 PDF

You could probably look at a PDF library like iText. If you have some programming knowledge and a bit of time you could write some code that adds the contact information to the PDFs

雪落纷纷 2024-07-16 21:57:35

有两种更简单、更便宜的解决方案。

首先,您可以使用 DataMerge 直接在 InDesign 中进行邮件合并。 这是早在 CS 时代就添加到 InDesign 中的实用程序。 您可以将您的姓名导出或保存为 CSV 格式。 将数据导入 InDesign 模板,然后将您的姓名、地址等字段放入布局中。 按开始。 它将创建一个包含所有已完成字母的新文档,或者您可以直接使用打印机。

或者,您可以将数据导出到 XML 文件并使用 InDesign 中的 XML 占位符创建动态布局。

《Adobe InDesign 和 XML 设计师指南》一书将教您如何执行此操作,或者您也可以查看 Lynda.com 视频,了解使用 InDesign 和 XML 实现动态工作流程。

很容易做到。

如果您想为邮件合并创建单独的 PDF 文件,您可以运行一份包含所有名称的长 PDF 文件,然后在 Acrobat Pro 本身中执行“提取到单独的 PDF 文件”操作。

There are two much simpler and cheaper solutions.

First, you can do your mail merge directly in InDesign using DataMerge. This is a utility added to InDesign way back in CS. You export or save your names in CSV format. Import the data into an InDesign template and then drop in your name, address and such fields in the layout. Press Go. It will create a new document with all the finished letters or you can go right to the printer.

OR, you can export your data to an XML file and create a dynamic layout using XML placeholders in InDesign.

The book A Designer's Guide to Adobe InDesign and XML will teach you how to do this, or you can check out the Lynda.com videos for Dynamic workflows with InDesign and XML.

Very easy to do.

If you want to create separate PDFs files for the mail merge, you can run out one long PDF with all the names in one file then do an Extract to Separate PDF files in Acrobat Pro itself.

噩梦成真你也成魔 2024-07-16 21:57:35

如果您无法获取 PDF 以外的其他格式的模板,一个简单的临时解决方案是将

  • PDF 转换为图像,
  • 将图像放在 (OpenOffice.org) 文档的背景中
  • ,将邮件合并字段放在图像顶部,
  • 执行以下操作:邮件合并并打印

If you cannot get the template in another format than PDF a simple ad-hoc solution would be to

  • convert the PDF into an image
  • put the image in the backgroud of your (OpenOffice.org) document
  • position mail merge fields on top of the image
  • do the mail merge and print
゛时过境迁 2024-07-16 21:57:35

最好的方法可能是生成另一个包含缺失文本的 PDF,然后将一个 PDF 覆盖在另一个 PDF 上。 快速 Google 后发现此链接显示了如何在 Acrobat 中执行此操作,并且我确信还有其他方法。

http://forums.macrumors.com/showthread.php?t=508226

Probably the best way would be to generate another PDF with the missing text, and overlay one PDF over the other. A quick Google found this link showing how to do it in Acrobat, and I'm sure there are other methods as well.

http://forums.macrumors.com/showthread.php?t=508226

葬花如无物 2024-07-16 21:57:35

要获得简洁的解决方案,请使用 iText 将文本简单地添加到 pdf 中。 例如,您可以执行以下操作,在加载后将文本添加到 pdf 文档中:

PdfContentByte cb= ...;
cb.BeginText();
cb.SetFontAndSize(font, fontSize);
float x = ...;
float y = ...;
cb.SetTextMatrix(x, y);
cb.ShowText(fieldValue);
cb.EndText();    

从那里开始,将其另存为不同的文件,然后打印。

然而,我发现表单字段是从模板生成 pdf 文档的方法。

如果您有带有表单字段的模板(使用 Adob​​e Acrobat 添加),则您有以下两种选择之一:

  • 创建 FDF 文件,该文件本质上是表单上字段的值列表。 FDF 是一个简单的文本文档,它引用原始文档,因此当您打开 PDF 时,文档会加载 FDF 提供的字段值。
  • 或者,使用 iText / iTextSharp 等库加载模板,手动填写表单字段,并将其另存为单独的 pdf。

示例 FDF 文件如下所示(从 Planet PDF) :

%FDF-1.2
%âãÏÓ
1 0 obj
<<<
 /F(Example PDF Form.pdf)
 /Fields[
  <<
  /T(myTextField)
  /V(myTextField default value)
  >>
  ]
 >>
>> endobj trailer
<>
%%EOF

由于 FDF 格式简单且尺寸较小,因此这是首选方法,并且该方法应该适用于任何语言。

至于以编程方式填充字段,您可以通过以下方式使用 iText :

PdfAcroForm acroForm = writer.AcroForm;
acroForm.Put(new PdfName(fieldInfo.Name), new PdfString(fieldInfo.Value));

For a no-mess, no-fuss solution, use iText to simply add the text to the pdf. For example, you can do the following to add text to a pdf document once loaded:

PdfContentByte cb= ...;
cb.BeginText();
cb.SetFontAndSize(font, fontSize);
float x = ...;
float y = ...;
cb.SetTextMatrix(x, y);
cb.ShowText(fieldValue);
cb.EndText();    

From there on, save it as a different file, and print it.

However, I've found that form fields are the way to go with pdf document generation from templates.

If you have a template with form fields (added with Adobe Acrobat), you have one of two choices :

  • Create a FDF file, which is essentially a list of values for the fields on the form. A FDF is a simple text document which references the original document so that when you open up the PDF, the document loads with the field values supplied by the FDF.
  • Alternatively, load the template with with a library like iText / iTextSharp, fill the form fields manually, and save it as a seperate pdf.

A sample FDF file looks like this (stolen from Planet PDF) :

%FDF-1.2
%âãÏÓ
1 0 obj
<<<
 /F(Example PDF Form.pdf)
 /Fields[
  <<
  /T(myTextField)
  /V(myTextField default value)
  >>
  ]
 >>
>> endobj trailer
<>
%%EOF

Because of the simple format and the small size of the FDF, this is the preferred approach, and the approach should work well in any language.

As for filling the fields programmatically, you can use iText in the following way :

PdfAcroForm acroForm = writer.AcroForm;
acroForm.Put(new PdfName(fieldInfo.Name), new PdfString(fieldInfo.Value));
一桥轻雨一伞开 2024-07-16 21:57:35

使用可变数据程序(例如 - XMPie for Adob​​e Indesign)怎么样? 它是一个应该引用您的人员列表的插件(不过我认为它可能必须是 Excel 中的列表)。

What about using a variable data program such as - XMPie for Adobe Indesign. It's a plug-in that should reference to your list of people (think it might have to be a list in Excel though).

盗梦空间 2024-07-16 21:57:35

一种简单的方法是在 Acrobat 中根据原始文档创建可填写的 pdf 表单,然后将该表单和 csv 进行邮件合并。

PDF 邮件合并在 python 和 pdftk 中相对容易完成。 Fdfgen (pip install fdfgen) 是一个 python 库,它将从 python 数组创建 fdf,因此您可以将 excel 网格保存到 csv,确保 csv 标题与 pdf 的名称匹配您想要填写该列的表单字段,然后执行类似

import csv
import subprocess

from fdfgen import forge_fdf

PDF_FORM = 'path/to/form.pdf'
CSV_DATA = 'path/to/data.csv'

infile = open(CSV_DATA, 'rb')
reader = csv.DictReader(infile)
rows = [row for row in reader]
infile.close()

for row in rows:
    # Create fdf
    filename = row['filename'] # Construct filename
    fdf_data = [(k,v) for k, v in row.items()]
    fdf = forge_fdf(fdf_data_strings=fdf_data)
    fdf_file = open(filename+'.fdf', 'wb')
    fdf_file.write(fdf)
    fdf_file.close()

    # Use PDFTK to create filled, flattened, pdf file
    cmds = ['pdftk', PDF_FORM, 'fill_form', filename+'.fdf',
            'output', filename+'.pdf', 'flatten', 'dont_ask']
    process = subprocess.Popen(cmds, stdout=subprocess.PIPE)
    stdout, stderr = process.communicate()
    returncode = process.poll()
    os.remove(filename+'.fdf')

我已经遇到此问题足以编写自己的免费解决方案的操作, PdfZero。 PdfZero 具有邮件合并功能,可将电子表格与 PDF 表单合并。 您仍然需要创建 PDF 表单,但您可以将表单和 csv 上传到 pdfzero,选择要填充哪些表单字段、哪些列、根据需要使用 csv 数据为每个填充的 pdf 创建命名约定,然后批量生成填充的 PDF。

免责声明:我写了 PdfZero

One easy way would be to create a fillable pdf form from the original document in Acrobat and do a mail merge with the form and a csv.

PDF mail merges are relatively easy to do in python and pdftk. Fdfgen (pip install fdfgen) is a python library that will create an fdf from a python array, so you can save the excel grid to a csv, make sure that the csv headers match the name of the pdf form field you want to fill with that column, and do something like

import csv
import subprocess

from fdfgen import forge_fdf

PDF_FORM = 'path/to/form.pdf'
CSV_DATA = 'path/to/data.csv'

infile = open(CSV_DATA, 'rb')
reader = csv.DictReader(infile)
rows = [row for row in reader]
infile.close()

for row in rows:
    # Create fdf
    filename = row['filename'] # Construct filename
    fdf_data = [(k,v) for k, v in row.items()]
    fdf = forge_fdf(fdf_data_strings=fdf_data)
    fdf_file = open(filename+'.fdf', 'wb')
    fdf_file.write(fdf)
    fdf_file.close()

    # Use PDFTK to create filled, flattened, pdf file
    cmds = ['pdftk', PDF_FORM, 'fill_form', filename+'.fdf',
            'output', filename+'.pdf', 'flatten', 'dont_ask']
    process = subprocess.Popen(cmds, stdout=subprocess.PIPE)
    stdout, stderr = process.communicate()
    returncode = process.poll()
    os.remove(filename+'.fdf')

I've encountered this problem enough to write my own free solution, PdfZero. PdfZero has a mail merge feature to merge spreadsheets with PDF forms. You will still need to create a PDF form, but you can upload the form and csv to pdfzero, select which form fields you want filled with which columns, create a naming convention for each filled pdf using the csv data if needed, and batch generate the filled PDfs.

DISCLAIMER: I wrote PdfZero

摘星┃星的人 2024-07-16 21:57:35

有人询问具体情况。 我不想用它来玷污我的最佳答案,因为你可以按照你喜欢的方式去做(并且只要知道 pdftk 就可以给人们带来想法)。

但这里有一些我很久以前使用过的脚本:

csv_to_pdf.py

#!/usr/bin/python
# This makes one PDF page per name in the CSV file
# csv_to_pdf.py <CSV_FILE>

import csv
import sys
from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.units import cm, mm

in_db = csv.reader(open(sys.argv[1], "rb"));
outname = sys.argv[1].replace("csv", "pdf")
pdf = Canvas(outname)
in_db.next()

i = 0
for rad in in_db:
        pdf.setFontSize(11)
        adr = rad[1]

        tekst = pdf.beginText(2*cm, 26*cm)

        for a in adr.split('\n'):
            if not a.strip():
                continue
            if a[-1] == ',':
                a = a[:-1]
            tekst.textLine(a)
        pdf.drawText(tekst)
        pdf.showPage()

        i += 1
        if i % 1000 == 0:
                print i
pdf.save()

当您运行此脚本时,您会得到一个包含数千页的文件,其中只有一个名称。 此时您可以将精美的 PDF 放在所有这些文件的背景下:

pdftk <YOUR_NEW_PDF_FILE.pdf> background <DESIGNED_FILE.pdf> <MERGED.pdf>

Someone asked for specifics. I didn't want to sully my top answer with it, because you can do it how you like (and just knowing pdftk is up to it should give people the idea).

But here's some scripts I used ages ago:

csv_to_pdf.py

#!/usr/bin/python
# This makes one PDF page per name in the CSV file
# csv_to_pdf.py <CSV_FILE>

import csv
import sys
from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.units import cm, mm

in_db = csv.reader(open(sys.argv[1], "rb"));
outname = sys.argv[1].replace("csv", "pdf")
pdf = Canvas(outname)
in_db.next()

i = 0
for rad in in_db:
        pdf.setFontSize(11)
        adr = rad[1]

        tekst = pdf.beginText(2*cm, 26*cm)

        for a in adr.split('\n'):
            if not a.strip():
                continue
            if a[-1] == ',':
                a = a[:-1]
            tekst.textLine(a)
        pdf.drawText(tekst)
        pdf.showPage()

        i += 1
        if i % 1000 == 0:
                print i
pdf.save()

When you've ran this, you have a file with thousands of pages, only with a name on it. This is when you can background the fancy PDF under all of them:

pdftk <YOUR_NEW_PDF_FILE.pdf> background <DESIGNED_FILE.pdf> <MERGED.pdf>
一腔孤↑勇 2024-07-16 21:57:35

您可以使用 InDesign 的数据合并功能,也可以像以前一样打印作业的一部分,然后使用 Word 或 Open Office 打印邮件合并。
但也要考虑寻找一家可以进行可变数据胶印或动态出版的公司。 前期可能会贵一些,但在时间、测试、甚至包装和邮寄方面可以节省很多。

You can use InDesign's data merge function, or you can do what you've been doing with printing a portion of the job, and then printing the mail merge atop that with Word or Open Office.
But also look into finding a company that can do variable data offset printing or dynamic publishing. Might be a little more expensive up front but can save a bundle when it comes to time, testing, even packaging and mailing.

┊风居住的梦幻卍 2024-07-16 21:57:35

免责声明:我是这个工具的作者。

我多次遇到这个问题,因此我为其构建了一个免费的在线工具:https://pdfbatchfill.com/

它假定 PDF 表单作为模板,并使用它与 CSV 表单数据一起生成单个 PDF 或 zip 文件中的各个 PDF。

Disclaimer: I'm the author of this tool.

I ran into this issue enough times that I built a free online tool for it: https://pdfbatchfill.com/

It assumes a PDF form as a template and uses that along with CSV form data to generate a single PDF or individual PDFs in a zip file.

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