3

Given some latex code like

    \section{the first section}
    some text

    \section{the second section}
    some text

    \section{the third section}
    some text

    \section{the fourth section}
    some text

I want to create a TOC as a three-column table, like so:

    -------------------------------------------------
    | 1. the first  | 2. the second | 3. the third  |
    |    section    |    section    |    section    |
    -------------------------------------------------
    | 4. the fourth |               |               |
    |    section    |               |               |
    -------------------------------------------------

It is okay if I use a completely custom command instead of section, as long as the numbering in the document body matches the numbering in the table.

How can I approach this problem?

10
  • Perhaps the etoc package provides some means for this
    – user31729
    Feb 13, 2015 at 10:02
  • 1
    @SoundsOfSilence yes it does, as described in an "advanced section for advanced users" :-). But anyhow the accepted answer isn't a table...
    – user4686
    Mar 6, 2015 at 16:01
  • @jfbu: And my answer is neither using your package nor is it accepted ... that's life ;-) I think, you should add an answer as well!
    – user31729
    Mar 6, 2015 at 16:04
  • @SoundsOfSilence I did, but after all maybe it's not that different from your own which uses as well longtable.
    – user4686
    Mar 6, 2015 at 19:33
  • 1
    @jfbu: I won't tell egreg about your vertical lines :-P
    – user31729
    Mar 6, 2015 at 19:53

3 Answers 3

4

enter image description here

\documentclass{article}
\makeatletter
\def\l@section#1#2{%
\noindent\begin{minipage}[t]{\dimexpr(.333\linewidth)-2em\relax}%
\def\numberline##1{##1: }\parfillskip0pt\relax
#1 \mbox{}\dotfill #2\end{minipage}\linebreak[0]\hspace{2em plus 2em}}
\makeatletter

\begin{document}

\tableofcontents

    \section{the first section}
    some text

    \section{the second section}
    some text

    \section{the third section}
    some text

    \section{the fourth section}
    some text

\end{document}
1
  • I wrapped the minipage in an \fbox{...} and removed the hspace and it works great!
    – Cephalopod
    Feb 13, 2015 at 12:16
7

Here is (another way) to do it in a longtable, here using package etoc.

\documentclass[a4paper]{article}
\usepackage[hscale=0.8]{geometry}

\usepackage{etoc}
\usepackage{array}
\usepackage{longtable}

% It is not at all obvious to display a TOC in a (long)-table,
% using etoc, but it is possible. See in its doc
% "Typesetting the TOC as a table".

% Let's illustrate here in a case which has only sections.
% We will use the *standard* way of displaying the sections in the TOC, except
% it will all take places in p cells of a longtable.


\usepackage[linktoc=all]{hyperref}% let's increase the challenge !

\newcounter{column}
\newtoks\toctabletok

\newcommand*\appendtotok[2]
{% #1=toks variable, #2=macro, 
 % #2 will be expanded once.
   #1\expandafter\expandafter\expandafter{\expandafter\the\expandafter #1#2}%
}

\makeatletter % for \l@section

\newcommand*{\PrepareSectionCell}{%
  \toks0 \expandafter{\etocthelinkednumber}% don't worry, etoc always in a group
  \toks2 \expandafter{\etocthelinkedname}%
  \toks4 \expandafter{\etocthelinkedpage}%
% or we could use \unexpanded  from e-TeX, rather than the \toks registers
  \edef\toctablecell {\relax % mandatory to stop TeX's future too 
                             % early expansion of cell
    \noexpand\par % \l@section MUST start in vertical mode
    \noexpand\vspace*{-\baselineskip}% compensate for the \par (I think)
    \noexpand\l@section % call the hotline if you have unnumbered sections
          {\noexpand\numberline{\the\toks0 }\noexpand\strut\the\toks2 }{\the\toks4 }%
    }%
}

%
\newcommand*{\TableTableOfContents}{\begingroup
%
  \etocsetstyle{section}{}{}
  {\PrepareSectionCell
   \appendtotok\toctabletok\toctablecell
   \stepcounter{column}%
   \ifnum\value{column}=3
    \toctabletok \expandafter{\the\toctabletok \\\hline}%
    \setcounter{column}{0}%
   \else
    \toctabletok \expandafter{\the\toctabletok &}%
   \fi}
  {}
%
  \etocsettocstyle
  {\toctabletok{%\hypersetup{hidelinks}%
                \begin{longtable}{*{3}{|p{.3\linewidth}}|}
                \hline
                \multicolumn{3}{|c|}{\Large\bfseries\strut TABLE OF CONTENTS}%
                \\
                \hline\hline}}
  {\ifcase\value{column}%
          \or\toctabletok\expandafter{\the\toctabletok &\\\hline}%
          \or\toctabletok\expandafter{\the\toctabletok  \\\hline}%
   \fi 
   \global\toctabletok\expandafter{\the\toctabletok \end{longtable}}%
   }
%
  \etocsetnexttocdepth {section}%
  \tableofcontents
  \endgroup
  \the\toctabletok % the only thing which survived the closing of the group
}
\makeatother


