5

Whenever I create a class list of my students, I use the format in MWE below. The problem I have is that I normally have to copy and paste a student name at a time and ensure the table is correct every time.

Is it possible to read the student names from a list or file and automatically create the table with a minimum of 20 rows pushing entry 21 in the 4th column as shown below. If the class list is less than 20, create only a three columns with #, Student Name and Signature.

Here is the MWE or desired output:

\documentclass{article}
\usepackage{array}
\begin{document}
\begin{center}
\renewcommand{\arraystretch}{1.3}
\makebox[\linewidth]{%
    \begin{tabular}{|r|l|>{\centering\arraybackslash}p{6em}|r|l|>{\centering\arraybackslash}p{6em}|}
    \hline
        \# & \textbf{Student Name} & \textbf{Signature} & \# & \textbf{Student Name} & \textbf{Signature}\\
    \hline
        1 & Surname, Fname Mname            & & 18 & Surname, Fname Mname &\\
    \hline
        2 & Surname, Fname Mname            & & 19 & Surname, Fname Mname &\\
    \hline
        3 & Surname, Fname Mname            & & 20 & Surname, Fname Mname &\\
    \hline
        4 & Surname, Fname Mname            & & 21 & Surname, Fname Mname &\\
    \hline
        5 & Surname, Fname Mname            & & 22 & Surname, Fname Mname &\\
    \hline
        6 & Surname, Fname Mname            & & 23 & Surname, Fname Mname &\\
    \hline
        7 & Surname, Fname Mname            & & 24 & Surname, Fname Mname &\\
    \hline
        8 & Surname, Fname Mname            & & 25 & Surname, Fname Mname &\\
    \hline
        9 & Surname, Fname Mname            & & 26 & Surname, Fname Mname &\\
    \hline
        10 & Surname, Fname Mname           & & 27 & Surname, Fname Mname &\\
    \hline
        11 & Surname, Fname Mname           & & 28 & Surname, Fname Mname &\\
    \hline
        12 & Surname, Fname Mname           & & 29 & Surname, Fname Mname &\\
    \hline
        13 & Surname, Fname Mname           & & 30 & Surname, Fname Mname &\\
    \hline
        14 & Surname, Fname Mname           & & 31 & Surname, Fname Mname &\\
    \hline
        15 & Surname, Fname Mname           & & 32 & Surname, Fname Mname &\\
    \hline
        16 & Surname, Fname Mname           & & 33 & Surname, Fname Mname &\\
    \hline
        17 & Surname, Fname Mname           & & 34 & Surname, Fname Mname &\\
    \hline
    \end{tabular}}
\end{center}
\end{document}

enter image description here

enter image description here

Note that the maximum number of students is 40.

I read @egreg answer in https://tex.stackexchange.com/a/499035/10898 but it seemed a bit complicated. I know probably I need to use filecontents but I haven't been able to use it with a table format.

azetina
  • 28,884

1 Answers1

4

Yes, you can read from a file and build the table in a rather straightforward way.

\documentclass{article}
\usepackage[margin=1cm]{geometry} % make room
\usepackage{xparse,array}

\ExplSyntaxOn

