24

There is a way to make TOC using \tableofcontents, but there are only sections and subsections.

How can I get list of all frames without using sectioning?

Marco Daniel
  • 95,681
kryksyh
  • 343

4 Answers4

22

Here's a simple approach using the \@starttoc command through the newly defined \listofframes command; the new list will have extension .lbf. \addtobeamertemplate was used so that the frametitle command writes the desired information (frame number and title) to the .lbf file. The list is created issuing \listofframes:

\documentclass{beamer}

\makeatletter
\newcommand\listofframes{\@starttoc{lbf}}
\makeatother

\addtobeamertemplate{frametitle}{}{%
  \addcontentsline{lbf}{section}{\protect\makebox[2em][l]{%
    \protect\usebeamercolor[fg]{structure}\insertframenumber\hfill}%
  \insertframetitle\par}%
}

\begin{document}

\begin{frame}
\frametitle{List of Frames}
\listofframes
\end{frame}

\begin{frame}
\frametitle{Test Frame One}
test
\end{frame}

\begin{frame}
\frametitle{Test Frame Two}
test
\end{frame}

\end{document}

Here's the resulting List of Frames:

enter image description here

To facilitate control over which frames to include in the new list, you can use a boolean switch; in the following example I used \ifframeinlbf initially set to true; if you want to suppress some titled frame(s) from the list of frames, use \frameinlbffalse right before those frame(s) and then use \frameinlbftrue right after the frame(s) to activate inclusion in the list:

\documentclass{beamer}

\newif\ifframeinlbf
\frameinlbftrue
\makeatletter
\newcommand\listofframes{\@starttoc{lbf}}
\makeatother

\addtobeamertemplate{frametitle}{}{%
  \ifframeinlbf
  \addcontentsline{lbf}{section}{\protect\makebox[2em][l]{%
    \protect\usebeamercolor[fg]{structure}\insertframenumber\hfill}%
  \insertframetitle\par}%
  \else\fi
}

\begin{document}

\frameinlbffalse
\begin{frame}
\frametitle{List of Frames}
\listofframes
\end{frame}

\frameinlbftrue
\begin{frame}
\frametitle{Test Frame One}
test
\end{frame}

\begin{frame}
\frametitle{Test Frame Two}
test
\end{frame}

