在同一标签中存储多个数据 - expl3 属性列表

在同一标签中存储多个数据 - expl3 属性列表

根据问题如何自动生成汇总表?,我重写了 MWE:

\documentclass{article}
\usepackage{nameref}
\usepackage{booktabs}
\usepackage{xparse}
\ExplSyntaxOn
\prop_new:N \g__leonardo_impact_prop
\prop_new:N \g__leonardo_counter_prop
\makeatletter
\NewDocumentCommand \DeclareImpact { m +m +m }
  {
    \@bsphack
      \prop_gput:Nnn \g__leonardo_impact_prop {#1} {#2}
      \prop_gput:Nnn \g__leonardo_counter_prop {#1} {#3}
    \@esphack
  }
\makeatother
\NewExpandableDocumentCommand \impact { O{Not~applicable} m }
  {
    \prop_if_in:NnTF \g__leonardo_impact_prop {#2}
      { \prop_item:Nn \g__leonardo_impact_prop {#2} }
      { \exp_not:n {#1} }
  }
\NewExpandableDocumentCommand \countermeasure { O{Not~applicable} m }
  {
    \prop_if_in:NnTF \g__leonardo_counter_prop {#2}
      { \prop_item:Nn \g__leonardo_counter_prop {#2} }
      { \exp_not:n {#1} }
  }
%
\NewExpandableDocumentCommand \TableBody { m }
  { \clist_map_function:nN {#1} \__leonardo_table_row:n }
\NewDocumentCommand \SetRowFormat { m }
  { \cs_gset:Npn \__leonardo_table_row:n ##1 {#1} }
\cs_new_eq:NN \StrLowerCase \str_lowercase:n
\ExplSyntaxOff

\begin{document}

\section{Impacts on the Environment}
\subsection{Air quality}
\label{sec:air}
Analyses of air quality.
\DeclareImpact{Air}{Wood burning}{Sleeve filter installation}

\textbf{Impact}: \impact{Air}

\textbf{Countermeasure}: \countermeasure{Air}

\subsection{Water resources}
\label{sec:water}
Analyses of water resources.

\DeclareImpact{Water}{low pervious surface rate}{rain water harvesting}
\DeclareImpact{Water}{alkaline waste water}{ph correction water treatment process}

\textbf{Impact}: \impact{Water}


\textbf{Countermeasure}: \countermeasure{Water}


\section{Conclusion}
A succinct conclusion. See Table \ref{tab:sumary}.

% Set table row format:
\SetRowFormat
  {%
    \nameref{sec:\StrLowerCase{#1}}
  & \impact[--]{#1}
  & \countermeasure[--]{#1} \\
  }

\begin{table}[htb!]
  \centering
  \caption{Summary of impacts and countermeasures}
  \label{tab:sumary}
  \begin{tabular}{lll}
    \toprule
      \textbf{Analyse} & \textbf{Impact} & \textbf{Countermeasure}\\
    \midrule
        \TableBody{Air, Water}
    \bottomrule
  \end{tabular}
\end{table}

\end{document}

是否可以将多个影响和对策存储在同一个标​​签下以获得这样的结果?

在此处输入图片描述

答案1

这个比较棘手。。。我重写了代码,以便它与以前的版本向后兼容。功能大致相同:

您使用 声明了一个新的影响/对策对\DeclareImpact{<id>}{<impact>}{<counter>}。如果您\DeclareImpact再次使用相同的<id>,则影响/对策对将附加到该列表中。允许任意多个项目。您可以<id>使用清除\ClearImpact{<id>}

命令\impact\countermeasure具有相同的语法。我对其中一个命令所说的一切都适用于另一个命令。使用时\impact[<empty-text>](<item-list>){<id>}有两种可能性:

  1. 如果<id>从未使用 声明\DeclareImpact或使用 清除\ClearImpact,则<empty-text>返回。该参数<empty-text>是可选的,默认值为“不适用”。
  1. 如果<id>包含单个影响(IE\DeclareImpact{<id>}只使用了一次),然后使用中的代码进行打印\SetPrintSingle(稍后会详细介绍)。

  2. 如果给出了参数<item-list>,则仅打印编号在中的项目<item-list>(项目按顺序编号,从 1 开始,因为它们是使用 放置的\DeclareImpact)。如果<item-list>没有给出,则按顺序打印所有项目。无论哪种方式,都会使用 中的代码打印项目\SetPrintList

处理完列表后,项目将传递给由两个模板函数\SetPrintSingle(即Print Single,不是Pringles:-) 和定义的代码\SetPrintList。要定义模板,请使用\SetPrintSingle{<code-with-#1>}(其中#1是影响文本)和\SetPrintList{<code-with-#1-and-#2>}(其中#1是项目编号,是影响文本)。使用模板函数设置表格行格式的#2方式相同,其中每个逗号分隔的项目都传递给。\SetRowFormat{<code-with-#1>}#1\TableBody

说得够多了。输出看起来和你要求的非常相似:

在此处输入图片描述

代码如下:

\documentclass{article}
\usepackage{nameref}
\usepackage{booktabs}
\usepackage[margin=4cm]{geometry}
\usepackage{tabularx}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Npn \leonardo_declare_property:Nn #1 #2
  {
    \seq_if_exist:NF #1 { \seq_new:N #1 }
    \seq_gput_right:Nn #1 {#2}
  }
\cs_generate_variant:Nn \leonardo_declare_property:Nn { c }
\cs_new:Npn \leonardo_get_property:Nnn #1 #2 #3
  {
    \bool_lazy_or:nnTF
      { ! \seq_if_exist_p:N #1 }
      { \seq_if_empty_p:N #1 }
      { \exp_not:n {#2} }
      { \__leonardo_get_property:Nn #1 {#3} }
  }
\cs_generate_variant:Nn \leonardo_get_property:Nnn { c }
\cs_new:Npn \__leonardo_get_property:Nn #1 #2
  {
    \tl_if_novalue:nTF {#2}
      {
        \int_compare:nNnTF { \seq_count:N #1 } = { 1 }
          { \__leonardo_print_property:f { \seq_item:Nn #1 { 1 } } }
          { \seq_indexed_map_function:NN #1 \__leonardo_print_property:nn }
      }
      { \__leonardo_seq_filtered_map_tokens:Nnn #1 {#2} { \__leonardo_print_property:nn } }
  }
\cs_new_eq:NN \__leonardo_print_property:n \use:n
\cs_new_eq:NN \__leonardo_print_property:nn \use_ii:nn
\cs_generate_variant:Nn \__leonardo_print_property:n { f }
\cs_new:Npn \__leonardo_seq_filtered_map_tokens:Nnn #1#2#3
  {
    \exp_last_unbraced:Nno
      \use_i:nn { \__leonardo_map_tokens:nnnw { 1 } {#2} {#3} } #1
    \prg_break: \__seq_item:n { } \prg_break_point:
    \prg_break_point:Nn \seq_map_break: { }
  }
\cs_new:Npn \__leonardo_map_tokens:nnnw #1 #2#3 #4 \__seq_item:n #5
  {
    #4
    \afp_int_ismember:nnT {#1} {#2} { \use:n {#3} {#1} {#5} }
    \exp_args:Nf \__leonardo_map_tokens:nnnw { \int_eval:n {#1+1} } {#2} {#3}
  }
% List membership code: https://tex.stackexchange.com/a/501777/134574
\cs_new:Npn \__afp_ismember_loop:Nnw #1#2#3,
  {
    \quark_if_recursion_tail_stop_do:nn {#3} { \prg_return_false: }
    #1 {#2} {#3}
      { \use_i_delimit_by_q_recursion_stop:nw { \prg_return_true: } }
      { \__afp_ismember_loop:Nnw #1 {#2} }
  }
\prg_new_conditional:Npnn \__afp_int_isequal:nn #1#2 { p, T, F, TF }
  { \int_compare:nNnTF {#1} = {#2} { \prg_return_true: } { \prg_return_false: } }
\prg_new_conditional:Npnn \afp_int_ismember:nn #1#2 { p, T, F, TF }
  { \__afp_ismember_loop:Nnw \__afp_int_isequal:nnTF {#1} #2 , \q_recursion_tail , \q_recursion_stop }
% User interfaces
\makeatletter
\NewDocumentCommand \DeclareImpact { m +m +m }
  {
    \@bsphack
      \leonardo_declare_property:cn { g__leonardo_#1_impact_seq } {#2}
      \leonardo_declare_property:cn { g__leonardo_#1_counter_seq } {#3}
    \@esphack
  }
\NewDocumentCommand \ClearImpact { m }
  {
    \seq_gclear:c { g__leonardo_#1_impact_seq }
    \seq_gclear:c { g__leonardo_#1_counter_seq }
  }
\makeatother
\NewExpandableDocumentCommand \impact { O{Not~applicable} d() m }
  { \leonardo_get_property:cnn { g__leonardo_#3_impact_seq } {#1} {#2} }
\NewExpandableDocumentCommand \countermeasure { O{Not~applicable} d() m }
  { \leonardo_get_property:cnn { g__leonardo_#3_counter_seq } {#1} {#2} }
\NewExpandableDocumentCommand \TableBody { m }
  { \clist_map_function:nN {#1} \__leonardo_table_row:n }
\NewDocumentCommand \SetRowFormat { +m }
  { \cs_gset:Npn \__leonardo_table_row:n ##1 {#1} }
\NewDocumentCommand \SetPrintSingle { +m }
  { \cs_gset:Npn \__leonardo_print_property:n ##1 {#1} }
\NewDocumentCommand \SetPrintList { +m }
  { \cs_gset:Npn \__leonardo_print_property:nn ##1 ##2 {#1} }
\cs_new_eq:NN \StrLowerCase \str_lowercase:n
\ExplSyntaxOff

现在来看看文档。请注意,我使用了\SetPrintList两次;一次是在文本中打印列表(我使用tabularx, 来匹配您想要的输出),另一次是在摘要表中打印文本。摘要表特别棘手,因为模板:

\SetRowFormat
  {%
    \nameref{sec:\StrLowerCase{#1}}
  & \impact[--]{#1}
  & \countermeasure[--]{#1} \\
  }

印刷全部存储在 中的影响#1,然后是所有对策。如果<id>#1恰好有多个,\impact那么您需要为每个影响创建一个新的表格行,并且当您转到下一列打印 时\countermeasure,表格会向下几行,您无法返回。为了解决这个问题,我将模板更改为:

\SetRowFormat
  {%
    \nameref{sec:\StrLowerCase{#1}}
  & \parbox[t]{\hsize}{\impact[--]{#1}}
  & \parbox[t]{\hsize}{\countermeasure[--]{#1}} \\
  }

将所有 排版\impact为单个\parbox,使它们全部进入同一表格行,然后相同进入\countermeasure。此设置依赖于tabularx的值发生变化\hsize,因此您需要加载它。

这里是:

\begin{document}

% Setting templates:

% Single-item impact/countermeasure: Just print the item
\SetPrintSingle{#1}

% Multi-item impact/countermeasure:
% Shift to the next table cell, print “<number>. <description>”, and shift to the next row
\SetPrintList{& #1.~#2\\}

\section{Impacts on the Environment}
\subsection{Air quality}
\label{sec:air}
Analyses of air quality.
\DeclareImpact{Air}{Wood burning}{Sleeve filter installation}

\textbf{Impact}: \impact{Air}

\textbf{Countermeasure}: \countermeasure{Air}

\subsection{Water resources}
\label{sec:water}
Analyses of water resources.

\DeclareImpact{Water}{low pervious surface rate}{rain water harvesting}
\DeclareImpact{Water}{alkaline waste water}{ph correction water treatment process}

\noindent
\begin{tabularx}{\textwidth}{lX}
  \textbf{Impact}: \impact{Water}
\end{tabularx}

\noindent
\begin{tabularx}{\textwidth}{lX}
  \textbf{Countermeasure}: \countermeasure{Water}
\end{tabularx}

\section{Conclusion}
A succinct conclusion. See Table \ref{tab:sumary}.

% Set table row format:
\SetRowFormat
  {%
    \nameref{sec:\StrLowerCase{#1}}
  & \parbox[t]{\hsize}{\impact[--]{#1}}
  & \parbox[t]{\hsize}{\countermeasure[--]{#1}} \\
  }

% Reset multi-item impact/countermeasure:
% Just print <description>, and break the paragraph: we're in a \parbox here
\SetPrintList{#2\par}

\begin{table}[htb!]
  \centering
  \caption{Summary of impacts and countermeasures}
  \label{tab:sumary}
  \begin{tabularx}{\textwidth}{l>{\hsize=.4\hsize}X>{\hsize=.6\hsize}X}
    \toprule
      \textbf{Analyse} & \textbf{Impact} & \textbf{Countermeasure}\\
    \midrule
        \TableBody{Air, Water}
    \bottomrule
  \end{tabularx}
\end{table}

\end{document}

相关内容