写下 \includepdf{paper.pdf},却只插进来一页——这是初次使用 LaTeX 的 pdfpages 时人人都会踩的第一级台阶。原因是该选项的默认值是 pages=1,也就是「只要第 1 页」;实测中,一个 5 页的 PDF 在不加选项时输出正好一页。要全部插入,就写 pages=-(同一个 PDF 便得到 5 页)。记住这一个字符,pdfpages 的其余功能就随之打开——该宏包作者是 Andreas Matthias,TeX Live 2024 附带的是 v0.5y,日期 2024/01/21。加封面、把各章 PDF 拼成学位论文、把幻灯片按 2×2 排成讲义、给每一页盖上 DRAFT、给书签和目录添加条目:本页逐一实际编译验证。
includepdf 怎么用 — 与 includegraphics 有何不同
在导言区载入 \usepackage{pdfpages},正文中调用 \includepdf[…]{file}。区别在于它是 以整页为单位 工作的。\includegraphics 把 PDF 当作「图」放进正文流,所以只要比版面大就会溢出,而且仍受文档页边距约束。\includepdf 则新起一张纸,并把源 PDF 的页面 自动缩放 以放进这张纸。实测中,一个以 A5(419.5 x 595.3pt)制作的 PDF 被读入 letter 尺寸的文档后,输出页是 612 x 792pt 的 letter——被缩放的是源页面,而不是纸张。文件名 不得包含空格。
\includepdf 在内部调用 graphicx 的 \includegraphics,所以凡是 pdfpages 自己不解释的选项——trim、clip、scale、angle 等——都会原样转交给它。若要裁掉所导入页面的页眉页脚,可以写 \includepdf[pages=-, trim=0 2cm 0 2cm, clip]{paper.pdf}。想停止自动缩放就用 noautoscale,想平移导入的页面就用接收两个尺寸的 offset。
\documentclass{article}
\usepackage{pdfpages}
\begin{document}
% body text ...
\includepdf[pages=-]{cover.pdf}
% ... body text continues
\end{document}pages 的写法 — 全部页面、逆序、插入白页
pages 用逗号分隔列出要插入的页面 及其顺序。范围写作 m-n;省略 m 表示第一页,省略 n 表示最后一页。所以 pages=- 读作「从头到尾」。最后一页也可以用关键字 last 指代,它只在范围内有效。有意思的正是顺序:写 pages=last-1 会 逆序 插入,实测中一个 8 页的 PDF 依次输出为 PAGE 8 到 PAGE 1。
另一个值得记住的技巧是 空的 {}。在列表中写 {},该处就会插入 一张白纸。写 pages={1,{},2-21} 就得到「封面、白页、正文第 1–20 页」的顺序。实测中,pages={1,{},2} 输出了 3 页,而抽取的文本只有 PAGE 1 与 PAGE 2 两项——中间那页确实是空白。双面印刷的学位论文中,要让每章都从右页开始时就用它。
% cover, then one blank leaf, then body pages 1-20
\includepdf[pages={1,{},2-21}]{thesis-cover.pdf}
% every page, in reverse order
\includepdf[pages=last-1]{scan.pdf}
% a hand-picked selection, in this order
\includepdf[pages={3,1,4,1,5}]{notes.pdf}| 写法 | 插入的页面 |
|---|---|
(omitted) | 只有第 1 页——默认是 pages=1 |
pages=- | 从头到尾的全部页面 |
pages={2-8} | 第 2 页到第 8 页 |
pages={1,3,5} | 只要第 1、3、5 页,按此顺序 |
pages={3,{},15} | 第 3 页、一张白纸、第 15 页 |
pages=last-1 | 全部页面逆序;last 只在范围内有效 |
pages={1-3,5,{},7} | 范围、单页与白页可以自由混用 |
用 nup 制作 2x2 讲义 — landscape 会写入 /Rotate
写 nup=横x纵 就能把多个逻辑页平铺到一张纸上。实测中,一个 8 页的幻灯片 PDF 以 nup=2x2 读入时输出 2 张,以 nup=2x1, landscape 读入时输出 4 张。默认按行填充(从左到右,再换行);加 column 改为按列填充,加 columnstrict 则连最后一张纸也严格保持列序。delta 用于在页面之间留出间隙(两个尺寸,如 delta=5mm 5mm),frame 用于给每一页加框。
landscape 旋转的是 纸张,摆在上面的页面本身仍是竖直的;若要旋转页面本身,请用 angle=90。有意思的是,这个 landscape 会 往 PDF 中写入 /Rotate 90。用 pdfinfo -f 1 -l 1 检查以 nup=2x1, landscape 生成的文件,会得到 Page 1 rot: 90,而纸张尺寸仍是 612 x 792——阅读器会自动转过来显示。若要抑制这一行为,设置 turn=false(默认是 turn=true)。pdflscape 宏包使用同样的机制;关于超出正文宽度的表格那一页对二者做了详细比较。
% four slides per sheet, boxed, with a gap between them
\includepdf[pages=-, nup=2x2, frame, delta=5mm 5mm]{slides.pdf}
% two pages side by side on a landscape sheet
\includepdf[pages=-, nup=2x1, landscape]{report.pdf}fitpaper — 让纸张去迁就源 PDF
默认情况下源页面会缩放去适应你的纸张,而 fitpaper=true 反过来,让纸张尺寸去匹配源 PDF。实测中,把一个 A5 的 8 页 PDF 以 fitpaper=true 读入 letter 尺寸的文档,输出页尺寸是 419.527 x 595.275pt——原本的 A5,原封不动。适用于缩放会损害画质的扫描稿,以及版面已经固定的提交用表单。
对于页面尺寸不统一的源文件,也有相应工具。默认情况下 第一张插入的页面成为模板,其后各页都会被缩放到能装进它的轮廓。若要指定别的页面作模板,用 pagetemplate=⟨页码⟩;若要直接给出尺寸,用 templatesize={⟨宽⟩}{⟨高⟩}——为避开舍入误差,请稍微设大一点。横向页面遇上纵向模板时默认会被缩小,而 rotateoversize=true 会 将其旋转以放入。若想 2 面付印刷、事后裁开得到两份,doublepages 会把每一页插入两次。
| 选项 | 作用(默认值) |
|---|---|
nup | 在一张纸上平铺多页;nup=2x2 是横 2 × 纵 2。默认 1x1 |
frame | 给每个逻辑页加上粗细为 \fboxrule 的边框。默认 false |
delta | 拼版页面之间的间隙;两个尺寸以空格分隔。默认 0 0 |
landscape | 把纸张变为横向,并往 PDF 写入 /Rotate 90。默认 false |
turn | 横向页面是否由阅读器旋转显示。默认 true |
scale | 转交给 \includegraphics 的缩放系数;与 noautoscale 搭配可手动控制 |
fitpaper | 把纸张尺寸调整为所插入文档的尺寸。默认 false |
offset | 平移插入页面的原点;两个尺寸。默认 0 0 |
pagecommand | 在每个插入页上执行的 LaTeX 代码。默认 \thispagestyle{empty} |
picturecommand | 在以页面左下角为原点的 picture 中执行的命令。默认为空 |
link | 让插入页成为名为 ⟨文件名⟩.⟨页码⟩ 的链接目标。默认 false;用 linkname 改名 |
恢复页码与盖上 DRAFT — pagecommand 与 picturecommand
若希望 在导入的页面上打印你自己文档的页码,就用 pagecommand。这个选项接收在每个插入页上执行的 LaTeX 代码,而 pdfpages.sty 把它的默认值定义为 \thispagestyle{empty}——这正是导入页既无页码也无页眉的原因。改成 pagecommand={\thispagestyle{plain}},你自己的页码就会印在上面。
这里有个陷阱:为自己的用途覆盖 pagecommand,会连同默认的 \thispagestyle{empty} 一起抹掉。 实测中,一份只把绘制水印的代码交给 pagecommand 的文档,在导入页上印出了 1、2、3… 的页码,完全不是本意。若不想要这些页码,就得在自己的代码开头补上 \thispagestyle{empty}。
至于加水印或盖章本身,有专门的钩子。picturecommand 接收在一个 picture 环境中执行的命令,该环境的 原点是每一页的左下角——即使页面被 landscape 转过去,原点也不移动。实测中,给一个 8 页的导入传入 picturecommand={\put(30,30){\Large CONFIDENTIAL}},pdftotext 的输出是 PAGE 1 CONFIDENTIAL PAGE 2 CONFIDENTIAL …,每一页都盖上了。若只想盖第一页,就用 picturecommand*。
% your own page numbers on the imported pages
\includepdf[pages=-, pagecommand={\thispagestyle{plain}}]{paper.pdf}
% stamp every imported page; the picture origin is its lower-left corner
\includepdf[pages=-,
picturecommand={\put(30,30){\Large CONFIDENTIAL}}]{paper.pdf}
% ...and picturecommand* would stamp only the first inserted page用各章 PDF 组装学位论文 — includepdfmerge 与 addtotoc
把分别排版好的 PDF 拼接起来的命令是 \includepdfmerge。它的参数是「文件名, 页面指定, 文件名, 页面指定, …」的序列,页面指定与 pages 语法相同;省略时只取该文件的第 1 页。实测中,\includepdfmerge{a.pdf,1-2,b.pdf,3} 输出了 3 页,依次是 PAGE 1、PAGE 2、SOURCE PAGE 3。若不想每次都写同样的选项,可以用 \includepdfset{…} 统一设定默认值,个别 \includepdf 上写的选项会覆盖它。
插入的 PDF 本身不会出现在目录或书签中。解决这个问题的是 addtotoc,它接收五个逗号分隔的参数:addtotoc={⟨页码⟩,⟨节类型⟩,⟨层级⟩,⟨标题⟩,⟨标签⟩}。页码是在你插入的页面中的序号,节类型是诸如 section 的分节名,层级是表示深度的数字,标题是要在目录中打印的字符串,标签则是可供 \ref 和 \pageref 引用的名字。这五项的顺序不可调换。
与 hyperref 配合时,这一个选项能一次完成三件事。来实测:在载入了 hyperref 的文档中指定 addtotoc={1,section,1,Imported paper,sec:paper},.toc 中写入了 \contentsline {section}{\numberline {2}\ignorespaces Imported paper}{2},.out 中出现了 \BOOKMARK [1][-]{section.2}{Imported paper}{},而正文中的 \ref{sec:paper} 与 \pageref{sec:paper} 也正确解析。目录条目、PDF 书签、交叉引用,三者都出自这一行。 若要加进图表目录,用 addtolist。
\documentclass{article}
\usepackage{hyperref}
\usepackage{pdfpages} % load pdfpages after hyperref
\begin{document}
\tableofcontents
\section{Front matter}
% one contents entry, one PDF bookmark, one \ref target
\includepdf[pages=-,
pagecommand={\thispagestyle{plain}},
addtotoc={1,section,1,Imported paper,sec:paper}]{paper.pdf}
\section{After}
See \ref{sec:paper} on page \pageref{sec:paper}.
% assemble a thesis from separately typeset parts
\includepdfmerge{frontmatter.pdf, -, chap1.pdf, -, chap2.pdf, -}
\end{document}signature=8 排出的顺序 — 8, 1, 2, 7, 6, 3, 4, 5
要做骑马钉小册子,就必须把页面重排成 折起来后顺序正确 的样子。给 pdfpages 的 signature 选项一个 4 的倍数,它就会按该数组成折帖,并根据方向自动以 nup=1x2 或 nup=2x1 拼版。来实测:一个 8 页的 PDF 指定 signature=8, landscape 后输出 4 面,抽取的页面顺序是 PAGE 8、PAGE 1、PAGE 2、PAGE 7、PAGE 6、PAGE 3、PAGE 4、PAGE 5。把它双面印在两张纸上,叠起来对折,翻开时页面正是 1 到 8 的顺序。
需要注意的是,pages=-, nup=1x2, landscape 完全不会重排页序。它只是把两页并排放置,折起来顺序就不对了。若要做折帖,就必须用 signature。若需要更复杂的拼版(多个折帖、爬移补偿、裁切标记等),TeX Live 中还有专门的 booklet 宏包。
% a saddle-stitched booklet in signatures of eight pages
\includepdf[pages=-, signature=8, landscape]{booklet-doc.pdf}导入会丢失链接 — pax 与 link 选项
\includepdf 复制的只是每一页的 外观。源 PDF 中的链接会失效——pdfpages 手册明确指出,丢失的不只是链接,而是 各种 PDF 注释(annotation)。若要保留原有链接,可搭配 pax(Heiko Oberdiek)使用,它会提取注释并重新贴回。
反过来说,pdfpages 也能 自己创建链接目标。传入 link=true,每个插入的页面就会成为名为 ⟨文件名⟩.⟨页码⟩ 的目标,于是正文中的 \hyperlink{paper.pdf.3}{…} 就能跳到导入的第 3 页。linkname=mylink 可改变基名,linkfilename、linktodoc、linkfit、newwindow 则用于指向外部文件的链接。创建文章串的 thread、threadname 属于同一系列。
引擎与驱动 — pLaTeX 与 dvipdfmx 下变成白页时
pdfpages 手册列出的引擎是 pdfTeX、VTeX、XeTeX、LuaTeX 和 pTeX,所以在 pdfLaTeX、LuaLaTeX、XeLaTeX 以及 (up)pLaTeX 下都能工作。不过它假定引擎会直接输出 PDF:在经由 DVI 的路线上无法导入 PDF,取而代之的是白页。在日语圈常见的 pLaTeX + dvipdfmx 配置中,导入 PDF 是 dvipdfmx 的工作,因此必须正确指定图形驱动。手册推荐的写法是把 dvipdfmx 作为文档类选项传入。
% the driver the pdfpages manual recommends for the platex route
\documentclass[dvipdfmx]{article}
\usepackage{pdfpages}
% ...or state it explicitly on graphicx
% \usepackage[dvipdfmx]{graphicx}这条路线还有一个值得知道的怪癖:pdfpages 会调用外部程序 extractbb 来查明导入 PDF 的总页数,但如果已经存在对应的 .xbb 文件,它就不再调用 extractbb,而直接使用该文件的内容。若替换了源 PDF 却留下了过期的 .xbb,页数就对不上,插入也会出错;因此更新 PDF 后请一并重新生成 .xbb。最后还有一个针对带背景色文档的陷阱:第一个 \pagecolor 必须放在 \usepackage{pdfpages} 之前。