\end{document}
Gonzalo Medina
  • 505,128
  • Oh, that faded tick on the left is hard to find first time.

    Done.

    Thank you

    – kryksyh May 19 '12 at 20:59
  • Now I have homework - remove from TOC contents slide itself :) – kryksyh May 19 '12 at 21:09
  • @kryksyh please see my updated answer. – Gonzalo Medina May 19 '12 at 21:19
  • May be I am doing something wrong, but \frameinlbftrue doesn't turn frameinlbf to true when placed inside {document} – kryksyh May 19 '12 at 21:41
  • @kryksyh: of course it does; my example code illustrates this, so perhaps there's something else going on in your code... Two possible causes: 1) You need to process your document at least two times, or 2) Perhaps you are using \frameinlbftrue inside a frame environment? (it must go outside the frame environment) If this is not the problem, I will need to see some code showing the undesired behaviour. – Gonzalo Medina May 19 '12 at 21:46
  • The problem was in ignorenonframetext option in \documentclass. All non-frame text including \frameinlbftrue was skipping. – kryksyh May 19 '12 at 22:12
  • Is it possible to have this solution work if I have a latex tag such as \emph{} inside a frame title? It says something about an invalid \end{frame} tag at the end of the first frame which has such a tag in the \frametitle{}. Thanks. – Sandro Gržičić Jul 25 '13 at 13:51
  • 1
    @SandroGržičić please feel free to open a follow up question, and add there a minimal example document (like the one in my example code) allowing us to reproduce the mentioned problem. – Gonzalo Medina Jul 25 '13 at 14:06
  • I did, here's the question: http://tex.stackexchange.com/questions/125540/how-to-produce-a-list-of-frames-with-beamer-if-frame-titles-have-latex-tags-in-t – Sandro Gržičić Jul 26 '13 at 11:45
  • 1
    Great stuff. However, this solution seems to have troubles with the allowframebreaks option. I get a "TeX capacity exceeded" error, supposedly because of the internal handling of automatic frame breaks in the beamer code. Thx for a comment on your original solution. – mfg Mar 14 '19 at 16:25
  • 1
    This solution appears to fail when the allowframebreaks option is used. – Dan Fox Jan 07 '20 at 12:21
  • 2
    @Mario @Dan Fox I managed to make this to work with allowframebreaks by making usebeamertemplate robust. Add this to the preamble:

    usepackage{makerobust}
    \MakeRobustCommand\usebeamertemplate

    – jorpppp Mar 15 '21 at 22:15
  • 1
    Thanks, @jorpppp, I will try that. – mfg Mar 16 '21 at 09:21
  • @GonzaloMedina Your answer recently stopped working. This answer provides the fix. – Robert Seifert Jan 24 '22 at 14:40
  • I implemented your listofframes, but the compiler does not seem to like the space factor. I get, in the .log file [. {/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] ! You can't use `\spacefactor' in internal vertical mode. @->\spacefactor @m {} l.344 \end{frame}

    Sorry, but I'm not programmed to handle this case; I'll just pretend that you didn't ask for it. If you're in the wrong mode, you might be able to return to the right one by typing I}' orI$' or `I\par'.

    – Duchamp Gérard H. E. Dec 15 '22 at 06:02
5

In addition to Gonzalo Medina's answer, if you want frame titles to link to page numbers, use this code just before the \insertframetitle:

\protect\hyperlink{page.\insertframenumber}

So the full code is:

\addtobeamertemplate{frametitle}{}{%
  \ifframeinlbf
  \addcontentsline{lbf}{section}{\protect\makebox[2em][l]{%
    \protect\usebeamercolor[fg]{structure}\insertframenumber\hfill}%
  \protect\hyperlink{page.\insertframenumber}\insertframetitle\par}%
  \else\fi
}

The above requires the hyperref package, so make sure you include it.

4

The answer of Sandro shows a very useful addition to Gonzalo Medinas answer in case one actually wants to use the list of frames as a link collection to easy access a certain frame.

However, the solution of Sandro fails if one resets the frame counter during the presentation. This is a more robust approach which also consideres overlays to avoid multiple links of the same frame:

\addtobeamertemplate{frametitle}{}{%
    \only<1>{%
      \hypertarget{\insertframetitle}{}%
      \addcontentsline{lbf}{section}{\protect\makebox[2em][l]{%
      \protect\usebeamercolor[fg]{structure}\insertframenumber\hfill}%
      \protect\hyperlink{\insertframetitle}{\insertframetitle}\par}% 
    }%
}
  • Works great unless I put ${\mathbb {R}}$ inside a framework title, in which case there is the 'undefined controlled sequence' error - any idea how to fix it? – Dmitri Zaitsev Sep 24 '20 at 14:56
  • @DmitriZaitsev have you tried the the optional argument \frametitle[linktitle]{${\mathbb {R}}$}? – Robert Seifert Sep 24 '20 at 17:36
  • No luck, the same annoying error as soon as \mathbb is present, linking to the entry \contentsline {section}{\makebox [2em][l]{\usebeamercolor [fg]{structure}5\hfill }\hyperlink {{${\mathbb {R}}$}}{{${\mathbb {R}}$}}\par } inside the *.lbf file. – Dmitri Zaitsev Sep 25 '20 at 12:50
3

i want to add some comments to the solution of Sandro:

The code was not working for me until i changed the line

 \addcontentsline{lbf}{section}{\protect\makebox[2em][l]{%

to

\addcontentsline{lbf\thesection}{section}{\protect\makebox[2em][l]{%

Further, the idea with the link is good, but if you have uncover-effects, e.g. with pause, uncover, ..., the framenumber does not correspond with the page number. Thus i changed the line

\protect\hyperlink{page.\insertframenumber}\insertframetitle\par}%

to

\protect\hyperlink{page.\insertpagenumber}\insertframetitle\par}%

Hope i was able to contriubte something!

erwin
  • 31