# latex table variable/optional many arguments

I would like to create a new tabular environment that allows me to add n (1-10) arguments without adding extra columns (such that both examples below work).

Here is my code:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[sfdefault]{AlegreyaSans}
\RequirePackage{booktabs}
\usepackage[table,x11names,dvipsnames,table]{xcolor}
\usepackage{tabularx}

\definecolor{mygreen}{RGB}{126,169,105}
\definecolor{myblue}{RGB}{9,28,87}

\begin{document}

\newenvironment{tabulargreen}[3]
{
% \renewcommand{\tempcaption}{#3}
\rowcolors{1}{mygreen!20}{mygreen!10}
\begin{tabular}{lcr}
\rowcolor{mygreen}
\textcolor{white}{\bfseries #1} & \textcolor{white}{\bfseries #2} & \textcolor{white}{\bfseries #3} \\
}
{
%      \caption{\tempcaption}
\end{tabular}
}

\begin{tabulargreen}{Name}{Zahl}{Nummer}
Modul eins & 2 & 3 \\
Modul zwei & 5 & 6 \\
Modul drei & 8 & 9 \\
Modul vier & 2 & 3 \\
Modul fünf & 5 & 6 \\
Modul sechs & 8 & 9 \\
\end{tabulargreen}

\vspace{5mm}

\begin{tabulargreen}{Name}{Zahl}
Modul eins & 3 \\
Modul zwei & 4 \\
Modul drei & 7 \\
\end{tabulargreen}

\end{document}


The tables still look like this:

Where does the "M" come from and how can I get rid of it?

Greetings and thanks a lot!

S.Millie

• you define tabulargreen to have three arguments and the the third one is the M leaving just odul as the text in the first cell. Did you intend to define the environment to just have two arguments? – David Carlisle Jul 7 '18 at 17:07
• hello David, I corrected the bracket. The environment uses three arguments as does the first example. For the second example I would like to have a different number of arguments and add more optional ones in the environment (say 7) instead of three. How can I do that? – s.millie Jul 7 '18 at 17:16
• sorry no you still use it as \begin{tabulargreen}{Name}{Zahl}M so the third argument is M I can not guess what you want to happen in that case. – David Carlisle Jul 7 '18 at 17:18
• hm, I would like to pass the words in the first row as arguments. The number of arguments shall be variable, it can be at most 7. Can I use something like \ifthenelse to test if #x is empty and not have another column then, or only add another column if there has been an argument? For the second example: I would like to make the third argument variable/optional, so that the third column disappears. Sorry for not being so specific. – s.millie Jul 7 '18 at 17:26
• latex optional arguments need to be [] delimited rather than {} but why that syntax rather than making them be & separated like the rest of the table? – David Carlisle Jul 7 '18 at 17:32

It's easier if you have only one argument, the header with the cells separated by the usual &.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[sfdefault]{AlegreyaSans}
\usepackage[table,x11names,dvipsnames,table]{xcolor}
\usepackage{xparse}

\definecolor{mygreen}{RGB}{126,169,105}
\definecolor{myblue}{RGB}{9,28,87}

\ExplSyntaxOn

\NewDocumentEnvironment{tabulargreen}{m}
{
\seq_set_split:Nnn \l_millie_tabgreen_head_in_seq { & } { #1 }
\seq_set_map:NNn
{ \millie_tabgreen_head:n { ##1 } }
\rowcolors{1}{mygreen!20}{mygreen!10}
\begin{tabular}
{
l
*{ \int_eval:n { \seq_count:N \l_millie_tabgreen_head_in_seq - 2 } } { c }
r
}
\rowcolor{mygreen}
\seq_use:Nn \l_millie_tabgreen_head_out_seq { & } \\
}
{
\end{tabular}
}
{
\textcolor{white}{\bfseries #1}
}
\ExplSyntaxOff

\begin{document}

\begin{tabulargreen}{Name & Zahl & Nummer}
Modul eins & 2 & 3 \\
Modul zwei & 5 & 6 \\
Modul drei & 8 & 9 \\
Modul vier & 2 & 3 \\
Modul fünf & 5 & 6 \\
Modul sechs & 8 & 9 \\
\end{tabulargreen}

\vspace{5mm}

\begin{tabulargreen}{Name & Zahl}
Modul eins & 3 \\
Modul zwei & 4 \\
Modul drei & 7 \\
\end{tabulargreen}

\end{document}


The idea is to count the number of headers, subtract 2 and make a suitable preamble l c … c r; the headers are massaged to add the requested formatting and then the table is built.

• Hi egreg - I thought I had answered you, somehow the comments disappeared.. Your answer was brilliant really! It helped such a lot. Follow-up question: How do I contrain the table to one column in my text and, by that, set the widths of the single columns in the table itself? OR: I think I could solve the problem by making line breaks, but somehow \newline and \\ didn't work. Do I need boxing here? – s.millie Aug 31 '18 at 7:18
• @s.millie Sorry, but I don't understand. – egreg Aug 31 '18 at 8:30
• Hello egreg, I'll try to be more precise. (*constrain) I would like to restrict the table to one column (of two) in my text, but it exceeds the boundary of my page. That is because in some lines there is too much text. Now if could put linebreaks in that text I could set the breadths/widths of the individual columns of my table. Is there a way how I can set these sizes such that I can restrict the breadth of the whole table to my column - in such a way that the lines break automatically? – s.millie Aug 31 '18 at 9:51
• @s.millie If a table has three columns, how do you “restrict” it to a single column? – egreg Aug 31 '18 at 9:53
• Ah, sorry. I meant to restrict each column of the three individually. Not turning 3 into 1, but setting the breadth of each single column of the table. I want to restrict the whole table to one text-column (one page, two columns. In one of these columns I have a table that has several columns itself, so I have text-columns and table-columns). – s.millie Aug 31 '18 at 10:03

As David says you still need to pass in three parameters based on how you have defined the tabulargreen environment:

\begin{tabulargreen}{Name}{Zahl}{}


As per the comments the code has beed modified to allow for 4 parameters (where the first two are mandatory and the last two are optional). So, not you need to invoke this as

\begin{tabulargreen}{Name}{Zahl}{}{}


Then, in the tabulargreen option you need to check if the optional parameters are empty and not define a column heading if they are. I used the ifmtarg package to do that but any other method to detect an empty option (such as using xparse) will do.

This technique can be extended to a maximum of nine paramters. Beyond that you need to do additional processing (see References).

## Notes:

• You were missing a trailing: \end{tabular}% -- I have added this to the code below. This removes extra horizontal spacing following the tabular (which won't show anything different in this MWE, but if you an \fbox{} around the usage of tabulargreen you can see the difference.

## Code:

\documentclass{article}
%\usepackage[utf8]{inputenc}
%\usepackage[T1]{fontenc}
%\usepackage[sfdefault]{AlegreyaSans}
\RequirePackage{booktabs}
\usepackage[table,x11names,dvipsnames,table]{xcolor}
\usepackage{tabularx}

\usepackage{ifmtarg}
\makeatletter%
\newcommand{\IfIsEmptyArg}[3]{\@ifmtarg{#1}{#2}{#3}}%
\makeatother%

\definecolor{mygreen}{RGB}{126,169,105}
\definecolor{myblue}{RGB}{9,28,87}

\begin{document}

\newenvironment{tabulargreen}[4]% <-- Note: 4 paramaters
{
%\renewcommand{\tempcaption}{#3}
\rowcolors{1}{mygreen!20}{mygreen!10}
\begin{tabular}{lcrr}
\rowcolor{mygreen}
\textcolor{white}{\bfseries #1}
& \textcolor{white}{\bfseries #2}
\IfIsEmptyArg{#3}{}{& \textcolor{white}{\bfseries #3}}
\IfIsEmptyArg{#4}{}{& \textcolor{white}{\bfseries #4}}
\\
}
{
%\caption{\tempcaption}
\end{tabular}% <---- Note trailing %
}

\begin{tabulargreen}{Name}{Zahl}{Nummer}{}% <-- Note: 4 paramaters
Modul eins & 2 & 3 \\
Modul zwei & 5 & 6 \\
Modul drei & 8 & 9 \\
Modul vier & 2 & 3 \\
Modul funf & 5 & 6 \\
Modul sechs & 8 & 9 \\
\end{tabulargreen}

\par\medskip
\begin{tabulargreen}{Name}{Zahl}{}{}% % <-- Note: 4 paramaters
Modul eins & 3 \\
Modul zwei & 4 \\
Modul drei & 7 \\
\end{tabulargreen}

\par\medskip
\begin{tabulargreen}{A}{B}{C}{D}% % <-- Note: 4 paramaters
1 & 2 & 3 & 4 \\
a & b & c & d \\
\end{tabulargreen}

\end{document}

• Hello Peter, thanks so much! It works. Now if I want to add another parameter #4 I change the following: \newcommand{\IfIsEmptyArg}[4]{\@ifmtarg{#1}{#2}{#3}{#4}}, \newenvironment{tabulargreen}[4], \begin{tabular}{l|c|r|r}, & \textcolor{white}{\bfseries #3} \IfIsEmptyArg{#4}{}{& \textcolor{white}{\bfseries #4}}, \begin{tabulargreen}{Name}{Zahl}{Nummer}{}, Modul eins & 2 & 3 & 3\ (Plus the others) and \begin{tabulargreen}{Name}{Zahl}{}{}. This, however, gives me the error message "Missing } inserted.". I have not found a missing "}". Can you help me? – s.millie Jul 8 '18 at 22:20
• You need to test paramater for being empty in the table, not in the \IfIsEmptyArg. So, definition of \IfIsEmptyArg should be as is in the above answer, and in your environment you have \IfIsEmptyArg{#3}{}{& \textcolor{white}{\bfseries #3}}  (as above) and include an additional line for each parameter \IfIsEmptyArg{#4}{}{& \textcolor{white}{\bfseries #4}}, \IfIsEmptyArg{#5}{}{& \textcolor{white}{\bfseries #5}}, etc. If you are still having difficulties let me know and I can update the answer to include these, but it seems that egreg's answer may be simpler for your case. – Peter Grill Jul 9 '18 at 1:57
• Hello Peter, that is exactly what I have done, adding another line without any signs ("\\", etc.) since it is a command. If you want you can still update the code for others, since I think your solution is easier to understand (for others) than egreg's, even though for me egreg's works rather well (just need to understand the code ;). Thanks for your help! – s.millie Jul 11 '18 at 19:36
• Based on your comment above you modified \newcommand{\IfIsEmptyArg}[4]{\@ifmtarg{#1}{#2}{#3}{#4}} which does not make sense. – Peter Grill Jul 11 '18 at 19:38
• @s.millie: Updated code to allow for 2-4 parameters. Let me know if that makes sense to you. – Peter Grill Jul 11 '18 at 19:47