将自定义命令应用于条件数据工具定义的宏

将自定义命令应用于条件数据工具定义的宏

这在某种程度上是对上一个问题的扩展:用于在逗号分隔的列表中应用自定义命令的宏

我正在用 LaTex 创建花园日志。我有一个 .csv 植物数据库文件(数据库-1.csv) 我使用数据工具包中的条件为花园的每个区域创建子集表,效果非常好。

我想在我的每个表中索引从数据库中提取的植物。我目前正在使用 makeidx 包。这样,我的最终索引将包括提及特定植物的位置,即使该提及出现在表中而不是直接出现在文本中。

我怎样才能使我的应用宏对我的数据工具条件 (\theback) 的结果起作用?

这是我的 MWE:

\documentclass[12pt]{book} 
\usepackage{datatool}
\usepackage{colortbl}
%necessary to color a table

\definecolor{lightmauve}{rgb}{0.86, 0.82, 1.0}

\usepackage{makeidx} % Required to make an index
\makeindex % Tells LaTeX to create the files required for indexing



% This command is for applying a single command to a comma-separated list of tokens, and listing the results separated by ", " (I removed the ``,'').
\makeatletter
\newcommand{\apply}[3][]{
% #1: optional separator to print between applications; default=[, ]
% #2: command to apply; 
% #3: list to apply command to 
  \def\itemsep{\def\itemsep{#1}} % first call to \itemsep prints nothing; later calls print #1
  \def\zz{\itemsep#2}%
  \@for \listelement:=#3\do{\expandafter\zz\expandafter{\listelement}}%
}
\makeatother

%%%%%%%%%%%%%%%%%%%


\DTLloaddb{dbsample}{db-1.csv}


\begin{document}

%First I'm creating my custom comma-separated list, the result of datatool conditions.  Can be called using \theback

\def\theback{\DTLforeach*[\DTLisSubString{\Location}{back}]{dbsample}%
{\Name=Name,\Variety=Variety,\Location=Location,\Established=Established}%
{\Name!\Variety, }}

\vspace{10mm}

%%% Now ideally I'd like to have 
%\apply{\index}{\theback} 
%to work in my table, but it does not.  This did not work, I may have to figure out how to set a macro (or definition?) within a macro???


%Next, this is my table.

\begin{table}[htbp] 
\caption{Plants that are pre-existing are highlighted in \colorbox{lightmauve}{lightmauve}} 
\vspace{5mm}
\centering 
\begin{tabular}{lllr} 
\bfseries Name & 
\bfseries Variety&
\bfseries Location & 
\bfseries Established % 
\DTLforeach*[\DTLisSubString{\Location}{back}]{dbsample}%
{\Name=Name,\Variety=Variety,\Location=Location,\Established=Established}
{% 
\DTLifSubString{\Established}{yes}{\\\rowcolor{lightmauve}}{\\\rowcolor{white}}%
\Name & \Variety & \Location & \Established}
\end{tabular} 

\apply{\index}{Daffodil!apricot,St. John's Wort}
%the above will work, but what I'm hoping for is instead, something along the lines of:
%\apply{\index}{\theback}

\end{table}


\printindex % Output the index

\end{document}

抱歉,我不确定我指的东西是否具有正确的名称。任何建议或帮助都将不胜感激。非常感谢!

答案1

正如你在问题的答案中所看到的如何更改 LaTeX 中项目化的“items”之间的间距?\itemsep已经在 LaTeX 中定义。

如果您愿意,您可以将非分隔宏参数的交换与旧的\romannumeral-expansion 结合起来,以定义一个宏,该宏检查的顶层扩展\Variety是否为空,然后将索引条目所需的内容附加到逗号列表宏(称为) - 我试图在回答这个问题时\theback解释-expansion\romannumeral如何知道附加到 csname 宏时的 expandafter 数量?

在下面的例子中,我决定采用\xdef...{\unexpanded{...}}-route 来应对\unexpandedLaTeX 在每次宏扩展时将连续哈希值的数量减半的问题。把这当作一个没有实际意义的观点。;-)

\documentclass[12pt]{book} 
\usepackage{datatool}
\usepackage{colortbl}
%necessary to color a table

\definecolor{lightmauve}{rgb}{0.86, 0.82, 1.0}

\usepackage{makeidx} % Required to make an index
\makeindex % Tells LaTeX to create the files required for indexing

\makeatletter

%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \CheckWhetherNull{<Argument which is to be checked>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is empty>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is not empty>}%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Exchange two arguments:
%%.............................................................................
\newcommand\exchangeargs[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Append comma-delimited element to comma-list-macro holding index-entries:
%%.............................................................................
\newcommand\GlobalAppendIndexEntryToCommalist[5]{%
  % #1 = comma-list-macro where tokens/index-entries are to be appended
  % #2 = !
  % #3 = ,
  % #4 = \Name
  % #5 = \Variety
  \xdef#1{%
    \unexpanded\expandafter{%
      \romannumeral0%
      \expandafter\exchangeargs\expandafter{\expandafter{%
        \romannumeral0%
        \expandafter\CheckWhetherNull\expandafter{#5}{%
          \expandafter\exchangeargs\expandafter{#4}{ }%
        }{%
          \expandafter\exchangeargs\expandafter{#5}{%
            \exchangeargs{#2}{%
              \expandafter\exchangeargs\expandafter{#4}{ }%
            }%
          }%
        }%
      }}{%
        \expandafter\CheckWhetherNull\expandafter{#1}{ }{%
          \expandafter\exchangeargs\expandafter{#1#3}{ }%
        }%
      }%
    }%
  }%
}%

\newcommand*\theback{}%
\newcommand*\GlobalResettheback{\gdef\theback{}}%

% This macro applies a command to each element of a list of comma-separated arguments:
\newcommand{\apply}[2]{%
  % #1: command to apply; 
  % #2: (macro holding) list of comma-separated arguments;
  \@for\listelement:=#2\do{%
    \expandafter\exchangeargs\expandafter{\expandafter{\listelement}}{#1}%
  }%
}%

\makeatother

%%%%%%%%%%%%%%%%%%%

\DTLloaddb{dbsample}{db-1.csv}

\begin{document}

%This is my table.

\begin{table}[htbp]
\caption{Plants that are pre-existing are highlighted in \colorbox{lightmauve}{lightmauve}}
\vspace{5mm}%
\centering 
\GlobalResettheback
\begin{tabular}{lllr} 
\bfseries Name & 
\bfseries Variety&
\bfseries Location & 
\bfseries Established %
\DTLforeach*[\DTLisSubString{\Location}{back}]{dbsample}%
{\Name=Name,\Variety=Variety,\Location=Location,\Established=Established}
{%
  \DTLifSubString{\Established}{yes}{\\\rowcolor{lightmauve}}{\\\rowcolor{white}}%
  \Name & \Variety & \Location & \Established%
  \GlobalAppendIndexEntryToCommalist{\theback}{!}{,}{\Name}{\Variety}%
}%
\end{tabular} 
%
%\apply{\index}{Daffodil!apricot,St. John's Wort}
%\show\theback
\apply{\index}{\theback}
%
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
% Be aware: 
%
% If you decide to have tables not as floating objects but as part of the 
% main text and switch to tabularx for having multipage-tables, then 
% carrying out all \index-commands _after_ already having shipped all pages
% of the table may yield wrong page-numbers with index-entries of things
% that do not occur on the last page of the table but do occur on pages
% prior to that last page.
%
% That's why below I added a suggestion where index-entries are produced
% and \index-commands are carried out at the time of producing the
% table-rows via \DTLforeach*.
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
%
\end{table}

\printindex % Output the index

\end{document}

可能您不需要维护这样的逗号列表宏,但可以让 LaTeX\DTLforeach*直接从循环中构建索引条目:

\documentclass[12pt]{book} 
\usepackage{datatool}
\usepackage{colortbl}
%necessary to color a table

\definecolor{lightmauve}{rgb}{0.86, 0.82, 1.0}

\usepackage{makeidx} % Required to make an index
\makeindex % Tells LaTeX to create the files required for indexing

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \CheckWhetherNull{<Argument which is to be checked>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is empty>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is not empty>}%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Exchange two arguments:
%%.............................................................................
\newcommand\exchangeargs[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Construct index-entry from \Name and \Variety
%%.............................................................................
\newcommand\ConstructIndexentry[4]{%
  % #1 = indexing-command, usually \index
  % #2 = !
  % #3 = \Name
  % #4 = \Variety
  \expandafter\exchangeargs\expandafter{\expandafter{%
    \romannumeral0%
    \expandafter\CheckWhetherNull\expandafter{#4}{%
      \expandafter\exchangeargs\expandafter{#3}{ }%
    }{%
      \expandafter\exchangeargs\expandafter{#4}{%
        \exchangeargs{#2}{%
          \expandafter\exchangeargs\expandafter{#3}{ }%
        }%
      }%
    }%
  }}{#1}%
}%
\makeatother

\DTLloaddb{dbsample}{db-1.csv}

\begin{document}

%This is the table.

\begin{table}[htbp]
\caption{Plants that are pre-existing are highlighted in \colorbox{lightmauve}{lightmauve}}
\vspace{5mm}%
\centering 
\begin{tabular}{lllr} 
\bfseries Name & 
\bfseries Variety&
\bfseries Location & 
\bfseries Established %
\DTLforeach*[\DTLisSubString{\Location}{back}]{dbsample}%
{\Name=Name,\Variety=Variety,\Location=Location,\Established=Established}
{%
  \DTLifSubString{\Established}{yes}{\\\rowcolor{lightmauve}}{\\\rowcolor{white}}%
  \Name & \Variety & \Location & \Established%
  \ConstructIndexentry{\index}{!}{\Name}{\Variety}%
}%
\end{tabular} 
\end{table}

\printindex % Output the index

\end{document}

相关内容