\begin{document}

\TableTableOfContents

    \section{the first section}
    some text

    \section{the second section}
    some text

    \section{the third section}
    some text

    \section{the fourth section}
    some text


\newcount\loopcount
\loopcount 50

\loop
  \section {and another section}
  hello
\clearpage
\advance\loopcount-1
\ifnum\loopcount>0
\repeat 

  \section {and the final section which happens to have quite a long name. By
    the way you can click on it, its number or the page number}

\end{document}

etoc table top of first page

and then continued on page 2:

etoc table continued on page 2

I add some extra info: there is a difference between a p column in a longtable and a p column in a standard tabular. The latter starts in vertical mode. But the former's p cell contents typesetting does not start in vertical mode. As a result, the \l@section which could have been used directly in a tabular at the start of a cell (after \relax) needed here in the longtable an extra \par. I then needed to compensate the resulting \baselineskip. There is a remnant vertical space which is due to the \addvspace{1em plus 1pt} done by \l@section.

As for the vertical space below the section names it is due to the fact that when a p column finishes, an (invisible) \vrule is added by macro \@finalstrut. Here this is the same in a tabular as in a longtable. In both cases this provokes a switch to horizontal mode hence again some vertical space.

In brief, using \l@section inside longtable was fun, but I should presumably rather have used the \etocthename etc... things directly and not wrap them up in \l@section (see the documentation of etoc for an example in section "Typesetting the TOC as a table").

4
  • I opened the pdf in Adobe Reader, to get the red rectangles to explicitely illustrate the presence of the links; as is known, these rectangles don't show in some other viewers nor in print.
    – user4686
    Mar 6, 2015 at 18:40
  • I don't know why I absolutely wanted to use \l@section... after all it was not designed to be used in such a context! but well, it does work.
    – user4686
    Mar 6, 2015 at 19:20
  • Most impressive my favourite character from Star Wars would say (+1)
    – user31729
    Mar 6, 2015 at 19:36
  • @SoundsOfSilence the Epsiode III is of Shakespearean stature! not like my table where I am not so sure I understand the vertical spacings...
    – user4686
    Mar 6, 2015 at 19:56
4

Another approach with the current disadvantage (amongst others) that it's necessary to delete the .tabtoc file later by hand.

\documentclass{article}

\usepackage{xparse}
\usepackage{etoolbox}
\usepackage{xpatch}
\usepackage{letltxmacro}
\usepackage{longtable}%
\usepackage{hyperref}


\NewDocumentCommand{\TableOfContents}{}{%
\section*{\contentsname}%
\begin{longtable}{*{3}{p{4cm}}}
& & \tabularnewline[1ex]
\InputIfFileExists{\jobname.tabtoc}{\typeout{File exists}}{\typeout{File does not exist}} \tabularnewline[2ex]
\end{longtable}%
}%


\newwrite\tabtoc%


\makeatletter



\newcounter{@@columncounter}
\setcounter{@@columncounter}{0}

\xapptocmd{\@sect}{%
  \begingroup
  \renewcommand{\thesection}{\arabic{section}. }
  \protect\addtocounter{@@columncounter}{1}%
  \immediate\write\tabtoc{%
    \thesection #7 % \tabularnewline
  }%
  \ifnumgreater{\value{@@columncounter}}{2}{%
    \immediate\write\tabtoc{%
      \string\tabularnewline[1ex]^^J
    }%
    \setcounter{@@columncounter}{0}
  }{%
    \immediate\write\tabtoc{&}
  }%
  \endgroup
}{%
\typeout{success}}{\typeout{fail}}

\makeatother
\AtBeginDocument{%
  \IfFileExists{\jobname.tabtoc}{%
    % Do nothing
  }{%
    % Open it for writing 
    \immediate\openout\tabtoc=\jobname.tabtoc%
  }%
}%

\AtEndDocument{%
\immediate\closeout\tabtoc
}


\begin{document}

\TableOfContents

\section{First}

\section{Second}
\section{Third}

\section{Fourth}

\section{Fifth}
\section{Sixth}
\section{Seventh with a very long wrapping title}
\section{Eight}


\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .