# Why is the height of (pdfpages) \includepdf files not taken into account?

The following MWE (to be run at least twice) points out on its 2nd page (the number of which being invisible, BTW) that the height of (pdfpages) \includepdf files seems to not be taken into account.

Do you see what's going on?

% File to be included
\begin{filecontents}{\jobname-bis.tex}
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage{mwe}
\usepackage[a4paper]{geometry}
\usepackage{babel}
\begin{document}
\lipsum[1-6]
\end{document}
\end{filecontents}
%
% Main file
\documentclass{report}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[a4paper]{geometry}
\usepackage[draft]{pdfpages}
\usepackage{mwe}
\usepackage{babel}
%
\begin{document}
\chapter{Foo foo foo foo foo foo foo foo foo foo foo foo foo}
\begin{figure}[hb]
\includegraphics[scale=0.425]{example-image-a4}
\end{figure}

\chapter{Foo foo foo foo foo foo foo foo foo foo foo foo foo}
\IfFileExists{\jobname-bis.pdf}{%
\begin{figure}[hb]
\includepdf[scale=0.425,frame]{\jobname-bis}
\end{figure}
}{%
}
\end{document}


## Edit

In the real use case, (pdfpages) \includepdf is necessary because multiple pages of the .pdf should be included in the same float.

• Do you mind rephrasing the first paragraph, I'm having a hard time figuring out what you are referring to. Besides that, why are you including a \includepdf inside a float? To the float that thing will have no size as everything is added into the background of the page. – daleif Jun 18 '18 at 14:59
• I'm getting the creeps seeing \includepdf used inside a float. Why don't you use \includegraphics? – Ulrike Fischer Jun 18 '18 at 15:03
• If several pages from the same known PDF is needed why no use several \includegraphics calls plus the page=X option. – daleif Jun 18 '18 at 15:09
• It is not stange, \includepdf is specifically made for including full page PDFs as full pages in the output (statement with modifications of course), it is not meant to be used inside floats. – daleif Jun 18 '18 at 15:10
• Author's attention drawn. – Denis Bitouzé Jun 18 '18 at 19:46

I don't know whether the following satisfies your needs. I don't remember the syntax and behaviour of pdfpages too well (I used it only once) and was too lazy to look it up.

The following defines the new macro \multpages. It takes an optional argument and a mandatory one. The mandatory one is the file from which the pages should be taken. The optional has the following options:

• pages: a list of pages to include, it should be a comma-separated list which can contain ranges
• nup: the arrangement of the images. It can either be a single number, which then sets the number of pages displayed next to each other horizontally, with a line break following those, or something matching the pattern AxB. In this case A images are displayed horizontally next to each other and B vertically. The images have the maximum width of hsize divided by the number of horizontally arranged images (padding respected), and the maximum height of vsize divided by the number of vertically arranged images (padding respected). However there is no box forced around the images, they might line or page break unexpectedly. The product of AxB doesn't have to be greater or equal to the number of included pages.
• hpad: the padding in horizontal direction between the images. No padding is applied on the outermost sides.
• vpad: the padding in vertical direction between the images. No padding is applied on the outermost sides.
• hsize: the horizontally available space. If you don't specify this one the current \textwidth will be used.
• vsize: the vertically available space. If you don't specify this one the current \textheight will be used. Has no effect if nup doesn't contain a vertical part.

Every unknown key is forwarded to the underlying \includegraphics commands.

Changes by edit:

• hpad and vpad are now skips not dim, so they accept glue as argument.
• pages with pattern -B are now ranges beginning by 1, A- are now ranges until the last page of the pdf to be included.

Changes by edit2:

• hcor and vcor keys, allowing to make small adjustments to the calculation of height and width (introduced instead of the fixed value of .1pt, initially set to 0pt)
• less vertical space after the image array, resulting in the same caption placement as under a single \includegraphics
• consistent vertical space with and without \centering
• removed duplicate code and more modularized by defining more functions and reusing functions instead of code blocks

Changes by edit3:

• hboxed key: is a choice between true meaning a horizontal box is put around each row of figures, fixed meaning the row is put into a box with the width fixed to the hsize, and false meaning it is not boxed
• vboxed key: also a choice between true, fixed, and false, with ruffly the same meaning but the vertical box is put around the whole array
• \noindent is forced prior to the array, you can suppress this using the nonoindent key

Changes by edit4:

• pages with undelimited range on the right side now works with LuaTeX and XeTeX, too.

