Eine Fortsetzung vonmeine vorherige Fragebeantwortet dank @egreg. (Vielleicht könnte mir Prof. Gregorio hier auch helfen.)
Situation
Ich erstelle ein ToQ-Makro (Table of Questions), um eine Bewertungstabelle auf dem Deckblatt einer Prüfung oder Aufgabe zu erstellen. Es funktionierte gut, tabular
aber ich bin zu Tabularray gewechselt tblr
, in das ich mich verliebt habe. Da ich normalerweise totcount
Zähler für die Noten in jeder neuen Frage erstelle, sobald sie auftritt, stoße ich leider auf Erweiterungsprobleme, die mich heute ratlos gemacht haben.
Problem
Schleifen können nicht in eine Umgebung eingefügt werden tblr
(siehe§3.2.3des Handbuchs), wie es bei normalen Tabellen der Fall ist. Aber die Lösungen, die für normale Tabellen zu funktionieren scheinen:
- Verwendung von LaTeX-Grundschleifen,
- Erstellen des Körpers außerhalb der Tabelle als \gdef aus \edefs und
- Aufbau des Körpers als Token-Register,
hat nicht funktioniert tblr
. Darüber hinaus tblr
kann man eine Option angeben, expand
um Token für die Erweiterung anzugeben, bevor der Text verarbeitet wird. (Ich werde dies im späteren MWE zeigen.)
Was ich möchte
Inspiriert von @frougons AntwortHier, ich würde gerne einen kompletten expl3-Ansatz wählen, da ich sowieso versuche, expl3 zu lernen. Aber ich bin überfordert und würde mich über etwas Hilfe freuen. Nicht nur eine Lösung, wenn Sie so freundlich wären, hätte ich gerne eine kurze Übersicht, damit ich die Lösung studieren kann, indem ich die Dokumente durchforste.
MWE
\documentclass{article}
\usepackage{tabularray}
\usepackage{xcolor}
\usepackage{totcount}
% Stuff for keeping account of questions and their scores
% ........................................................<<<
\newcounter{questioncount}
\setcounter{questioncount}{0}
\regtotcounter{questioncount}%
\newcounter{scoretotal}
\setcounter{scoretotal}{0}
\regtotcounter{scoretotal}%
\newcommand{\setquestionpoints}[2]{%
\expanded{\noexpand\newtotcounter{qpoints#1}}%
\expanded{\noexpand\setcounter{qpoints#1}}{#2}%
}
\newcommand{\getquestionpoints}[1]{%
\ifnum\value{qpoints#1}>0
\arabic{qpoints#1}%
\else
0%
\fi
}
\newcommand{\TOTAL}[1]{%
\ifcsname c@#1@totc\endcsname
\total{#1}%
\else
??%
\fi
}
% ........................................................>>>
% Typesetting questions
% ........................................................<<<
\newcommand{\nquestion}[1]{%
\stepcounter{questioncount}%
\setquestionpoints{\arabic{questioncount}}{#1}%
\addtocounter{scoretotal}{#1}%
Question~\thequestioncount (#1 marks.)%
}
% ........................................................>>>
\ExplSyntaxOn
\cs_new_protected:Npn \my_typeset_table_generic:nn #1#2
{
\group_begin:
\cs_set_protected:Npn \__my_typeset_table_generic_tmp_func:n ##1 {#1}
\__my_typeset_table_generic_tmp_func:n {#2}
\group_end:
}
\cs_generate_variant:Nn \my_typeset_table_generic:nn { nV }
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
% This works, but I would like to know how expl3 can help me build this
% list automatically, looping for
% q ∈ [1, \totvalue{questioncount}]
% to obtain \TOTAL{qpoints\theq} in each cell of the middle column.
\tl_set:Nn \l_my_tabular_tl {%
1 & \TOTAL{qpoints1} & \null \\ \hline
2 & \TOTAL{qpoints2} & \null \\ \hline
3 & \TOTAL{qpoints3} & \null \\ \hline
}
\my_typeset_table_generic:nV
{
\SetTblrInner{rowsep=1ex}%
\begin{tblr}{colspec={|ccX[c]|}, width=0.35\linewidth}
\SetRow{black, rowsep=0.25ex}
\color{white}\textit{Q}\textnumero & \color{white}Marks & \color{white}Grade \\ \hline
#1
\SetCell[c=2]{c}~TOTAL:~&~\null\\\cline[r]{3-3}
&& {\TOTAL{scoretotal}}\\\hline
\end{tblr}
}
\l_my_tabular_tl
\ExplSyntaxOff
%%% Make some questions:
\vspace{2cm}
\noindent
\nquestion{10}\\
\nquestion{12}\\
\nquestion{15}\\
\end{document}
Produziert:
Antwort1
Das letzte \\
Nachher \nquestion{15}
hat eine Badbox verursacht und wird daher entfernt.
Die tblr
Umgebung kann außerhalb des expl3-Codes platziert werden. Die Option expand
in der tblr
Umgebung wird verwendet. Sie \my_typeset_table_generic:nn
wird dann nicht mehr benötigt.
In der tblr
Umgebung wird die Option rowsep=1ex
in die Optionenliste gestellt, die Einstellungen für die erste Zeile werden mit der Taste festgelegt . Dann ist dreimaliges row{1}
Schreiben unnötig .\color{white}
Das Makro \null
wird entfernt.
Die Klammern ringsherum \TOTAL{scoretotal}
werden entfernt.
Im Befehl wird danach ein \nquestion
, {}
hinzugefügt \thequestioncount
, damit die Klammern nicht unmittelbar auf die Zahl folgen.
Das Makro \l_my_tabular_tl
wurde nicht mit initialisiert \tl_new:N
. Dies wird nun mit erledigt \tl_new:N \tblrbody
.
Die Inhalte werden mit gesammelt \tl_build_put_right:Nn
. Dieser Vorgang wird mit gestartet \tl_build_begin:N
und mit beendet \tl_build_end:N
.
Es ist nicht notwendig, \setcounter{questioncount}{0}
danach etwas einzufügen \newcounter{questioncount}
, da der Anfangswert bereits 0 ist.
Anstelle von \newcounter
und kann \regtotcounter
die Abkürzung verwendet werden.\newtotcounter
Es ist nicht notwendig, den Befehl zu definieren \TOTAL
. Dieser wird durch ersetzt \total
.
Der Befehl \setquestionpoints
ist in den Befehl integriert \nquestion
. Dabei \arabic{questioncount}
wird durch ersetzt \thequestioncount
. Für \setcounter
sind \expanded
und \noexpand
nicht erforderlich.
Nach wird \SetCell
ein &
hinzugefügt, da bei der Verwendung \SetCell
ausgelassene Zellen nicht entfernt werden dürfen.
\documentclass{article}
\usepackage{xcolor}
\usepackage{tabularray}
\usepackage{totcount}
% Stuff for keeping account of questions and their scores
% ........................................................<<<
\newtotcounter{questioncount}
\newtotcounter{scoretotal}
\newcommand{\getquestionpoints}[1]{%
\ifnum\value{qpoints#1}>0
\arabic{qpoints#1}%
\else
0%
\fi
}
% ........................................................>>>
% Typesetting questions
% ........................................................<<<
\newcommand{\nquestion}[1]{%
\stepcounter{questioncount}%
\expanded{\noexpand\newtotcounter{qpoints\thequestioncount}}%
\setcounter{qpoints\thequestioncount}{#1}%
\addtocounter{scoretotal}{#1}%
Question~\thequestioncount{} (#1 marks.)%
}
% ........................................................>>>
\begin{document}
\ExplSyntaxOn
\tl_new:N \tblrbody
\tl_build_begin:N \tblrbody
\int_step_inline:nn { \totvalue { questioncount } }
{
\tl_build_put_right:Nn \tblrbody { #1 & \total { qpoints#1 } & \\ \hline }
}
\tl_build_end:N \tblrbody
\ExplSyntaxOff
\begin{tblr}[expand=\tblrbody]{
colspec={|ccX[c]|},
width=0.35\linewidth,
rowsep=1ex,
row{1}={bg=black,fg=white,rowsep=0.25ex}
}
\emph{Q}\textnumero & Marks & Grade\\\hline
\tblrbody
\SetCell[c=2]{c} ~TOTAL:~ & & \\\cline[r]{3-3}
& & \total{scoretotal}\\\hline
\end{tblr}
%%% Make some questions:
\vspace{2cm}
\noindent
\nquestion{10}\\
\nquestion{12}\\
\nquestion{15}
\end{document}
Antwort2
Ich habe eine Lösung gefunden, bei der ich die Zeilen eines Makros in expl3 erstelle. Ich denke nicht, dass das die eleganteste ist, aber es funktioniert. Ich bin an Tipps/Kommentaren zur Verbesserung interessiert, daher lasse ich diese Antwort unakzeptiert, um zu sehen, ob jemand mit etwas Schönem einsteigt.
\ExplSyntaxOn
\NewDocumentCommand{\ToQ}{}{
\tl_set:Nn \l_tmpa_tl {
\SetTblrInner{rowsep=1ex}%
\begin{tblr}[b]{colspec={|ccX[c]|}, width=0.35\linewidth}
\SetRow{black, rowsep=0.25ex}
\color{white}\textit{Q}\textnumero
& \color{white}Marks
& \color{white}Grade \\ \hline
}
\int_step_inline:nn {\totvalue{questioncount}} {
\tl_put_right:Nn \l_tmpa_tl { ##1 & \fromaux{qpoints##1} & \null \\ \hline }
}
\tl_put_right:Nn \l_tmpa_tl {
\SetCell[c=2]{c}~TOTAL:~&~\null\\\cline[r]{3-3}
&& {\fromaux{scoretotal}}\\\hline
\end{tblr}
}
\l_tmpa_tl
}
\ExplSyntaxOff
Produziert
Antwort3
Das Leben muss nicht so kompliziert sein. Beginnen Sie immer damit, anzugeben, wie die Eingabe und die Ausgabe aussehen sollen. Das heißt, Sie stellen eine API bereit.
- Sie benötigen die LaTeX2e-Zähler nicht, verwenden Sie das
int
Modul. - Wenn Sie Werte speichern möchten, denken Sie an
csname
. - Erstellen Sie eine Reihe von Befehlen
\Q1
und\Qn
speichern Sie den Wert, denn\Q1-marks
wenn Sie möchten, können Sie\Q1-question
auch die eigentliche Frage speichern.
Hier ist eine schnelle Lösung. Ich habe tabellarisch verwendet, nur um die Konzepte zu demonstrieren. Generell versuche ich, die Anzahl der von mir verwendeten Pakete zu minimieren. Bitte ändern Sie die Vorgehensweise, indem Sie den l3-Befehlen Präfixe hinzufügen.
\documentclass{article}
%------------------------------------------------------------
% INPUT : \AddQuestion{name}{marks}
% OUTPUT: PrintScoreSheet
%------------------------------------------------------------
\ExplSyntaxOn
\int_new:N \g_questions_total_int
\clist_new:N \g_questions_clist
\prop_new:N \g_questions_marks_prop
\cs_new_protected:Npn \questions_add:nn #1 #2
{
\clist_gput_right:Nn \g_questions_clist {#1}
\prop_gput:Nnn \g_questions_marks_prop {#1} {#2}
}
\cs_new_protected:Npn \questions_printlist:
{
\begin{tabular}{lrr}
\hline
\clist_map_inline:Nn \g_questions_clist
{
\prop_get:NnN \g_questions_marks_prop {##1} \l_tmpa_tl
\int_gadd:Nn \g_questions_total_int { \l_tmpa_tl }
##1 & \use:c{##1-marks} &\\ %Row
}
\\\noalign{\vskip-10pt}
\cline{2-3}
Total & \int_use:N\g_questions_total_int &\\
\hline
\end{tabular}
}
\let\AddQuestion\questions_add:nn
\let\PrintScoreSheet\questions_printlist:
\ExplSyntaxOff
\begin{document}
\AddQuestion {Q1}{10}
\AddQuestion {Q2}{20}
\AddQuestion {Q3}{5}
\AddQuestion{Q4}{5}
\PrintScoreSheet
\end{document}