5

I want to indicate the progress of a beamer presentation using external pictures.

Let's say we are at slide 24 out of 200 slides then I want to display a picture called 12.png (24/200 = 12 %) on the current slide.

I am already able to manage to calculate the percentage of the progress but I can't use \pgfmathresult (\pgfmathprintnumber[precision=0]{\pgfmathresult}, which in my MWE gives the progress percentage of the current slide) as part of a file name (error ! Missing \endcsname inserted.).

I use the calc library of tikz/pgf to do the calculations.

In the MWE I input an external tex file in order to emulate inserting a picture.

\documentclass{beamer}
\usepackage{filecontents}

\begin{filecontents}{33.tex}
File with name \texttt{33.tex}.
\end{filecontents}

\begin{filecontents}{67.tex}
File with name \texttt{67.tex}.
\end{filecontents}

\begin{filecontents}{100.tex}
File with name \texttt{100.tex}.
\end{filecontents}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] 
    \pgfmathparse{min((100*\insertframenumber/\inserttotalframenumber),100)} 
    \pgfmathprintnumber[precision=0]{\pgfmathresult}\,\%
\end{description}
%
\input{33.tex}
\end{frame}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] 
    \pgfmathparse{min((100*\insertframenumber/\inserttotalframenumber),100)} 
    \pgfmathprintnumber[precision=0]{\pgfmathresult}\,\%
\end{description}
%
\input{67.tex}
\end{frame}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] 
    \pgfmathparse{min((100*\insertframenumber/\inserttotalframenumber),100)} 
    \pgfmathprintnumber[precision=0]{\pgfmathresult}\,\%
\end{description}
%
\input{100.tex}
\end{frame}

\end{document}

enter image description here

enter image description here

enter image description here

When you first compile the document then \inserttotalframenumber is 1 (One). So if you are on slide 3 (Three) then the current progress percentage is 300 (slide 3 out of 1). Therefore I use the min function to restrict the result of the calculation to be 100 at maximum.


Related

  • 1
    Are you sticking to pgfmath... calculations? – user31729 Jan 4 '17 at 19:59
  • @ChristianHupfer I do not. I just thought that pgf/tikz will be modern (state of the art) and easy to use. – Dr. Manuel Kuehner Jan 4 '17 at 20:08
  • 1
    \pgfmathresult does not survive the group, that's the point – user31729 Jan 4 '17 at 20:09
  • @ChristianHupfer Ok. As I said - I do not need to use pgfmath. Thanks for the help by the way. – Dr. Manuel Kuehner Jan 4 '17 at 20:10
5

This exploits expl3 features of easy calculation and storing values into a property list, the \prop_item:Nn command is expandable, whereas the expansion content of \pgfmathresult does not survive the description environment group, it will show 0.0 most likely.

The wrapper command \retrievepercentage is expandable as well then and can be used as argument to \input in order to generate the corresponding filename.

\documentclass{beamer}
\usepackage{filecontents}

\begin{filecontents}{33.tex}
File with name \texttt{33.tex}.
\end{filecontents}

\begin{filecontents}{67.tex}
File with name \texttt{67.tex}.
\end{filecontents}

\begin{filecontents}{100.tex}
File with name \texttt{100.tex}.
\end{filecontents}

\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{calc}

\ExplSyntaxOn
\int_new:N \l_beamer_percentage_int
\prop_new:N \g_beamer_percentage_prop
\NewDocumentCommand{\getpercentage}{}{%
  \int_set:Nn  \l_beamer_percentage_int {\fp_to_int:n {\fp_eval:n { min((100*\insertframenumber/\inserttotalframenumber),100)}}}
  \prop_gput:NnV \g_beamer_percentage_prop {percentage} { \l_beamer_percentage_int }
}

\newcommand{\retrievepercentage}{%
  \prop_item:Nn \g_beamer_percentage_prop {percentage}
}
\ExplSyntaxOff


\begin{document}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent]
  \getpercentage%
  \retrievepercentage
\end{description}
%

\input{\retrievepercentage.tex}
\end{frame}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] 
  \getpercentage%
  \retrievepercentage
\end{description}
%
\input{\retrievepercentage.tex}
\end{frame}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] 
  \getpercentage%
  \retrievepercentage
