6

I am trying to build a table inside a LaTeX 3 command. A MWE:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\createTable}{ m m }{
    \begin{tabular}{|c*{#2}{|c}|}
        \hline
        \int_step_inline:nnnn {1} {1} {#1} {
            ##1
            \int_step_inline:nnnn {1} {1} {#2} {
                & x
            }
            \\\hline
        }
    \end{tabular}
}
\ExplSyntaxOff

\begin{document}

    \createTable{5}{4}

\end{document}

This gives me following ouput in which the column lines of the first column are too long:

enter image description here

In order to solve this problem I read questions

  1. Too long vertical lines in table
  2. Too long vertical lines in table when declarations must remain on distinct lines
  3. Producing expandable environments with only optional arguments with LaTeX3 syntax

Though I still did not understand the actual nature of the problem (or its given solutions), I was able to reproduce the solution from Producing expandable environments with only optional arguments with LaTeX3 syntax.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareDocumentCommand{\fillRow}{ m m }{
    #1
    \int_step_inline:nnnn {1} {1} {#2} {
    & x
    }
    \\\hline
}

\DeclareDocumentCommand{\BuildTable}{ m }{
    \begin{tabular}{|c*{#1}{|c}|}
    \hline
}

\def\endBuildTable{
    \end{tabular}
}
\ExplSyntaxOff

\begin{document}

    \begin{BuildTable}{4}
        \fillRow{1}{4}
        \fillRow{2}{4}
        \fillRow{3}{4}
        \fillRow{4}{4}
        \fillRow{5}{4}
    \end{BuildTable}

\end{document}

This code outputs the desired result. But I don't like it because it needs 3 commands instead of 1 (minor issue). But most of all because of the verbose, redundant and inflexible syntax to generate the table. Therefore I decided to make an abstraction by putting the table-generating-commands in another command:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareDocumentCommand{\fillRow}{ m m }{
    #1
    \int_step_inline:nnnn {1} {1} {#2} {
    & x
    }
    \\\hline
}

\DeclareDocumentCommand{\BuildTable}{ m }{
    \begin{tabular}{|c*{#1}{|c}|}
    \hline
}

\def\endBuildTable{
    \end{tabular}
}

\DeclareDocumentCommand{\putTogether}{ m m }{
    \begin{BuildTable}{#2}
        \int_step_inline:nnnn {1} {1} {#1} {
            \fillRow{##1}{#2}
        }
    \end{BuildTable}
}
\ExplSyntaxOff

\begin{document}

    \putTogether{5}{4}

\end{document}

But this brought me back to my original problem because the column lines of the first column are too long again.

Could anyone

  1. explain to me what exactly is wrong with my original code;
  2. what the difference is between the second and the third code fragments;
  3. how to edit my (original) code in order to solve my problem?
  • I always struggle with this too. There's a refined `\noalign{\edef\x...}\x approach, but easier is to make just one row less and add the final one again – user31729 Dec 31 '15 at 12:43
4

The problem is that \int_step_inline:nnnn has an unexpandable terminating part which goes into the way before \end{tabular} can be seen, so this creates a new table cell (in a new row).

You can avoid this with \prg_replicate:nn:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\fillRow}{ m m }
 {
  #1 \prg_replicate:nn { #2 } { & x } \\ \hline
 }

\NewDocumentCommand{\putTogether}{ m m }
 {
  \begin{tabular}{|c*{#1}{|c}|}
  \hline
  \int_gzero:N \g_tmpa_int
  \prg_replicate:nn { #1 }
   {
    \int_gincr:N \g_tmpa_int
    \fillRow{\int_to_arabic:n { \g_tmpa_int } } {#2}
   }
  \end{tabular}
}
\ExplSyntaxOff

\begin{document}

\putTogether{5}{4}

\end{document}

enter image description here

Alternatively, you can collect the table body in a token list and deliver it at once.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\fillRow}{ m m }
 {
  #1 \prg_replicate:nn { #2 } { & x } \\ \hline
 }

\NewDocumentCommand{\putTogether}{ m m }
 {
  \begin{tabular}{|c*{#1}{|c}|}
  \hline
  \tl_clear:N \l_tmpa_tl
  \int_step_inline:nnnn { 1 } { 1 } { #1 }
   {
    \tl_put_right:Nn \l_tmpa_tl { \fillRow { ##1 } {#2} }
   }
  \tl_use:N \l_tmpa_tl
  \end{tabular}
}
\ExplSyntaxOff

\begin{document}

\putTogether{5}{4}

\end{document}
3

No explanation so far, but working. I'll improve later on!

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareDocumentCommand{\fillRow}{ m m }{
    #1
    \int_step_inline:nnnn {1} {1} {#2} {
    & x
    }
%    \hline
}

\DeclareDocumentCommand{\BuildTable}{ m }{
    \begin{tabular}{|c*{#1}{|c}|}
    \hline
}

\def\endBuildTable{
    \end{tabular}
}



\DeclareDocumentCommand{\putTogether}{ m m }{
  \begin{BuildTable}{#2}
    \int_step_inline:nnnn {1} {1} {#1-1} {
      \fillRow{##1}{#2} \\ \hline
    }%
    \fillRow{#1}{#2} \\
    \hline
  \end{BuildTable}
}
\ExplSyntaxOff

\begin{document}
\putTogether{5}{4}

\end{document}

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.