3

I looking for a way to automate some of the work behind setting up single-day schedules. The final outcome I am looking for is something along the lines:

| Time          | Presenter   |
-------------------------------
| 12:00 - 12:20 | presenter 1 |
| 12:20 - 12:50 | presenter 2 |
| 12:50 - 13:10 | presenter 3 |
| 13:10 - 13:20 | break       |
| 13:20 - 14:00 | presenter 4 |

The idea is that the time in the left column should be generated more or less automatically. Note that some entries take more time than others. If we can automatically generate the left column, any subsequent changes of the schedule can easily be made without having to re-do the entire schedule by hand.

The most convenient way I can think of is to define a command that sets the starting time, and another command that keeps track of the current time and increments a given amount each time it is called.

The code to generate the table above would then look something like:

\SetStartTime{12:00}

\begin{tabular}[H!]{|l|l|}
      \hline
      Time & Presenter \\
      \hline
      \NewEntry{00:20} & presenter 1 \\
      \NewEntry{00:30} & presenter 2 (with more time) \\
      \NewEntry{00:20} & presenter 3 \\
      \NewEntry{00:10} & break \\
      \NewEntry{00:40} & presenter 4 \\
\end{tabular}

I haven't found any packages that can handle something similar, so I guess I would have to resort to custom commands to make it work.

metnix
  • 33

1 Answers1

3

Here is an implementation with expl3. We define an environment that takes the starting time as argument; this is converted to decimal form for doing later computations and the result is stored in an integer variable.

The environment will be filled with \Entry commands that take the allotted time in minutes and the title as arguments. This command prints the current time value (converting it back into hh:mm form), adds the allotted time, saves the value and prints it as the end time. Then &, the title and \\ are added.

Since the separator is a colon, we have to use an indirect method for using it as a delimiter in the auxiliary macros for the conversion, with the \char_generate:nn function (this is the only nonstandard trick in the code below).

\documentclass{article}
\usepackage{xparse}
\usepackage{booktabs}

\ExplSyntaxOn

\NewDocumentEnvironment{schedule}{m}
 {% #1 is the starting time
  % save the starting time in an integer variable
  \int_gset:Nn \g_metnix_schedule_start_int { \metnix_schedule_time_decimal:n { #1 } }
  % start a tabular
  \begin{tabular}{ll}
  \toprule
  \multicolumn{1}{c}{Time} & Presenter \\
  \midrule
 }
 {
  % end the tabular
  \bottomrule
  \end{tabular}
 }

\NewDocumentCommand{\Entry}{mm}
 {% #1 is the allotted time, #2 is the title
  % print the starting time
  \metnix_schedule_time_print:
  % separate the two times with <space><endash><space>
  { ~--~ }
  % add the allotted time
  \metnix_schedule_time_add:n { #1 }
  % print the end time
  \metnix_schedule_time_print:
  &
  #2 \\
 }

% allocate an integer variable
% (global, because the computations take place in tabular cell)
\int_new:N \g_metnix_schedule_start_int

% convert to decimal form, passing hh:mm to an auxiliary function
\cs_new:Nn \metnix_schedule_time_decimal:n
 {
  \__metnix_schedule_time_decimal:w #1 \q_stop
 }

% \__metnix_schedule_time_decimal:w has two arguments,
% the first is delimited by :, the second by \q_stop
\use:x
 {% we need the trick because : is special
  \cs_new:Npn
  \exp_not:N \__metnix_schedule_time_decimal:w 
  ##1 \char_generate:nn { `: } { 12 } ##2 \exp_not:N \q_stop
 }
 {
  % hours times 60 + minutes
  #1*60+#2
 }

\cs_new:Nn \metnix_schedule_time_print:
 {
  % add a leading zero if the hour is less than 10
  \int_compare:nT { \int_div_truncate:nn { \g_metnix_schedule_start_int } { 60 } < 10 } { 0 }
  \int_eval:n { \int_div_truncate:nn { \g_metnix_schedule_start_int } { 60 } }
  % print a colon
  :
  % add a leading zero if the minutes are less than 10
  \int_compare:nT { \int_mod:nn { \g_metnix_schedule_start_int } { 60 } < 10 } { 0 }
  \int_eval:n { \int_mod:nn { \g_metnix_schedule_start_int } { 60 } }
 }

% syntactic sugar for adding time
\cs_new:Nn \metnix_schedule_time_add:n
 {
  \int_gadd:Nn \g_metnix_schedule_start_int { #1 }
 }

\ExplSyntaxOff

\begin{document}

\begin{schedule}{12:00}
\Entry{20}{Presenter 1}
\Entry{30}{Presenter 2}
\Entry{20}{Presenter 3}
\Entry{10}{Break}
\Entry{80}{Presenter 4}
\end{schedule}

\end{document}

enter image description here

egreg
  • 1,121,712
  • This looks great, but I get this error when trying to compile your code with pdflatex ("\" inserted in place of newlines): ! Misplaced \noalign. \\ \bottomrule ->\noalign \\ {\ifnum 0=\}\fi @aboverulesep =\aboverulesep \global... \ l.88 \end{schedule}` – metnix Nov 21 '17 at 10:18
  • @metnix The \\ breaks are added automatically, you don't have to type them in. – egreg Nov 21 '17 at 10:30
  • That's not what I meant, I added the "\" to separate the different lines of the error message. The code I tried to compile was exactly what you posted. (sorry if this was unclear). – metnix Nov 21 '17 at 10:45
  • @metnix I copy-pasted the code in a new file and ran it without problems. Is Misplaced \noalign the very first error message? – egreg Nov 21 '17 at 10:50
  • Yes, it is the first message. Here's a link to the complete log: https://pastebin.com/PVynAHZZ EDIT: If I ignore this and 8 following errors (all pointing to l.88) I get the desired pdf... – metnix Nov 21 '17 at 11:11
  • @metnix Sorry, but you have an outdated TeX Live from 2015. – egreg Nov 21 '17 at 11:16