\NewDocumentCommand{\studentlist}{m}
 {% #1 = file name
  \azetina_studentlist:n { #1 }
 }

\ior_new:N \g_azetina_studentlist_stream
\seq_new:N \l_azetina_studentlist_seq
\seq_new:N \l__azetina_studentlist_temp_seq
\tl_new:N \l__azetina_studentlist_header_tl

\cs_new_protected:Nn \azetina_studentlist:n
 {
  \seq_clear:N \l_azetina_studentlist_seq
  \ior_open:Nn \g_azetina_studentlist_stream { #1 }
  \int_zero:N \l_tmpa_int
  % populate the sequence
  \ior_map_inline:Nn \g_azetina_studentlist_stream
   {
    \int_incr:N \l_tmpa_int
    \seq_put_right:Nx \l_azetina_studentlist_seq
     {
      \int_to_arabic:n { \l_tmpa_int } & \exp_not:n { ##1 } &
     }
   }
  % build the header
  \tl_set:Nn \l__azetina_studentlist_header_tl
   {
    \# & \textbf{Student~Name} & \textbf{Signature}
   }
  % check the number
  \int_compare:nT { \seq_count:N \l_azetina_studentlist_seq > 20 }
   {
    \__azetina_studentlist_halve:
   }
  % make the table
  \par\noindent
  \begin{tabular}{|*{2}{r|l|w{c}{6em}|}}
  \hline
  \tl_use:N \l__azetina_studentlist_header_tl \\ \hline
  \seq_map_function:NN \l_azetina_studentlist_seq \__azetina_studentlist_row:n
  \end{tabular}
 }

\cs_new_protected:Nn \__azetina_studentlist_halve:
 {
  % make it even
  \int_if_odd:nT { \seq_count:N \l_azetina_studentlist_seq }
   {
    \seq_put_right:Nn \l_azetina_studentlist_seq { \multicolumn{3}{c|}{} }
   }
  % split in half
  \seq_clear:N \l__azetina_studentlist_temp_seq
  \int_step_inline:nn { \seq_count:N \l_azetina_studentlist_seq / 2 }
   {
    \seq_put_right:Nx \l__azetina_studentlist_temp_seq
     {
      \seq_item:Nn \l_azetina_studentlist_seq { ##1 } &
      \seq_item:Nn \l_azetina_studentlist_seq { ##1 + \seq_count:N \l_azetina_studentlist_seq / 2 }
     }
   }
  % replace the sequence
  \seq_set_eq:NN \l_azetina_studentlist_seq \l__azetina_studentlist_temp_seq
  % double the header
  \tl_put_right:Nx \l__azetina_studentlist_header_tl
   {
    & \exp_not:V \l__azetina_studentlist_header_tl
   }
 }

\cs_new_protected:Nn \__azetina_studentlist_row:n
 {
  #1 \\ \hline
 }

\ExplSyntaxOff

\begin{document}

\studentlist{namelist40}

\bigskip

\studentlist{namelist31}

\bigskip

\studentlist{namelist18}

\end{document}

Here's the file namelist40.tex, the other two files just use the first n rows. The names have been generated by https://homepage.net/name_generator/ (apologies if people see themselves listed).

Alsop, Christian
Arnold, Carol
Bailey, Brian
Bell, Luke
Blake, Wendy
Bond, Abigail
Bower, Phil
Chapman, Austin
Cornish, Sebastian
Davidson, Sebastian
Dyer, Frank
Dyer, Molly
Grant, Harry
Henderson, Anna
Henderson, Rebecca
Henderson, Theresa
Howard, Joanne
Hudson, Peter
Ince, Brian
Kelly, Richard
Knox, Thomas
Lawrence, Isaac
MacLeod, Joe
McLean, John
Morrison, Liam
Murray, Stephen
Oliver, Stephanie
Payne, Sebastian
Powell, Kimberly
Pullman, Keith
Rampling, Faith
Rees, Joshua
Ross, Sebastian
Rutherford, Joanne
Sanderson, Hannah
Short, Kylie
Slater, Joshua
Springer, Jake
Springer, Sally
Sutherland, Lillian

enter image description here

egreg
  • 1,121,712
  • Thanks for the presented solution. Can you guide me as to documentation for the LaTeX 3 commands? \azetina_studentlist:n, \ior_new:N, \seq_new:N, \seq_new:N, \tl_new:N ... – azetina Jan 04 '20 at 17:52
  • @azetina The \<module>_new:N commands allocate a new variable; \azetina_studentlist:n is the main command, which is defined in the presented code. – egreg Jan 04 '20 at 17:55
  • Thanks. Am reading http://texdoc.net/texmf-dist/doc/latex/l3kernel/interface3.pdf to understand some of the commands. – azetina Jan 04 '20 at 23:33