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
    – gigabytes
    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

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.