4

I want to have a macro that creates tables of a specific type which specialize in multiple choices questions.

The required command \createtable{#1}{#2}{#3} has three arguments:

  1. The total number of questions
  2. The number of columns in each row
  3. The caption of table

It also should create a label for that table.

Examples are given below:

\documentclass{article}

\usepackage[table,xcdraw]{xcolor}
\usepackage{tabu}

\begin{document}

\section{createtable[20][10][table 1 caption]}
\begin{table}[h]
\centering
\caption{table 1 caption}
\label{table:1}   %%% automatically generate {table:\tableCounter} as label

\begin{tabu} to 0.8\textwidth {| *{10}{X[c]|}}

\hline
\rowcolor[HTML]{EFEFEF}
1  & 2  & 3  & 4  & 5  & 6  & 7  & 8  & 9  & 10 \\ \hline
   &    &    &    &    &    &    &    &    &    \\ [1ex]\hline
\rowcolor[HTML]{EFEFEF}
11 & 12 & 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 \\ \hline
   &    &    &    &    &    &    &    &    &    \\ [1ex]\hline

\end{tabu}
\end{table}

\section{createtable[17][10][table 2 caption]}
\begin{table}[h]
\centering
\caption{table 2 caption}
\label{table:2}   %%% automatically generate {table:\tableCounter} as label
\begin{tabu} to 0.8\textwidth {| *{10}{X[c]|}}
\hline
\rowcolor[HTML]{EFEFEF}
1  & 2  & 3  & 4  & 5  & 6  & 7  & 8                        & 9                        & 10                       \\ \hline
   &    &    &    &    &    &    &                          &                          &                          \\ [1ex]\hline
\rowcolor[HTML]{EFEFEF}
11 & 12 & 13 & 14 & 15 & 16 & 17 &                          &                          &                          \\ \hline
   &    &    &    &    &    &    & \cellcolor[HTML]{9B9B9B} & \cellcolor[HTML]{9B9B9B} & \cellcolor[HTML]{9B9B9B} \\ [1ex]\hline
\end{tabu}
\end{table}

\section{createtable[17][6][table 3 caption]}
\begin{table}[h]
\centering
\caption{table 3 caption}
\label{table:3}  %%% automatically generate {table:\tableCounter} as label

\begin{tabu} to 0.8\textwidth {| *{6}{X[c]|}}

\hline
\rowcolor[HTML]{EFEFEF}
1  & 2  & 3  & 4  & 5  & 6  \\ \hline
   &    &    &    &    &    \\ [1ex]\hline
\rowcolor[HTML]{EFEFEF}
7  & 8  & 9  & 10 & 11 & 12 \\ \hline
   &    &    &    &    &    \\ [1ex]\hline
\rowcolor[HTML]{EFEFEF}
13 & 14 & 15 & 16 & 17 &    \\ \hline
   &    &    &    &    & \cellcolor[HTML]{9B9B9B}    \\ [1ex]\hline
\end{tabu}
\end{table}

\end{document} 

enter image description here

How can I do this?

  • 3
    tabu is a great package for those who enjoy nasty surprises. I don't, so I recommend not using it. You want an environment so \begin{createtable}{...? – cfr Jul 9 '15 at 1:19
  • yes, you are right. It should be \begin{createtable}[#1][#2][#3] – Baffin Chu Jul 9 '15 at 2:10
  • So how are you going to fill in the data within the environment? – cfr Jul 9 '15 at 15:52
  • like that: \createtable{20}{10}{Table 1 caption} – Baffin Chu Jul 9 '15 at 17:59
  • Well, then you seem to have a solution if you don't need to fill in the data at all? – cfr Jul 9 '15 at 21:12
5

Using the powerful tikz package, we can define a \newcommand with three arguments as follows:

\createtable{<# Questions>}{<# Columns>}{<Table caption>}

like this:

\documentclass[12pt,a4paper]{article}
\usepackage{tikz,xcolor}
\usetikzlibrary{calc}
\begin{document}

\newcounter{xy}
\definecolor{Qcolor}{HTML}{EFEFEF}
\definecolor{noQcolor}{HTML}{9B9B9B}
\newcommand{\createtable}[3]{%
\begin{table}[!h]\centering
\pgfmathparse{ceil(#1/#2)} 
\edef\yfin{\pgfmathresult}
\setcounter{xy}{0}
\begin{tikzpicture}[cell/.style={draw,minimum size=1cm}]
\foreach \y [count=\yi] in {1,...,\yfin}{%
   \foreach \x [count=\xi] in {1,...,#2}{%
   \addtocounter{xy}{1}
   \node [cell,fill=Qcolor]at ([shift={(0,-\yi)}]\xi,-\yi) {%
   \ifnum\the\value{xy}>#1{}\else\the\value{xy}\fi};
   \node [cell,fill={\ifnum\the\value{xy}>#1noQcolor\else white\fi}] 
   at ([shift={(0,-\yi-1)}]\xi,-\yi) {};}}
\end{tikzpicture}
\caption{#3} \label{Tab:#1#2}
\end{table}
}
\createtable{20}{10}{Table 1 caption} 
\createtable{17}{10}{Table 2 caption}
\createtable{17}{6}{Table 3 caption}
We can refer to Table \ref{Tab:2010}, Table \ref{Tab:1710} or Table \ref{Tab:176} as usual.
\end{document}

enter image description here

If the table is required to occupy the total \linewidth, we can modify the width of the cell to be equal to \linewidth/# columns as follows:

\newcounter{xy}
\definecolor{Qcolor}{HTML}{EFEFEF}
\definecolor{noQcolor}{HTML}{9B9B9B}
\newcommand{\createtable}[3]{%
\begin{table}[!h]\centering
\pgfmathparse{ceil(#1/#2)} 
\edef\yfin{\pgfmathresult}
\setcounter{xy}{0}
\begin{tikzpicture}[cell/.style={draw,minimum height=1cm,minimum width=\linewidth/#2}]
\foreach \y [count=\yi] in {1,...,\yfin}{%
   \foreach \x [count=\xi] in {1,...,#2}{%
   \addtocounter{xy}{1}
   \node [cell,fill=Qcolor]at ([shift={(0,-\yi)}]\xi*\linewidth/#2,-\yi) {%
   \ifnum\the\value{xy}>#1{}\else\the\value{xy}\fi};
   \node [cell,fill={\ifnum\the\value{xy}>#1noQcolor\else white\fi}] 
   at ([shift={(0,-\yi-1)}]\xi*\linewidth/#2,-\yi) {};}}
\end{tikzpicture}
\caption{#3} \label{Tab:#1#2}
\end{table}
}

enter image description here

Details

PGF has a good mathematical engine bywhich we can evaluate many expressions and perform many mathematical functions, besides a for/foreach loop for repeating actions. Since the required table is mainly a Question number with an empty cell below it in an ordered manner, then using a for loop is a natural choice. Also, it is so easy to fill a node with some color in TiKZ.

I used \pgfmathparse{<expression>} to calculate the number of rows as \pgfmathparse{ceil(#questions/#columns)} and stored this in \yfin for iteration along the rows. A counter xy is used to hold the Question number \newcounter{xy} initialized to zero \setcounter{xy}{0} and updated each iteration by \addtocounter{xy}{1}. The xcolor package is used for shading. A conditional on xy is used for shading color as fill={\ifnum\the\value{xy}>#1noQcolor\else white\fi} if there is no question. For referencing the table, \label{Tab:#1#2} is used as a unique label for each table.

The code can be much improved, but this at least addresses the OP requirements.

  • Why not use \pgfmathtruncatemacro{\yfin}{ceil(#1/#2)} instead of the combination of \pgfmathparse, \edef and \pgfmathprintresult? – Pier Paolo Jul 9 '15 at 17:22
  • 1
    @PierPaolo Yes, pgfmath has many useful macros, one can choose whatever of these to implement a solution. I used a primitive or more readable version (IMHO) however. – AboAmmar Jul 9 '15 at 17:41

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.