tabularx 环境中自己的计数器从 3 开始

tabularx 环境中自己的计数器从 3 开始

以下示例显示环境中的自定义计数器tabularx不以“1”开头。无法弄清楚如何定义命令以始终以“1”开头。有什么想法吗?

\documentclass{article}

\usepackage{enumitem}
\usepackage{cleveref}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}

\makeatletter\newcommand*{%
\CreateCounterIfNotExists}[1]{\begingroup%
\@ifundefined{c@#1}{\newcounter{#1}}{}%
\endgroup}\makeatother

\def\sdef#1{\expandafter\def\csname#1\endcsname}
\newcommand\requirement[3]{%
\CreateCounterIfNotExists{my#1}%
\sdef{themy#1}{#1\arabic{my#1}}%
\refstepcounter{my#1}%
\label{#2} #1\arabic{my#1}: #3%
}

\begin{document}
\requirement{A}{req:foo:a}{Starts with 1}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\begin{tabularx}{\textwidth}{lX}
    \caption{Requirements}\\
    \label{tbl:reqs}\\
    \toprule
    \textbf{Area}& \textbf{Description}  \\\midrule
    \requirement{C}{req:bar:A}{Starts with 3}
    \requirement{C}{req:bar:B}{Continues with 4}
       & 
    This should start with C1    \\\midrule
\end{tabularx}
\end{document}

答案1

您不能在计数器tabularx执行其工作时定义它。

解决方案可能是预先定义您需要的那个tabularx,或者使用文件以延迟方式执行.aux

\documentclass{article}

\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}
\usepackage{cleveref}

\makeatletter
\newcommand\requirement[3]{%
  \protected@write\@auxout{}{\string\CreateCounter{#1}}%
  \@ifundefined{c@my#1}
    {#1??: #3}
    {\refstepcounter{my#1}\label{#2}#1\arabic{my#1}: #3}%
}
\newcommand{\CreateCounter}[1]{%
  \@ifundefined{c@my#1}
    {\newcounter{my#1}\global\@namedef{themy#1}{#1\arabic{my#1}}}
    {}%
}
\AtEndDocument{\let\CreateCounter\@gobble}
\makeatother

\begin{document}
{\requirement{A}{req:foo:a}{Starts with 1}}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}

\noindent
\begin{tabularx}{\textwidth}{lX}
\caption{Requirements}\label{tbl:reqs}\\
\toprule
\textbf{Area}& \textbf{Description}  \\
\midrule
\requirement{C}{req:bar:A}{Starts with 1}
\requirement{C}{req:bar:B}{Continues with 2} & This should start with C1 \\
\midrule
\end{tabularx}

\end{document}

在此处输入图片描述

第一次\requirement{X}使用时不会生成数字,但下次运行 LaTeX 时会生成数字。

答案2

您几乎永远不应该在宏中声明计数器,它应该在序言中声明一次并仅使用。然后tabularx在进行试验宽度设置时了解它并保留其值。

\documentclass{article}

\usepackage{enumitem}
\usepackage{cleveref}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}

\newcounter{myA}\renewcommand\themyA{A\arabic{myA}}
\newcounter{myB}\renewcommand\themyB{B\arabic{myB}}
\newcounter{myC}\renewcommand\themyC{C\arabic{myC}}



\newcommand\requirement[3]{%
\refstepcounter{my#1}%
\label{#2}#1\arabic{my#1}: #3%
}

\begin{document}
\requirement{A}{req:foo:a}{Starts with 1}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\begin{tabularx}{\textwidth}{lX}
    \caption{Requirements}\\
    \label{tbl:reqs}\\
    \toprule
    \textbf{Area}& \textbf{Description}  \\\midrule
    \requirement{C}{req:bar:A}{Starts with 3}
    \requirement{C}{req:bar:B}{Continues with 4}
       & 
    This should start with C1    \\\midrule
\end{tabularx}
\end{document}

答案3

正如 David Carlisle 和 egreg 的解决方案中提到的那样:不应定义计数器on-the-fly

我使用了与 David Carlisle 类似的方法,提供了仅可在序言中使用的\NewDocumentCounter、、\DeclareRequirement命令,以防止意外使用。DeclareRequirements

\documentclass{article}

\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}
\usepackage{cleveref}

\usepackage{xparse}

\NewDocumentCommand{\NewDocumentCounter}{m}{%
  \ifltxcounter{#1}{%
  }{%
    \typeout{Creating counter #1}
    \newcounter{#1}%
  } 
}

\NewDocumentCommand{\DeclareRequirement}{m}{%
  \NewDocumentCounter{my#1}%
  \expandafter\renewcommand\csname themy#1\endcsname{#1\arabic{my#1}}
}%

    \listgadd\reqlist{}


\NewDocumentCommand{\DeclareRequirements}{+m}{%
  \forcsvlist{\listgadd\reqlist}{#1}
  \forlistloop{\DeclareRequirement}{\reqlist}
}%



\makeatletter
\@onlypreamble{\NewDocumentCounter}
\@onlypreamble{\DeclareRequirement}
\@onlypreamble{\DeclareRequirements}
\makeatother




\DeclareRequirements{A,B,C} % Declare all requirement counters in a row ... 


\newcommand\requirement[3]{%
  \refstepcounter{my#1}%
  \label{#2} #1\arabic{my#1}: #3%
}

\begin{document}
\requirement{A}{req:foo:a}{Starts with 1}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\begin{tabularx}{\textwidth}{lX}
    \caption{Requirements}\\
    \label{tbl:reqs}\\
    \toprule
    \textbf{Area}& \textbf{Description}  \\\midrule
    \requirement{C}{req:bar:A}{Starts with 3 no longer} %\themyC
    \requirement{C}{req:bar:B}{Continues with 4 no longer} %\themyC
    & 
    This should start with C1    \\\midrule
  \end{tabularx}
\end{document}

相关内容