如何在包含 PDF 页面之前确定它是否存在?

如何在包含 PDF 页面之前确定它是否存在?

我想在使用 插入 PDF 之前测试它是否包含指定页面\includegraphicx[page=?]{filename.pdf}。(通常指定不存在的页面会产生致命错误。)我该如何对 、 和 执行pdflatexxelatex操作lualatex

梅威瑟:

\documentclass{article}
\usepackage{graphicx}
\usepackage{filecontents}
\begin{filecontents*}{\jobname page.pdf}
%PDF-1.1
1 0 obj <</Type /Catalog /Pages 2 0 R>>
endobj
2 0 obj <</Type /Pages /Kids [3 0 R] /Count 1>>
endobj
3 0 obj<</Type /Page /Parent 2 0 R /Resources 4 0 R /MediaBox [0 0 70 50] /Contents 6 0 R>>
endobj
4 0 obj<</Font <</F1 5 0 R>>>>
endobj
5 0 obj<</Type /Font /Subtype /Type1 /BaseFont /Helvetica>>
endobj
6 0 obj
<</Length 36>>
stream
BT /F1 10 Tf 20 20 Td (Page 1)Tj ET
endstream
endobj
xref
0 9
0000000000 65535 f
0000000009 00000 n
0000000056 00000 n
0000000111 00000 n
0000000210 00000 n
0000000248 00000 n
0000000315 00000 n
trailer <</Size 7/Root 1 0 R>>
startxref
398
%%EOF
\end{filecontents*}
% \includepdfifhaspage{filename.pdf}{page}
\newcommand{\includepdfifhaspage}[2]{%
  \iftrue % <- what test should go here?
    \includegraphics[page=#2]{#1}%
  \else
    % do nothing
  \fi
}
\begin{document}
% insert page one of pdf:
\includepdfifhaspage{\jobname page.pdf}{1}
% insert nothing, since there is no page 2:
\includepdfifhaspage{\jobname page.pdf}{2}
\end{document}

答案1

我从包 pdfpages 源代码中提取了方法,该方法本身似乎是从 graphicx/pdftex.def 获取的。

我最初查看了 pdfpages 文档,但没有找到用户级界面。以下是其源代码中的相关文档:

%    Unfortunately, |\pdflastximagepages| is not updated if |\includegraphics|
%    is used repeatedly on the same file. Heiko is aware of this and will provide
%    a solution in pdftex.def. Until then we will use the original graphicx's filename
%    from |\Gread@@pdftex|.
%    
%    \def\AM@getpagecount{%
%      \setbox\@tempboxa=\hbox{\includegraphics{\AM@currentdocname}}%
%      \edef\AM@pagecount{\the\AM@lastsavedimageresourcepages}%
%    }

注意:pdfpages 可能应该在其 中使用draft选项。这就是我在这里所做的。\includegraphics\AM@getpagecount

编辑:在这个答案的第一个版本中,我太容易忽略了上述评论,并且修剪了太多的代码pdfpages.sty

\documentclass{article}
\usepackage{graphicx}
\usepackage{filecontents}
\begin{filecontents*}{\jobname page.pdf}
%PDF-1.1
1 0 obj <</Type /Catalog /Pages 2 0 R>>
endobj
2 0 obj <</Type /Pages /Kids [3 0 R] /Count 1>>
endobj
3 0 obj<</Type /Page /Parent 2 0 R /Resources 4 0 R /MediaBox [0 0 70 50] /Contents 6 0 R>>
endobj
4 0 obj<</Font <</F1 5 0 R>>>>
endobj
5 0 obj<</Type /Font /Subtype /Type1 /BaseFont /Helvetica>>
endobj
6 0 obj
<</Length 36>>
stream
BT /F1 10 Tf 20 20 Td (Page 1)Tj ET
endstream
endobj
xref
0 9
0000000000 65535 f
0000000009 00000 n
0000000056 00000 n
0000000111 00000 n
0000000210 00000 n
0000000248 00000 n
0000000315 00000 n
trailer <</Size 7/Root 1 0 R>>
startxref
398
%%EOF
\end{filecontents*}

\makeatletter
% FIX FROM pdfpages.sty TO FIX ISSUE WITH \pdflastximagepages
\let\AM@Gread@@pdftex\Gread@@pdftex
\renewcommand*{\Gread@@pdftex}[1]{%
  \xdef\AM@currentdocname@fix{#1}%
  \AM@Gread@@pdftex{#1}%
}
\makeatother

\makeatletter
\newcommand{\includepdfifhaspage}[2]{%
  \setbox\@tempboxa=\hbox{\includegraphics[draft]{#1}}%
  \pdfximage{\AM@currentdocname@fix}%
  \ifnum #2>\z@
   \unless\ifnum #2>\pdflastximagepages
     \includegraphics[page=#2]{#1}%
   \fi
  \fi
}
\makeatother

\begin{document}
% insert page one of pdf:
\includepdfifhaspage{\jobname page.pdf}{1}
% insert nothing, since there is no page 2:
\includepdfifhaspage{\jobname page.pdf}{2}
\end{document}

在上面,我没有处理 luatex 上下文。最终,最好的办法是pdfpages让包生成用户控制的\pdfhaspage布尔切换。我没有从其文档中感觉到它已经存在。



编辑以实际使用包pdfpages以便其驱动程序也能处理 xetex、luatex。

\documentclass{article}
\usepackage{graphicx}
\usepackage{pdfpages}
\usepackage{filecontents}
\begin{filecontents*}{\jobname page.pdf}
%PDF-1.1
1 0 obj <</Type /Catalog /Pages 2 0 R>>
endobj
2 0 obj <</Type /Pages /Kids [3 0 R] /Count 1>>
endobj
3 0 obj<</Type /Page /Parent 2 0 R /Resources 4 0 R /MediaBox [0 0 70 50] /Contents 6 0 R>>
endobj
4 0 obj<</Font <</F1 5 0 R>>>>
endobj
5 0 obj<</Type /Font /Subtype /Type1 /BaseFont /Helvetica>>
endobj
6 0 obj
<</Length 36>>
stream
BT /F1 10 Tf 20 20 Td (Page 1)Tj ET
endstream
endobj
xref
0 9
0000000000 65535 f
0000000009 00000 n
0000000056 00000 n
0000000111 00000 n
0000000210 00000 n
0000000248 00000 n
0000000315 00000 n
trailer <</Size 7/Root 1 0 R>>
startxref
398
%%EOF
\end{filecontents*}

\makeatletter
\newcommand{\includepdfifhaspage}[2]{%
  \begingroup
  \edef\AM@currentdocname{#1}%
  \IfFileExists{\AM@currentdocname}{%
  \AM@getpagecount
  \global\let\David@temp\AM@pagecount
  \endgroup
  \ifnum #2>\z@
   \ifnum #2>\David@temp\relax
     % NO PAGE #2 IN FILE #1\par
   \else
     \includegraphics[page=#2]{#1}%
   \fi
  \else
     % NO PAGE #2 IN FILE #1\par
  \fi}%
  {\endgroup}% file does not exist
}
\makeatother

\usepackage{xinttools}
\begin{document}
% insert page one of pdf:
1: \includepdfifhaspage{\jobname page.pdf}{1}XXXX\par

% insert nothing, since there is no page 2:
2: \includepdfifhaspage{\jobname page.pdf}{2}XXXX\par

% Test plus complet


\xintFor #1 in {-1, 0, 1, 2, 3}\do {%
#1: \includepdfifhaspage{\jobname page.pdf}{#1}XXXX\par
}

\end{document}

警告:使用 xetex,包含的 pdf 占用的空间是空白的。此外,在更广泛的测试中,我包含了一个十页的 pdf,xelatex 运行似乎正确结束,但日志以错误结束并且没有生成 pdf。这些示例使用来自 OP 的 pdf 数据filecontents*,也许 xetex 不喜欢那里的某些东西。

无论如何,这只是一个.pdf使用包的一些内部功能的 hack(需要在文件名中使用扩展名)pdfpages。如果该包提供了它,那就最好了。

附注:简短的阅读给我留下的印象是,一些不受保护的行尾空格可能会潜入 pdfpages 代码中。没有调查,我可能在胡说八道。

编辑在上面使用包的代码pdfpages

     \includegraphics[page=#2]{#1}%

应该读作

     \includepdf[pages=#2]{#1}%

现在已pdfpages实际使用。

最后说明在对其他一些文件进行额外测试时,我没有遇到任何问题xetex。因此,这可能是xetexOP 的明确 pdf 文件中存在一些令人不满意的地方。

相关内容