再会,
我正在为考试班制作一个自定义评分表。具体来说,我想删除第一列并在末尾添加一个新列。看来,创建一个新的表格才是最佳选择。
在搜索 stackexchange 后我发现这个问题,它会修改\part
环境并将每个问题部分及其分数写入辅助文件,然后将它们放入表中。除了分数的显示方式外,我可以根据自己的喜好进行更改。建议的解决方案默认使用问题部分,而我只想查看每个问题的总数。因此,问题是计算每个的总数\question
。
我当前的代码(主要是@Andrew 提出的代码)如下:
% redefine \question command to be \myquest
\appto\questions{\let\examquestion\question\let\question\myquestion}
% redefine \part command to be \mypart
\appto\parts{\let\exampart\part\let\part\mypart}
\makeatletter
\ExplSyntaxOn
% this will become a sequence of the part numbers and scores
% like: 1a,10,1b,8,1c,9,2a,6,2b,8,3,12,4,14, ...
\clist_new:N \g_grades_clist
\clist_new:N \g_grades_aux_clist
\int_new:N \g_questions_row_int
\int_new:N \g_scores_row_int
\int_new:N \g_spaces_row_int
\int_new:N \g_grade_total_int
\int_new:N \g_number_of_scores_int
\int_new:N \g_total_questions
% add a question/part number and score to \g_grades_clist
\cs_new:Nn \__add_to_grades_list:nn {
\clist_gput_right:Nx \g_grades_clist { #1 }
\clist_gput_right:Nx \g_grades_clist { #2 }
}
\NewDocumentCommand\myquestion{o}{
\IfNoValueTF{#1}{\examquestion}{
% don't do anything special inside solutions
\if@insolution\examquestion[#1]
\else\examquestion[#1]
% store both the part number and score in \g_grades_clist
\__add_to_grades_list:nn { Auf.~\arabic{question} } { #1 }
\fi
}
}
\NewDocumentCommand\mypart{o}{
\IfNoValueTF{#1}{\exampart}{
% don't do anything special inside solutions
\if@insolution\exampnrt[#1]
\else\exampart[#1]
% store both the part number and score in \g_grades_clist
\__add_to_grades_list:nn { Auf.~\arabic{question}\alph{partno} } { #1 }
\fi
}
}
\AtEndDocument{
\iow_now:cx { @auxout } {
\token_to_str:N \SetGradeList { \g_grades_clist } ^^J
}
}
% set grade list from the aux file
\NewDocumentCommand\SetGradeList{m}{\clist_gset:Nn \g_grades_aux_clist {#1}}
% Draw quesions
\cs_new:Nn \__add_questions_to_grade_table: {
\int_gincr:N \g_questions_row_int
\clist_item:Nn \g_grades_aux_clist {2*\g_questions_row_int-1} \int_compare:nT {\g_questions_row_int < (\g_number_of_scores_int)} { & \__add_questions_to_grade_table: }
}
% Draw scores
\cs_new:Nn \__add_scores_to_grade_table: {
\int_gincr:N \g_scores_row_int
\clist_item:Nn \g_grades_aux_clist {2*\g_scores_row_int} \int_compare:nT {\g_scores_row_int < \g_number_of_scores_int} { & \__add_scores_to_grade_table: }
}
% Draw empty spaces
\cs_new:Nn \__add_spaces_to_grade_table: {
\int_gincr:N \g_spaces_row_int
\int_compare:nT {\g_spaces_row_int < \g_number_of_scores_int} { & \__add_spaces_to_grade_table: }
}
\NewDocumentCommand\PrintGradeTable{}{% the new grade table
\int_set:Nn \g_number_of_scores_int {(\clist_count:N \g_grades_aux_clist)/2}
\int_gzero:N \g_questions_row_int % a counter to step through the rows
\int_gzero:N \g_scores_row_int % a counter to step through the rows
\int_gzero:N \g_spaces_row_int % a counter to step through the rows
% create the grade table
\renewcommand{\arraystretch}{2}
\begin{tabular}{|c|*{\int_eval:n {(\clist_count:N \g_grades_aux_clist)/2-1}}{c|}c}
\hline
\int_compare:nT {\g_number_of_scores_int>0} { \__add_questions_to_grade_table: } & \multicolumn{1}{l|}{\hphantom{A}~\large\textbf{Note}~\hphantom{A}} \\
\hline
\int_compare:nT {\g_number_of_scores_int>0} { \__add_scores_to_grade_table: } & \\
\hline
\int_compare:nT {\g_number_of_scores_int>0} { \__add_spaces_to_grade_table: } & \multicolumn{1}{l|}{} \\
\hline
\end{tabular}
}
\ExplSyntaxOff
考试中的每个练习都采用以下格式:
\question
\begin{parts}
\part
\end{parts}
因此每个问题总是由多个部分组成的。
计算各部分总数的最简单的方法是什么?
答案1
我最终修改了内置的表函数。如果有人需要做同样的事情,我引入了一个较短版本的 emptycols 迭代器,它少创建一个单元格,并将所有循环更改为在主要部分后添加 & 符号,因此它们不会在它们之前留下一个空单元格,而是在它们之后留下一个。这样,它就不是包含所有名称或为空的第一列,而是最后一列。
全部改变的代码如下:
\def\do@lines@h{%
% Called only by \@multirowtable.
% It's either bonus or regular, but not combined:
\addtocounter{current@row}{1}% Set to the number of the current row
\setcounter{cols@done}{0}%
\do@pq@indexloop@h
% When we finish \do@pq@indexloop@h, either we've finished a
% complete row of page numbers (or questions), or we've done all
% the page numbers (or questions) through \last@pq@index, or both:
\ifnum \value{cols@done} < \value{num@cols}\relax
% We've inserted all the page or question numbers, and there's
% room remaining on the current line for \@htword (or \@bhtword):
\ifnum \value{current@row} = \value{num@rows}\relax
% This is the last row; put in the total:
\do@note
\else
% This isn't the last row. We insert (\value{num@cols} -
% \value{cols@done}) ampersands.
\setcounter{@iterator}{\value{num@cols}}%
\addtocounter{@iterator}{-\value{cols@done}}%
\do@emptycols@h
\fi
\fi
\\
\hline
% Point values go here!
\setcounter{cols@done}{0}%
\if@bonus
\do@bptloop@h
\else
\do@ptloop@h
\fi
% When we finish \do@ptloop@h or \do@bptloop@h, either
% we've finished a complete row of point values, or we've done all
% the question (or page) numbers through \last@pq@index, or both:
\ifnum \value{cols@done} < \value{num@cols}\relax
% We've inserted all the point values, and there's room
% remaining on the current line for Total Points:
\ifnum \value{current@row} = \value{num@rows}\relax
% This is the last row; put in the total:
\if@bonus
\do@totalbpts@h
\else
\do@totalpts@h
\fi
\else
% This isn't the last row. We insert (\value{num@cols} -
% \value{cols@done}) ampersands.
\setcounter{@iterator}{\value{num@cols}}%
\addtocounter{@iterator}{-\value{cols@done}}%
\do@emptycols@h
\fi
\fi
% We hold off on putting in the "\\ \hline" because we may want to
% immediately follow it with either an "\end{tabular}" or another
% "\hline".
% Scores?
\if@scores
\\
\hline
\if@bonus
\hidden@ampersand
\else
\hidden@ampersand
\fi
\setcounter{cols@done}{0}%
\do@sloop@h
\fi
\ifnum \value{current@row} = \value{num@rows}\relax
% This is the last line! End the tabular:
\\
\hline
\end{tabular}%
\else
% Don't end the tabular:
\\
\hline\hline
\fi
% Check if we should repeat:
\ifnum \value{current@row} < \value{num@rows}\relax
\let\nextdo@lines@h=\do@lines@h
\else
\let\nextdo@lines@h=\relax
\fi
\nextdo@lines@h
}% do@lines@h
\def\do@pq@indexloop@h{%
% Called by both \do@lines@h and \do@comblines@h.
% We insert at most one row of pq@index:
\increment@index{pq@index}%
\ifnum \value{pq@index} > \last@pq@index\relax
% Do nothing!
\else
Aufg. \refto@index{pq@index}%
\hidden@ampersand
\addtocounter{cols@done}{1}%
\fi
\ifnum \value{pq@index} < \last@pq@index\relax
\ifnum \value{cols@done} < \value{num@cols}\relax
\let\nextdo@pq@indexloop@h=\do@pq@indexloop@h
\else
\let\nextdo@pq@indexloop@h=\relax
\fi
\else
\let\nextdo@pq@indexloop@h=\relax
\fi
\nextdo@pq@indexloop@h
}% do@pq@indexloop@h
\def\do@ptloop@h{%
% Called by both \do@lines@h and \do@comblines@h.
% We insert at most one row of non-bonus point values:
\increment@index{pq@index@pts}%
\ifnum \value{pq@index@pts} > \last@pq@index\relax
% Do nothing!
\else
\addtocounter{cols@done}{1}%
\pointsof@index{pq@index@pts}%
\hidden@ampersand
\addto@hlfcntr{tbl@points}{\pointsof@index{pq@index@pts}}%
\fi
\ifnum \value{pq@index@pts} < \last@pq@index\relax
\ifnum \value{cols@done} < \value{num@cols}\relax
\let\nextdo@ptloop@h=\do@ptloop@h
\else
\let\nextdo@ptloop@h=\relax
\fi
\else
\let\nextdo@ptloop@h=\relax
\fi
\nextdo@ptloop@h
}% do@ptloop@h
\def\do@note{%
% Called by both \do@lines@h and \do@comblines@h.
% We insert (\value{num@cols} - \value{cols@done}) ampersands,
% and then either \@htword or \@bhtword or \@chtword:
\setcounter{@iterator}{\value{num@cols}}%
\addtocounter{@iterator}{-\value{cols@done}}%
\do@shortemptycols@h
\if@combined
Gesamt \hidden@ampersand \textbf{Note}
\else
\if@bonus
Gesamt \hidden@ampersand \textbf{Note}
\else
Gesamt \hidden@ampersand \textbf{Note}
\fi
\fi
}% do@note
\def\do@totalpts@h{%
% Called by both \do@lines@h and \do@comblines@h.
% We insert (\value{num@cols} - \value{cols@done}) ampersands
% and then the total points:
\setcounter{@iterator}{\value{num@cols}}%
\addtocounter{@iterator}{-\value{cols@done}}%
\do@shortemptycols@h
\prt@tablepoints
}% do@totalpts@h
\def\do@shortemptycols@h{%
% Called by \do@lines@h, \do@comblines@h, \do@note,
% \do@totalpts@h, and \do@totalbpts@h.
% We insert \value{@iterator} ampersands:
\ifnum \value{@iterator} > 1\relax
\hidden@ampersand
\addtocounter{@iterator}{-1}%
\let\nextdo@emptycols@h=\do@emptycols@h
\else
\let\nextdo@emptycols@h=\relax
\fi
\nextdo@emptycols@h
}% do@emptycols@h
所有文本部分都是硬编码的,因为在我的特定情况下不需要变化,但可以很容易地用变量替换。