In a nutshell: I've seen code for creating tables programmatically using tabular
. Can it be done using tabularx
? If so, how?
I'm a math teacher, and I'd like to create a "problem set" environment in which I can list problems that will be formatted into a table.
Additionally, I'd like the environment to have a parameter that specifies the number of columns the table should have. This bit of modularity is why I'd prefer to use tabularx
.
The code below, inspired by other answers I've read here, uses tabular
and almost works as I'd like. Including the tabularx
package causes the code below to fail with an Illegal pream-token
error (update: that's a true statement, although the problem is in array
, which is used by tabularx
.)
I'd like help with any of the following:
(1) Can I use tabularx
instead of tabular
? What would I need to change to do so?
(2) If not, I'd like the table to be the same width (\textwidth
) no matter how many columns. This code doesn't behave in that way. What am I doing wrong in my current tabular
environment?
(3) Unrelated to table creation, but also needs fixing: My scheme for numbering these items is to use a counter and \int_use:N
, but the result is that the typeset output always has the last value of the counter. Like I said, I'm new to expl3 programming; to me, this code looks like it like it should work.
(4) Of course, I'm also open to suggestions for better ways to implement this.
Thanks, all!
The code:
\documentclass{article}
\usepackage{xparse}
\usepackage{environ}
\usepackage{lipsum}
\usepackage{tabularx}
\ExplSyntaxOn
\NewEnviron{problemset}[1]{\jermer_pset:V \BODY #1}
\seq_new:N \l_jermer_items_seq
\int_new:N \l_jermer_ncol_int
\int_new:N \l_jermer_ctr_int
\tl_new:N \l_jermer_tblpreamble_tl
\tl_new:N \l_jermer_tblcontent_tl
\cs_new_protected:Npn \jermer_pset:n #1 #2
{
\seq_set_split:Nnn \l_jermer_items_seq { \item } { #1 }
\seq_pop_left:NN \l_jermer_items_seq \l_tmpa_tl % remove empty element
\int_set:Nn \l_jermer_ncol_int { #2 }
\int_zero:N \l_jermer_ctr_int
\tl_clear:N \l_jermer_tblpreamble_tl
\tl_clear:N \l_jermer_tblcontent_tl
\seq_map_inline:Nn \l_jermer_items_seq
{
\int_incr:N \l_jermer_ctr_int
\tl_put_right:Nn \l_jermer_tblcontent_tl { \makebox[1.5em][r]{\__int_value:w \l_jermer_ctr_int}.~ ##1} % ??
\int_compare:nNnTF {\int_mod:nn {\l_jermer_ctr_int} {\l_jermer_ncol_int}} = {0}
{\tl_put_right:Nn \l_jermer_tblcontent_tl { \\ }}
{\tl_put_right:Nn \l_jermer_tblcontent_tl { & }}
}
\int_zero:N \l_jermer_ctr_int
\fp_new:N \l_jermer_wfrac_fp
\fp_set:Nn \l_jermer_wfrac_fp {1 / \l_jermer_ncol_int}
\tl_put_right:Nn \l_jermer_tblpreamble_tl { | }
\int_while_do:nn {\l_jermer_ctr_int < \l_jermer_ncol_int}
{
\tl_put_right:Nn \l_jermer_tblpreamble_tl { p{ \fp_to_decimal:N \l_jermer_wfrac_fp \textwidth} | } % Even col widths?
% \tl_put_right:Nn \l_jermer_tblpreamble_tl { X } % Would prefer this!
\int_incr:N \l_jermer_ctr_int
}
\jermer_draw_table:
}
\cs_generate_variant:Nn \jermer_pset:n { V }
\cs_new:Npn \jermer_draw_table:
{
\begin{center}
% Would prefer to use tabularx here.
\begin{tabular}{\l_jermer_tblpreamble_tl}
\tl_use:N \l_jermer_tblcontent_tl
\end{tabular}
\end{center}
}
\ExplSyntaxOff
\begin{document}
\noindent
\lipsum[1]
\begin{problemset}{3}
\item Alpha
\item Beta
\item Gamma
\item Delta
\item Epsilon
\item Zeta
\item Eta
\item Theta
\item Iota
\end{problemset}
\noindent
\lipsum[1]
\end{document}