4

I am trying to create a template sort of LaTeX document for myself where I can set a number near the beginning (like a variable) and later in the document there shall be a table with as many rows as that number. Also, in the first column there shall be an increasing list of numbers. So if I set the 'variable' to 5, I would get a table with numbers from 1 to 5 in the first column.

I have followed this professional's answer to a similar question to create this table using tokens. My problem is that I can't get the numbers in my first column like I desire. Here is an MWE

\documentclass{article}

\def\numberoflines{10}

\newcounter{i}
\setcounter{i}{0}
\newtoks\tabtoks
\newcommand*\addtabtoks[1]{\tabtoks\expandafter{\the\tabtoks#1}}
\newcommand*\resettabtoks{\tabtoks{}}
\newcommand*\printtabtoks{\the\tabtoks}

\begin{document}

\resettabtoks
\loop\ifnum\thei<\numberoflines
    \addtabtoks{\thei & \\ \hline}
    \stepcounter{i}
\repeat

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \printtabtoks
\end{tabular}

\end{document}

yes, I know vertical lines are ugly; this is a special use case, not for professional typesetting, please ignore

Output:

MWE output

Is there some fix to get 1-10 instead of 10 everywhere?

Thanks in advance!

3 Answers 3

8

The main problem is that you aren't expanding \thei, so the token register will contain

\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline
\thei & \\ \hline

However, the idea of doing

\expandafter\addtabtoks\expandafter{\thei & \\ \hline}

doesn't work, because the first level expansion of \thei is \arabic{i}; a further expansion gives \number\c@i and a third expansion would be needed, leading to a whopping 14 repetitions of \expandafter. Not ideal.

The simplest trick is to force expansion all the way with

\expandafter\addtabtoks\expandafter{\romannumeral-`Q\thei & \\ \hline}

Also \stepcounter{i} should be moved before this instruction.

\documentclass{article}

\def\numberoflines{10}

\newcounter{i}
\setcounter{i}{0}
\newtoks\tabtoks
\newcommand*\addtabtoks[1]{\tabtoks\expandafter{\the\tabtoks#1}}
\newcommand*\resettabtoks{\tabtoks{}}
\newcommand*\printtabtoks{\the\tabtoks}

\begin{document}

\resettabtoks
\loop\ifnum\thei<\numberoflines
    \stepcounter{i}
    \expandafter\addtabtoks\expandafter{\romannumeral-`Q\thei & \\ \hline}
\repeat
\showthe\tabtoks

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \printtabtoks
\end{tabular}

\end{document}

You may find the following solution better. Any number of rows can be specified at runtime.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\makerows}{m}
 {
  \int_step_function:nN { #1 } \__bertalanp_mr_row:n
 }
\cs_new:Nn \__bertalanp_mr_row:n { #1 & \\ \hline }
\ExplSyntaxOff

\begin{document}

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \makerows{10}
\end{tabular}

\end{document}

enter image description here

2
  • The alternative solution you provided clearly seems superior, thank you. I am not even sure if using LaTeX for things like this is appropriate (is it?), but this xparse solution is still elegant.
    – bp99
    Oct 27, 2018 at 20:36
  • 1
    In my opinion (not that you asked for it), doing things like this is where LaTeX really shines Oct 28, 2018 at 8:16
3

Three Four ways to do this on-the-fly without pre-accumulating tokens, using xinttools. The first method only uses a counter.

expandable replication with normal LaTeX counter

Sorry for \romannumeral but this is the syntax for using \xintreplicate. If you prefer, define \newcommand{\xintReplicate}{\romannumeral\xintreplicate} to hide it and use \xintReplicate.

\documentclass{article}
\usepackage{xinttools}

\newcounter{i}

\newcommand{\makerows}[1]{%
   \romannumeral\xintreplicate{#1}{\stepcounter{i}\thei&\\\hline}%
}

\begin{document}

\setcounter{i}{0}
\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \makerows{10}
\end{tabular}

\end{document}

No counter is used in the next three methods.

expandable loop with magic loop indexing

This is completely expandable loop; a somewhat delicate beast to use. The parameter #1 is assumed to be explicit digits (the end of line space terminates them in the \ifnum test).

\documentclass{article}
\usepackage{xinttools}

\newcommand{\makerows}[1]{%
   \xintiloop[1+1]
   \xintiloopindex & \\ \hline
   \unless\ifnum\xintiloopindex=#1
   \repeat
}
\begin{document}

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \makerows{10}
\end{tabular}

\end{document}

xintFor loop over integers (starts at 1 per default) with a Break

Here the ##1 is encapsulated in a \numexpr, hence the need for \number.

\documentclass{article}
\usepackage{xinttools}

\newcommand{\makerows}[1]{%
   \xintFor ##1 in \xintintegers
   \do 
   {\number##1 & \\ \hline
   \ifnum#1=##1\expandafter\xintBreakFor\fi}%
}

\begin{document}

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \makerows{10}
\end{tabular}

\end{document}

xintFor loop with pre-computed list of integers

Here the ##1 are digit tokens.

\documentclass{article}
\usepackage{xinttools}

\newcommand{\makerows}[1]{%
   \xintFor* ##1 in {\xintSeq{1}{#1}}
   \do 
   {##1 & \\ \hline}%
}

\begin{document}

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \makerows{10}
\end{tabular}

\end{document}

output (same for all four methods, of course)

enter image description here

1
  • for the first method (\xintreplicate) one only needs the smaller package xintkernel, not needed to load xinttools.
    – user4686
    Oct 28, 2018 at 13:08
2

You need some more expansion. As it is only the macro \thei is stored and it will be executed when typesetting it (i.e. at the end when i=10).

\documentclass{article}

\def\numberoflines{10}

\newcounter{i}
\setcounter{i}{0}
\newtoks\tabtoks
\newcommand*\addtabtoks[1]{\tabtoks\expandafter{\the\tabtoks#1}}
\newcommand*\resettabtoks{\tabtoks{}}
\newcommand*\printtabtoks{\the\tabtoks}

\begin{document}

\resettabtoks
\loop\ifnum\value{i}<\numberoflines
    \expandafter\addtabtoks\expandafter{\expanded{\arabic{i}} & \\ \hline}
    \stepcounter{i}
\repeat

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \printtabtoks
\end{tabular}

\end{document}

Edit: \expanded is currently LuaLaTeX-only. Here's a more general version:

\documentclass{article}

\def\numberoflines{10}

\newcounter{i}
\setcounter{i}{0}
\newtoks\tabtoks
\newcommand*\addtabtoks[1]{\tabtoks\expandafter{\the\tabtoks#1}}
\newcommand*\resettabtoks{\tabtoks{}}
\newcommand*\printtabtoks{\the\tabtoks}

\begin{document}

\resettabtoks
\loop\ifnum\value{i}<\numberoflines
        \edef\tmpi{\thei}
    \expandafter\addtabtoks\expandafter{\tmpi & \\ \hline}
    \stepcounter{i}
\repeat

\begin{tabular}{| c | c |}
    \hline
    number & empty \\
    \hline
    \printtabtoks
\end{tabular}

\end{document}
4
  • What is expanded? xelatex gives me undefined control sequence for that.
    – bp99
    Oct 27, 2018 at 20:01
  • 2
    At present, only LuaTeX features \expanded.
    – egreg
    Oct 27, 2018 at 20:03
  • 1
    @bertalanp99 It is LuaTeX only, but I have added a more general approach.
    – TeXnician
    Oct 27, 2018 at 20:06
  • 1
    This prints the numbers from 0 to 9. For 1 to 10, \stepcounter{i} must be moved just after \numberoflines.
    – egreg
    Oct 27, 2018 at 20:33

You must log in to answer this question.

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