Expl3 zur Vereinfachung von Erweiterungsproblemen mit schleifenerstelltem Tabularray-Inhalt

Expl3 zur Vereinfachung von Erweiterungsproblemen mit schleifenerstelltem Tabularray-Inhalt

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, tabularaber ich bin zu Tabularray gewechselt tblr, in das ich mich verliebt habe. Da ich normalerweise totcountZä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 tblrkann man eine Option angeben, expandum 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 tblrUmgebung kann außerhalb des expl3-Codes platziert werden. Die Option expandin der tblrUmgebung wird verwendet. Sie \my_typeset_table_generic:nnwird dann nicht mehr benötigt.

In der tblrUmgebung wird die Option rowsep=1exin 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 \nullwird 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_tlwurde 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:Nund 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 \newcounterund kann \regtotcounterdie Abkürzung verwendet werden.\newtotcounter

Es ist nicht notwendig, den Befehl zu definieren \TOTAL. Dieser wird durch ersetzt \total.

Der Befehl \setquestionpointsist in den Befehl integriert \nquestion. Dabei \arabic{questioncount}wird durch ersetzt \thequestioncount. Für \setcountersind \expandedund \noexpandnicht erforderlich.

Nach wird \SetCellein &hinzugefügt, da bei der Verwendung \SetCellausgelassene Zellen nicht entfernt werden dürfen.

Bildbeschreibung hier eingeben

\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

Bildbeschreibung hier eingeben

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.

  1. Sie benötigen die LaTeX2e-Zähler nicht, verwenden Sie das intModul.
  2. Wenn Sie Werte speichern möchten, denken Sie an csname.
  3. Erstellen Sie eine Reihe von Befehlen \Q1und \Qnspeichern Sie den Wert, denn \Q1-markswenn Sie möchten, können Sie \Q1-questionauch 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.

Ausgabe

\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}

verwandte Informationen