\end{description}
\input{\retrievepercentage.tex}
\end{frame}

\end{document}

Details of the solution.

As explained above, \pgfmathresult will not keep the result being stored in the description environment since this is TeX group.

A possible bypass would use an \xdef - based approach, say \xdef\foo{\pgfmathresult} which is a globally expanded definition, i.e. \foo will contain the value of \pgfmathresult at definition time.

I tried another strategy to calculate the result of the percentage with expl3 (the upcoming (;-)) LaTeX 3 format)

Let's look into the code...

\int_new:N \l_beamer_percentage_int 

defines a new integer 'variable' (internally it is a TeX count register)

\prop_new:N \g_beamer_percentage_prop

defines a property list, which is something like expl3's version of a hash-table or array, i.e. key names can be defined and a value assigned to it.

  \fp_to_int:n {\fp_eval:n {min((100*\insertframenumber/\inserttotalframenumber),100)}}

evaluates (\fp_eval:n) the floating point (fp) expression with min(...) which looks equal basically to the pgfmath approach. After evaluation it is converted ('truncated') to an integer value, which is stored to the \l_beamer_percentage_int with \int_set:Nn.

The set-operation is not expandable, it can not be used in expansion chains, e.g. like in the generation of the filenames as requested here, but storing the value to property list is a possible way with

  \prop_gput:NnV \g_beamer_percentage_prop {percentage} { \l_beamer_percentage_int }

this means: Globally put (gput) the Value (V) of \l_beamer_percentage_int into the list named \g_beamer_percentage_prop and assign it to key percentage.

Finally, calling the command \prop_item:Nn \g_beamer_percentage_prop {percentage} is the slower but expandable version of getting the stored value.

I refer to the description of texdoc interface3 for the details about the name conventions used in expl3.

  • Thanks. Can you give me a resource hint where I can read about stuff like \prop and so on? It would be perfect if the solution also would work with \beamer@startpageofappendix (see tex.stackexchange.com/questions/141157). – Dr. Manuel Kuehner Jan 4 '17 at 21:07
  • 1
    @Dr.ManuelKuehner texdoc.net/pkg/interface3 – Joseph Wright Jan 4 '17 at 21:09
  • 1
    Better to use xparse to make a protected outer layer than using \newcommand :) – Joseph Wright Jan 4 '17 at 21:09
  • It works perfectly. Can you elaborate the code a little bit? It all looks very unfamiliar to me :). – Dr. Manuel Kuehner Jan 5 '17 at 15:20
  • 1
    @Dr.ManuelKuehner: No, not this way. You would overwrite the property value each time you're using retrievepercentage because \getpercentage recalculates the value again -- the values of the input for computing the percentage are lost outside however – user31729 Jan 7 '17 at 15:21
2

You can define an expandable command:

\begin{filecontents}{33.tex}
File with name \texttt{33.tex}.
\end{filecontents}

\begin{filecontents}{67.tex}
File with name \texttt{67.tex}.
\end{filecontents}

\begin{filecontents}{100.tex}
File with name \texttt{100.tex}.
\end{filecontents}

\documentclass{beamer}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\percentageofpresentation}{}
 {
  \fp_to_int:n { 100*\insertframenumber/\inserttotalframenumber }
 }
\ExplSyntaxOff

\begin{document}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] \percentageofpresentation
\end{description}
%
\InputIfFileExists{\percentageofpresentation.tex}{}{NOT YET COMPUTED}
\end{frame}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] \percentageofpresentation
\end{description}
%
\InputIfFileExists{\percentageofpresentation.tex}{}{NOT YET COMPUTED}
\end{frame}

%% Start of Frame
\begin{frame}
\frametitle{Frame Title}
%
\begin{description}
\item[Current Frame Number] \insertframenumber
\item[Total Frame Number] \inserttotalframenumber
\item[Progress in Percent] \percentageofpresentation
\end{description}
%
\InputIfFileExists{\percentageofpresentation.tex}{}{NOT YET COMPUTED}
\end{frame}

\end{document}

With \InputIfFileExists we cope with the problem of the first LaTeX run. In your project you can do

\IfFileExists{\percentageofpresentation.png}
  {\includegraphics{\percentageofpresentation.png}}
  {NOT YET COMPUTED}

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.