English 中文(简体)
如何在PDF顶部执行邮件合并?
原标题:
  • 时间:2008-12-10 15:38:41
  •  标签:

我經常從我們的設計師那裡收到一個 PDF (用 Adobe InDesign 創建),據說要發送給成千上萬的人。

我有所有人的名单,并且在OpenOffice.org中执行邮件合并很容易。然而,OpenOffice.org不支持高级PDF。我只想将一些文本输出到每个页面上并打印它。

这是我现在的做法:打印出6,000份PDF副本,然后再把它们全部放回打印机中,在其顶部打印姓名、地址和其他信息。但这很昂贵。

可悲的是,我无法将PDF转换为图像并在OpenOffice.org中使用,因为它会使计算机变得异常缓慢。同时,将此任务发送到打印机也需要极长的时间。

那么,有没有一种简便的方法来执行邮件合并(最好是用Python),而不用付费使用第三方封闭解决方案呢?

问题回答

现在我已经创建了一个账户。我使用了巧妙的pdftk修复了它。

在寻找过程中,我完全忽略了"背景"和"叠加"功能。我的解决方案是这样的:

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

使用Python reportlab或类似的PDF创建脚本可以轻松地创建names.pdf。最好使用代码进行操作,使用LibreOffice / OpenOffice创建6k页需要数小时,而使用Python只需要几秒钟。

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

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

首先,您可以直接在InDesign中使用DataMerge进行邮件合并。这是在CS很久以前添加到InDesign的实用工具。您可以将姓名以CSV格式导出或保存。将数据导入InDesign模板,然后将姓名、地址等字段放入布局中。按下Go键。它将创建一个包含所有完成的信函的新文档,或者您可以直接去打印机。

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

《设计师指南:Adobe InDesign和XML》这本书会教你怎样做,或者你也可以观看Lynda.com的“使用InDesign和XML进行动态工作流程”的视频。

非常容易完成。

如果您想为邮件合并创建单独的PDF文件,可以先将所有姓名放在一个文件中,然后在Acrobat Pro中执行“提取到单独的PDF文件”操作来生成单独的PDF文件。

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

  • 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

可能最好的方法是生成另一个带有丢失文本的PDF,并将一个PDF叠加在另一个上面。快速搜索谷歌发现这个链接可以在Acrobat中进行操作,我相信还有其他方法。

将此翻译成中文:http://forums.macrumors.com/showthread.php?t=508226 http://forums.macrumors.com/showthread.php?t=508226

为了实现无杂乱、无麻烦的解决方案,使用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添加),您有两个选择:

  • 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.

一个样例的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));

如何使用可变数据程序(例如Adobe Indesign的XMPie插件)?它是一个插件,应该与您的人员名单相对应(可能需要在Excel中列出)。

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

PDF邮件合并在Python和pdftk中相对较容易实现。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,选择要使用哪些列填充哪些表单字段,如果需要,为每个已填充的pdf创建命名约定,并批量生成填充的PDf。

免责声明:我编写了PdfZero。

有人要求具体说明。我不想用我的顶部答案来污染它,因为你可以按照自己的方式来做(只要知道pdftk能做到这一点就应该让人们有了想法)。

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

csv_to_pdf.py 的中文翻译为: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( 
 ):
            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>

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.

免责声明:本工具作者为我。

我遇到了这个问题很多次,所以我开发了一个免费在线工具来解决它: https://pdfbatchfill.com/

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





相关问题
热门标签