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

时间:2008-12-10 15:38:41

标签: pdf pdf-generation mailmerge adobe-indesign

我经常从我们的设计师(内置于Adobe InDesign中)获取PDF,该PDF应该发送给成千上万的人。

我已经获得了所有人的列表,并且很容易在OpenOffice.org中进行邮件合并。但是,OpenOffice.org不支持高级PDF。我只是想在每个页面上输出一些文字并打印出来。

以下是我现在的操作方法:打印出6.000份PDF文件,然后将所有这些文件再次打印到打印机中,然后在其上打印出名称,地址和其他信息。但那很贵。

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

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

11 个答案:

答案 0 :(得分:7)

现在我已经开了帐户。我使用巧妙的pdftk修复了它。

在我的追求中,我完全忽略了“背景”和“叠加”这一特征。我的解决方案是:

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

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

答案 1 :(得分:2)

你可能会看到像iText这样的PDF库。如果您有一些编程知识和一些时间,您可以编写一些代码,将联系信息添加到PDF

答案 2 :(得分:2)

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

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

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

“设计师指南”中的Adobe InDesign和XML将教您如何执行此操作,或者您可以使用InDesign和XML查看Lynda.com视频中的动态工作流程。

很容易做到。

如果要为邮件合并创建单独的PDF文件,可以在一个文件中运行一个包含所有名称的长PDF,然后在Acrobat Pro中自行提取以分离PDF文件。

答案 3 :(得分:1)

如果您无法以PDF格式之外的其他格式获取模板,则可以使用简单的临时解决方案

  • 将PDF转换为图像
  • 将图像放入(OpenOffice.org)文档的背景中
  • 在图像顶部放置邮件合并字段
  • 进行邮件合并并打印

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

对于一个没有乱七八糟的解决方案,使用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文档的方法。

如果您的模板包含表单字段(使用Adobe 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));

答案 6 :(得分:1)

如何使用可变数据程序,例如 - XMPie for Adob​​e Indesign。这是一个应该引用您的人员列表的插件(虽然它可能必须是Excel中的列表)。

答案 7 :(得分:1)

一种简单的方法是从Acrobat中的原始文档创建一个可填充的pdf表单,然后使用该表单和一个csv进行邮件合并。

在python和pdftk中,PDF邮件合并相对容易。 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创建命名约定,并批量生成填充的PDfs。

免责声明:我写了PdfZero

答案 8 :(得分:1)

有人要求提供详细信息。我不想用它来回答我的最高答案,因为您可以按照自己的喜好来做(只是知道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>

答案 9 :(得分:0)

您可以使用InDesign的数据合并功能,或者您可以执行打印部分作业所做的操作,然后使用Word或Open Office打印邮件合并。 但也要寻找一家可以进行可变数据胶印或动态发布的公司。可能会更加昂贵,但在时间,测试,甚至包装和邮寄方面都可以节省成本。

答案 10 :(得分:0)

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

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

它假设PDF表单作为模板,并将其与CSV表单数据一起使用,以zip文件格式生成单个PDF或单个PDF。