2

I'm trying to fill a table by iterating through predefined data and experience errors with both & (next column) and \\ (next row) using code like follows:

\begin{document}
%   \foreach \s in \schedule {
%       \textbf{\GetListMember{\s}{1}:} \GetListMember{\s}{2} \\
%   }
    \begin{tabular}{ll}
        \foreach \s in \schedule {
            \textbf{\GetListMember{\s}{1}} & \GetListMember{\s}{2} \\
        }
    \end{tabular}
\end{document}

The complete example:

\documentclass[12pt, a4paper]{article}%
\usepackage[T1]{fontenc}%
\usepackage[utf8]{inputenc}%
\usepackage{pgffor}%
\usepackage{xstring}%
%
%\tracingall%
%
\setlength{\parindent}{0in}%
%
\newcommand*{\GetListMember}[2]{%
    \edef\dotheloop{%
        \noexpand\foreach \noexpand\a [count=\noexpand\i] in {#1} {%
            \noexpand\IfEq{\noexpand\i}{#2}{\noexpand\a\noexpand\breakforeach}{}%
    }}%
    \dotheloop%
}%
%
\edef\schedule {%
    %{{Title},{Description}},%
    {{Ipsum},{Pellentesque mauris mauris, feugiat ut.}},%
    {{Lorem},{Integer viverra blandit magna, in imperdiet sapien sollicitudin at.}},%
    {{Presen},{Nunc eu euismod nunc. Sed tincidunt, sem eu facilisis rhoncus.}},%
    {{Magna},{Phasellus velit dui, tristique at sem et, finibus volutpat sapien.}},%
    {{Vide},{Fusce in sapien mi. Vestibulum sed venenatis risus. Ut turpis dui.}},%
    {{Albi},{Proin dolor mauris, pellentes sem convallis. Suspendisse elementum.}},%
    {{Cosco},{Integer in molestie diam. Donec sapien, porta lacinia gravida ac.}}%
}%
\begin{document}
%   \foreach \s in \schedule {
%       \textbf{\GetListMember{\s}{1}:} \GetListMember{\s}{2} \\
%   }
    \begin{tabular}{ll}
        \foreach \s in \schedule {
            \textbf{\GetListMember{\s}{1}} & \GetListMember{\s}{2} \\
        }
    \end{tabular}
\end{document}

pdflatex states:

! Extra }, or forgotten \endgroup.
<template> \unskip \hfil }
                          \hskip \tabcolsep \endtemplate 
l.36        }

Unfortunately, tracing the build with \tracingall runs endlessly and I'm not familiar with macros. The build succeeds with documents like:

\begin{document}
%   \foreach \s in \schedule {
%       \textbf{\GetListMember{\s}{1}:} \GetListMember{\s}{2} \\
%   }
    \begin{tabular}{l}
        \foreach \s in \schedule {
            \textbf{\GetListMember{\s}{1}} \GetListMember{\s}{2}
        }
    \end{tabular}
\end{document}

and:

\begin{document}
    \foreach \s in \schedule {
        \textbf{\GetListMember{\s}{1}:} \GetListMember{\s}{2} \\
    }
%   \begin{tabular}{ll}
%       \foreach \s in \schedule {
%           \textbf{\GetListMember{\s}{1}} & \GetListMember{\s}{2} \\
%       }
%   \end{tabular}
\end{document}

You can find the discussion about GetListMember here: Macro to access a specific member of a list

I'm happy with every solution that enables building a table by iterating and accessing two dimensional data.

walfi
  • 23

1 Answers1

2

\foreach cannot straddle table cells.

There is a simpler way to do the task, with expl3.

I define a \listloop command that takes as argument a list name and a template for what to do to each list item.

In this case, each item in the list consists of a pair of braced items, so we can define \makerow to do \textbf{#1} & #2 \\ and the template will be

\makerow#1

so that we pass exactly the two arguments to \makerow. In the template #1 stands for the current list item being processed.

Another similar example is to build a description list.

The trick is that \clist_map_function:cN delivers the result altogether; the job is done in the first cell (in the tabular case, but then the & and \\ will build the cells. A scratch function \__walfi_list_loop:n function is redefined at each call.

\documentclass[12pt, a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\newlist}{mm}
 {
  \clist_clear_new:c { l_walfi_list_#1_clist }
  \clist_set:cn  { l_walfi_list_#1_clist } { #2 }
 }

\NewDocumentCommand{\looplist}{mm}
 {
  \cs_gset:Nn \__walfi_list_loop:n { #2 }
  \clist_map_function:cN  { l_walfi_list_#1_clist } \__walfi_list_loop:n
 }

\ExplSyntaxOff

\newlist{schedule}{
  %{Title}{Description},
  {Ipsum}{Pellentesque mauris mauris, feugiat ut.},
  {Lorem}{Integer viverra blandit magna, in imperdiet sapien sollicitudin at.},
  {Presen}{Nunc eu euismod nunc. Sed tincidunt, sem eu facilisis rhoncus.},
  {Magna}{Phasellus velit dui, tristique at sem et, finibus volutpat sapien.},
  {Vide}{Fusce in sapien mi. Vestibulum sed venenatis risus. Ut turpis dui.},
  {Albi}{Proin dolor mauris, pellentes sem convallis. Suspendisse elementum.},
  {Cosco}{Integer in molestie diam. Donec sapien, porta lacinia gravida ac.}
}

\newcommand{\makerow}[2]{\textbf{#1} & #2 \\}

\newcommand{\makeitem}[2]{\item[#1] #2}

\begin{document}

\begin{tabular}{lp{8cm}}
  \looplist{schedule}{\makerow#1}
\end{tabular}

\begin{description}
\looplist{schedule}{\makeitem#1}
\end{description}

\end{document}

enter image description here

egreg
  • 1,121,712
  • How can the list be completed with further columns? How to output only individual columns (for example only title) or output in different order (for example description, then title)? Some pointers will be enough I think. For now I don't understand your directions, however, I'll read into expl3 – walfi Jan 28 '19 at 07:48
  • @walfi I'm afraid that the request is too generic. – egreg Jan 28 '19 at 08:53