Known issues:

• the vertical height doesn't match the specified vsize, it tends to be bigger for more than one row and to be smaller for one row (as far as I have encountered so far). As a result vboxed=fixed results in the lowest row overlapping the \vbox downwards. As of now, I don't know what causes this.

Known issues (if hboxed=false)

• for some combinations of options in a figure environment the width seems to be a bit too wide, the figures are line broken prematurely
• line breaks can change depending on \centering being present or not

I won't use \centering if I don't use a vertical nup argument and no hsize, as in this case the result always takes the full text width and there is no need for centring the output, but it could lead to unexpected line breaks.

Perhaps it would be better to box up single rows in a \hbox, but I don't know whether I will invest the time to change the output loop to test this.

Code:

\documentclass[]{article}

\usepackage{showframe}% for debugging
\usepackage{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\clist_new:N \g_DenisBitouze_pages_clist
\clist_new:N \l_DenisBitouze_tmp_clist
\dim_new:N \l_DenisBitouze_hsize_dim
\dim_new:N \l_DenisBitouze_vsize_dim
\skip_new:N \l_DenisBitouze_tmp_skip
\int_new:N \l_DenisBitouze_hnup_int
\int_new:N \l_DenisBitouze_vnup_int
\int_new:N \l_DenisBitouze_tmp_int
\tl_new:N \l_DenisBitouze_tmp_tl
\tl_new:N \l_DenisBitouze_graphicx_opt_tl
\cs_new_protected:Nn \DenisBitouze_not_hboxed:n { #1 }
\keys_define:nn { DenisBitouze }%>>>
{
,pages       .tl_set:N   = \l_DenisBitouze_pages_tl
,nup         .tl_set:N   = \l_DenisBitouze_nup_tl
,hsize       .dim_set:N  = \l_DenisBitouze_hsize_available_dim
,hsize       .default:n  = \textwidth
,vsize       .dim_set:N  = \l_DenisBitouze_vsize_available_dim
,vsize       .default:n  = \textheight
,hcorrection .dim_set:N  = \l_DenisBitouze_hcor_dim
,hcorrection .initial:n  = 0pt
,hcor        .meta:n     = { hcorrection = #1 }
,vcorrection .dim_set:N  = \l_DenisBitouze_vcor_dim
,vcorrection .initial:n  = 0pt
,vcor        .meta:n     = { vcorrection = #1 }
,vboxed      .choice:
,vboxed / true  .code:n  =
\cs_set_protected:Nn \DenisBitouze_vbox:n { \vbox:n { ##1 } }
,vboxed / false .code:n  =
\cs_set_protected:Nn \DenisBitouze_vbox:n { ##1 }
,vboxed / fixed .code:n  =
\cs_set_protected:Nn \DenisBitouze_vbox:n
{ \vbox_to_ht:nn { \l_DenisBitouze_vsize_available_dim } { ##1 } }
,vboxed      .default:n  = true
,vboxed      .initial:n  = true
,hboxed      .choice:
,hboxed / true  .code:n  =
\cs_set_eq:NN \DenisBitouze_hbox:n \hbox:n
,hboxed / false .code:n  =
\cs_set_eq:NN \DenisBitouze_hbox:n \DenisBitouze_not_hboxed:n
,hboxed / fixed .code:n  =
\cs_set_protected:Nn \DenisBitouze_hbox:n
{ \hbox_to_wd:nn { \l_DenisBitouze_hsize_available_dim } { ##1 } }
,hboxed      .default:n  = true
,hboxed      .initial:n  = true
,nonoindent  .bool_set:N = \l_DenisBitouze_no_noindent_bool
,nonoindent  .default:n  = true
,unknown     .code:n     =
{
\tl_put_right:NV \l_DenisBitouze_graphicx_opt_tl \l_keys_key_tl
\tl_if_empty:nF { #1 }
{ \tl_put_right:Nn \l_DenisBitouze_graphicx_opt_tl { =#1 } }
\tl_put_right:Nn \l_DenisBitouze_graphicx_opt_tl { , }
}
}%<<<
\cs_new_protected:Nn \DenisBitouze_store_pages_count:n%>>>
{
\group_end:
\cs_set:Nn \DenisBitouze_pages_count: { #1 }
}%<<<
\cs_generate_variant:Nn \DenisBitouze_store_pages_count:n { x }
\cs_new_protected:Nn \DenisBitouze_define_count_pages:nn%>>>
{
\cs_set_protected:Nn \DenisBitouze_count_pages:n
{
\group_begin:
#1
\DenisBitouze_store_pages_count:x { #2 }
}
}%<<<
\sys_if_engine_pdftex:T%>>>
{
\DenisBitouze_define_count_pages:nn
{ \pdfximage { #1 } }
{ \the\pdflastximagepages }
}%<<<
\sys_if_engine_luatex:T%>>>
{
\DenisBitouze_define_count_pages:nn
{ \saveimageresource { #1 } }
{ \the\lastsavedimageresourcepages }
}%<<<
\sys_if_engine_xetex:T%>>>
{
\DenisBitouze_define_count_pages:nn
{}
{ \the\XeTeXpdfpagecount #1 \relax }
}%<<<
\cs_new:Nn \DenisBitouze_recall_parse:nnn%>>>
{
\DenisBitouze_parse_range:w #1 - #2 \q_stop { #3 }
}%<<<
\cs_generate_variant:Nn \DenisBitouze_recall_parse:nnn { nxn }
\cs_new_protected:Npn \DenisBitouze_parse_range:w #1-#2\q_stop#3%>>>
{
\tl_if_blank:nTF { #1 }
{
\DenisBitouze_parse_range:w 1-#2\q_stop { #3 }
}
{
\tl_if_blank:nTF { #2 }
{
\tl_if_in:nnTF { #3 } { .pdf }
{ \DenisBitouze_count_pages:n { #3 } }
{ \DenisBitouze_count_pages:n { #3.pdf } }
\DenisBitouze_recall_parse:nxn
{ #1 } { \DenisBitouze_pages_count: } { #3 }
}
{
\int_step_inline:nnn { #1 } { #2 }
{
\clist_gput_right:Nn \g_DenisBitouze_pages_clist { ##1 }
}
}
}
}%<<<
\cs_new_protected:Nn \DenisBitouze_parse_pages:n%>>>
{
\clist_gclear:N \g_DenisBitouze_pages_clist
\clist_set:NV \l_DenisBitouze_tmp_clist \l_DenisBitouze_pages_tl
\clist_map_inline:Nn \l_DenisBitouze_tmp_clist
{
\tl_if_in:nnTF { ##1 } { - }
{
\DenisBitouze_parse_range:w ##1 \q_stop { #1 }
}
{
\clist_gput_right:Nn \g_DenisBitouze_pages_clist { ##1 }
}
}
}%<<<
\cs_new_protected:Npn \DenisBitouze_parse_nup_x:w #1x#2\q_stop%>>>
{
\int_set:Nn \l_DenisBitouze_hnup_int { #1 }
\int_set:Nn \l_DenisBitouze_vnup_int { #2 }
}%<<<
\cs_new_protected:Nn \DenisBitouze_parse_nup:n%>>>
{
\tl_if_empty:nTF { #1 }
{
\int_set:Nn \l_DenisBitouze_hnup_int { \c_one }
\int_set:Nn \l_DenisBitouze_vnup_int { \c_zero }
}
{
\tl_if_in:nnTF { #1 } { x }
{
\DenisBitouze_parse_nup_x:w #1 \q_stop
}
{
\int_set:Nn \l_DenisBitouze_hnup_int { #1 }
\int_set:Nn \l_DenisBitouze_vnup_int { \c_zero }
}
}
}%<<<
\cs_generate_variant:Nn \DenisBitouze_parse_nup:n { V }
\cs_new_protected:Nn \DenisBitouze_output_single:nnn%>>>
{
\includegraphics [ #1, #2 ] { #3 }
}%<<<
\cs_generate_variant:Nn \DenisBitouze_output_single:nnn { nVn }
\cs_new_protected:Nn \DenisBitouze_output_single_no_vnup:nn%>>>
{
\DenisBitouze_output_single:nVn
{ width=\l_DenisBitouze_hsize_dim, page=#1 }
\l_DenisBitouze_graphicx_opt_tl
{ #2 }
}%<<<
\cs_new_protected:Nn \DenisBitouze_output_single_with_vnup:nn%>>>
{
\DenisBitouze_output_single:nVn
{
width=\l_DenisBitouze_hsize_dim,
height=\l_DenisBitouze_vsize_dim,
keepaspectratio=true,
page = #1
}
\l_DenisBitouze_graphicx_opt_tl
{ #2 }
}%<<<
\cs_generate_variant:Nn \DenisBitouze_output_single_no_vnup:nn { V }
\cs_generate_variant:Nn \DenisBitouze_output_single_with_vnup:nn { V }
\cs_new_protected:Nn \DenisBitouze_calc_hsize:%>>>
{
\dim_set:Nn \l_DenisBitouze_hsize_dim
{
(
\l_DenisBitouze_hsize_available_dim
)
/ \l_DenisBitouze_hnup_int
% rounding could lead to too much horizontal space taken without
% this in a figure environment
- \l_DenisBitouze_hcor_dim
}
}%<<<
\cs_new_protected:Nn \DenisBitouze_calc_vsize:%>>>
{
\dim_set:Nn \l_DenisBitouze_vsize_dim
{
(
\l_DenisBitouze_vsize_available_dim
)
/ \l_DenisBitouze_vnup_int
- \l_DenisBitouze_vcor_dim
}
}%<<<
\cs_new_protected:Nn \DenisBitouze_output_line:Nn%>>>
{
\int_step_inline:nn { \l_DenisBitouze_hnup_int }
{
\clist_if_empty:NF \g_DenisBitouze_pages_clist
{
\clist_gpop:NN \g_DenisBitouze_pages_clist \l_DenisBitouze_tmp_tl
#1 \l_DenisBitouze_tmp_tl { #2 }
}
}
}%<<<
\cs_new_protected:Nn \DenisBitouze_output_loop:Nn%>>>
{
\bool_do_while:nn { !\clist_if_empty_p:N \g_DenisBitouze_pages_clist }
{
\bool_if:NF \l_DenisBitouze_no_noindent_bool { \noindent }
\mbox{}
\DenisBitouze_hbox:n { \DenisBitouze_output_line:Nn #1 { #2 } }
\mbox{}
}
}%<<<
\cs_new_protected:Nn \DenisBitouze_after_loop:%>>>
{
}%<<<
\cs_new_protected:Nn \DenisBitouze_output_no_vnup:n%>>>
{
\DenisBitouze_output_loop:Nn
\DenisBitouze_output_single_no_vnup:Vn { #1 }
}%<<<
\cs_new_protected:Nn \DenisBitouze_output_with_vnup:n%>>>
{
\DenisBitouze_calc_vsize:
\DenisBitouze_output_loop:Nn
\DenisBitouze_output_single_with_vnup:Vn { #1 }
}%<<<
\NewDocumentCommand \multpages { O{} m }%>>>
{
\group_begin:
\keys_set:nn { DenisBitouze } { hsize, vsize, #1 }
\DenisBitouze_parse_pages:n { #2 }
\clist_if_empty:NT \g_DenisBitouze_pages_clist
{
\clist_gset:Nn \g_DenisBitouze_pages_clist { \c_one }
}
\DenisBitouze_parse_nup:V \l_DenisBitouze_nup_tl
\DenisBitouze_calc_hsize:
\DenisBitouze_vbox:n
{
\int_compare:nNnTF { \l_DenisBitouze_vnup_int } = { \c_zero }
{ \DenisBitouze_output_no_vnup:n { #2 } }
{ \DenisBitouze_output_with_vnup:n  { #2 } }
\DenisBitouze_after_loop:
}
\group_end:
}%<<<
\ExplSyntaxOff

\begin{document}
\begin{figure}[t]% >>>
\centering
\multpages[pages=1-5,nup=3]{example-image-duck.pdf}
\caption
{%
A happy duck family%
\label{fig:ducks}%
}%
\end{figure}% <<<
\end{document}


• You can get the total number of pages with \pdflastximagepages see tex.stackexchange.com/a/8324/2388 – Ulrike Fischer Jun 18 '18 at 17:59
• @UlrikeFischer thank you very much! I had that one anywhere back in my head, but didn't need it for a long time now:) Is it even necessary to get that one. Currently I'm defaulting to page 1, would it be better to default to all pages? – Skillmon Jun 18 '18 at 18:01
• includepdf defaults to one too, pages=- is the syntax for all pages. – Ulrike Fischer Jun 18 '18 at 18:03
• Wow, brilliant! Could be a nice package :) – Denis Bitouzé Jun 18 '18 at 19:41
• @DenisBitouzé I've added the possibility to box the stuff up (horizontally and vertically). It could use some testing, debugging, restructuring, but it should work. I'm not sure whether it's completely stable. I won't consider it package level code, but perhaps use it myself... – Skillmon Jun 19 '18 at 16:08