6

I am using beamer for a presentation (of sorts) and want to add a frame every n frames (let's keep things general). As an additional challenge, I want these extra slides to not be counted in the regular numbering (although this is maybe better solved by using a custom counter? See below).

What I've tried

I'm really close to getting this done, but my approach I guess can be improved.

What I've been trying so far is to use everypage to perform a check at every page to see if an extra slide should go after (I do this check using pgf), and if it is, I insert a frame with afterpage.

This works, but it adds one too many additional slides, because in a 10 page presentation it adds an extra one at the end (after page 10, which technically is not wrong, but is not what I want). Also, it means I need to add two packages, just for this (and that's just because I get pgf for free with beamer)!

Also, for this I've been using framenumber, but it's very possible that it would be better to use a different, custom counter (since beamer, you know... uses framenumber).

\documentclass{beamer}

\usepackage{afterpage}
\usepackage{everypage}

% Regular slide
\newcommand{\baseslide}[1]{
  \begin{frame}{\phantom{bg}}
    \begin{center}%
      \LARGE #1
    \end{center}
  \end{frame}
}

% Extra slide
\newcommand{\extraslide}{
  \baseslide{This slide was inserted}
  \addtocounter{framenumber}{-1}
}

% Modulo test using pgfmathparse
% Based on http://tex.stackexchange.com/a/15303/18982
\newcommand\modulo[4]{ 
  \begingroup
  \pgfmathsetmacro{\a}{#1}
  \pgfmathsetmacro{\b}{#2}
  \pgfmathparse{mod(\a,\b)==0} 
  \ifdim\pgfmathresult pt= 1 pt 
    #3
  \else 
    #4
  \fi 
  \endgroup
}

% At every page, check if the next should come before an inserted slide
\AddEverypageHook{
  \modulo{\value{framenumber}+1}{5}{
    % If so, add a slide after that page
    \afterpage{\extraslide}
  }{}
}

\begin{document}

\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
% Slide should go here
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
\baseslide{This is test \insertframenumber}
% But it also goes here, and it shouldn't!

\end{document}

So, my questions:

  1. Is there a better way to do this?
  2. How can I make sure that these pages are only added within the document (not as the first or last page)?

Additional, perhaps not necessarily useful background

I'm using beamer to generate a series of slides with some text that I can show to people one at a time to elicit certain responses. In this particular case, they are sentences to be read during a recording session.

The extra slides I'm inserting are "breaks", so that I can give the participant (performer?) some time to rest, drink some water, or do whatever it is people do when they relax.

  • 1
    Uncertain idea: Maybe you could add a counter to count the number of inserted slides, and add a test in \modulo to check if the considered page number is equal to the last page number (this requires of course two compilations) plus the number of inserted slides. If it is, you should not insert a blank frame, since it means the considered slide is the last one. Hope it gives you some ideas before more elegant solutions come. – anderstood Jul 10 '14 at 6:28
  • 1
    You might find this post helpful. It describes a way of automatically inserting some predefined sections into particular places of a document (for example as sections 6, 9, 11). – Andrew Jul 10 '14 at 7:49
  • That's a good idea, @anderstood. However, I've never written anything that relies on multiple compilations, so I don't really know how to take advantage of that. Any pointers? – jja Jul 10 '14 at 17:20
  • @Andrew's suggestion is not bad either, but I'd have to mess with the definition of an environment instead of a command... and the placement issues would remain, no? – jja Jul 10 '14 at 17:21
  • 1
    Instead of manipulating the framenumber counter by hand, you could use the noframenumbering option for the extra slides: tex.stackexchange.com/q/30461/3323 – diabonas Jul 11 '14 at 7:49
1

A non-answer using pdftk

With the existing solution (the MWE), the last spurious slide (in the cases where it exists) can be easily removed with the help of pdftk (although this sort of post-production makes me feel dirty inside):

pdftk "input.pdf" cat 1-r2 output "output.pdf"

Another possibility would be to go with an entirely pdftk solution.

I put together this bash script which works fine... but it messes with the pagination (of course) in such a way that in a file which originally had 10 pages, in which you added the slide every 5 pages, the page that was originally page 6 will be now page 7 (and labeled as such) in the final pdf. The whole reason for me messing with framenumber in the first place was to keep the page numbering ignore the extra slides, so this is not really a solution in my book. But for completion's sake, here it is:

#/bin/bash

file=$1
every=$2
out=$3

added=$(mktemp PDFXXXX.pdf)
pages=$(
  echo "$(
    pdftk "$file" dump_data |
    grep NumberOfPages   |
    cut -f2 -d" "
  )-1" | bc -l
)
n=$(echo "($pages - 1) / $every" | bc)

pdftk "$file" cat end output "$added"
pdftk "$file" cat 1-r2 output "$out"

for ((i=$n;i>0;i--)); do
  start=$(echo "($i * $every) + 1" | bc)
  end=$(echo "$start - 1" | bc)
  tmp=$(mktemp PDFXXXX.pdf)

  pdftk A="$out" B="$added" cat A1-$end B1 A$start-end output "$tmp"
  mv "$tmp" "$out"
done
rm "$added"

Ran as ./script.sh "input.pdf" 5 "output.pdf", it will extract the last page of input.pdf and create a new output.pdf file in which this page is inserted every 5 pages in the original.

1

The following example adds a slide before a new frame if needed.

  • no additional frame at the beginning is ensured by \ifnum\value{framenumber}=0
  • per construction an additional frame at the end is not possible

Con's

The additional frame has to use the \frame{} syntax and cannot be written as \begin{frame}


\documentclass{beamer}

\usepackage{etoolbox} 
\BeforeBeginEnvironment{frame}{
\ifnum\value{framenumber}=0
\else
    \pgfmathparse{int(mod(\value{framenumber},3))}
    \ifnum\pgfmathresult=0
        \addtocounter{framenumber}{-1}
        \frame{%
            whatever
        } 
    \fi
\fi
}


\usepackage{pgffor}
\usepackage{tikz}

\begin{document}

\foreach \i in {1,...,30} {
    \begin{frame}
        \insertframenumber
    \end{frame}
}

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.