宏在 foreach 循环中不起作用

宏在 foreach 循环中不起作用

我正在尝试根据作为参数传递的边界,用不同的颜色为几列中的单元格着色。我想要一个接受两个参数的宏:一个.csv文件和一个逗号分隔的列表,以正斜杠 ( ) 为子分隔符/。第二个参数的每个元素将有两个值:一个列索引和一个边界。

我希望宏能够.csv根据列索引和提供的边界,通过第二个参数循环构建表格,为列中的单元格着色。

例如:该参数1/0.2, 2/0.5将使第 1 列中 0.2 以上的单元格和第 2 列中 0.5 以上的单元格变为蓝色,其他单元格变为橙色。我几乎明白了。我有处理第二个参数并创建颜色列表的 lua 代码。

我的问题是:为什么它不会为下面结构中的单元格着色?

我知道有更好的方法来完成下面具体的 MWE,比如将事物从循环中取出,但我需要那里的循环,因为我希望将多个列表传递到的第二个参数中\buildTable,然后将其传递给我的 lua 代码,创建并将列表传递给\ColorColumn

我的想法是:有一个循环遍历每组列索引和边界并将其传递给 lua,然后将生成的列表传递给\ColorColumn

所以我们不必担心 lua,我已经在下面以生成的格式包含了一个颜色列表的示例。

我怀疑这只是一个扩展问题,但我不确定。

梅威瑟:

\documentclass{article}
\RequirePackage{etoolbox}
\RequirePackage{pgfplotstable}
\RequirePackage{colortbl}
\RequirePackage{pgfplots}
\RequirePackage{xparse}
\RequirePackage{listofitems}

\begin{filecontents*}{test.csv}
    ColA, ColB, ColC
    0.17, 0.91, 0.67
    0.15, 0.17, 0.92
    0.48, 0.1, 0.28
\end{filecontents*}

\def\assigncolor#1#2{%
    \pgfplotstableset{
        every row \thecount\space column #2/.style={
            postproc cell content/.style={
            @cell content/.add={\cellcolor{#1}}{}%
            },%
        },
    }%
}%

\newcounter{count}%
\def\ColorColumn#1#2{%
    \def\ArgOne{#1}%
    \ifdef{\thecount}{}{\newcounter{count}}%
    \readlist*\mylist{#2}% star option removes surrounding whitespace
    \setcounter{count}{-1}%
    \foreachitem\x\in\mylist[]{%
        \stepcounter{count}%
        \expandafter\assigncolor\expandafter{\x}{\ArgOne}%
    }%
}%

\def\buildTable#1#2{%
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \def\selection{}%
    \edef\tempor{%
        columns = {\selection},%
    }%
    \expandafter\xappto\expandafter\parser\expandafter{\tempor}%    
    \foreach \x/\y in {#2}{
        \ColorColumn{\x}{blue, blue, orange}
    }%
    \xdef\theTable{\noexpand\pgfplotstabletypeset[\parser]}%
    \theTable{\rawdata}%
}%

\begin{document}
\begin{table}
    \buildTable
    {%CSV file
        test.csv%
    }
    {%
        1/0.1%
    }%
\end{table}
\end{document}

答案1

我不确定我是否理解了你实际上想要做什么。但是\foreach你应该使用而不是 。而且在任何地方\pgfplotsforeachungrouped使用时都应该小心一点。宏或循环内部的 并不会自动局限于此宏。\x\x

\documentclass{article}
\RequirePackage{etoolbox}
\RequirePackage{pgfplotstable}
\RequirePackage{colortbl}
\RequirePackage{pgfplots}
\RequirePackage{xparse}
\RequirePackage{listofitems}

\begin{filecontents*}{testnew.csv}
    ColA, ColB, ColC
    0.17, 0.91, 0.67
    0.15, 0.17, 0.92
    0.48, 0.1,  0.28
\end{filecontents*}

\def\assigncolor#1#2{%
    \pgfplotstableset{
        every row \thecount\space column #2/.style={
            postproc cell content/.style={
            @cell content/.add={\cellcolor{#1}}{}%
            },%
        },
    }%
}%

\newcounter{count}%
\def\ColorColumn#1#2{%
    \edef\ArgOne{#1}% <----------changed 
    \ifdef{\thecount}{}{\newcounter{count}}%
    \readlist*\mylist{#2}% star option removes surrounding whitespace
    \setcounter{count}{-1}%
    \foreachitem\x\in\mylist[]{%
        \stepcounter{count}%
        \expandafter\assigncolor\expandafter{\x}{\ArgOne}%
    }%
}%

\def\buildTable#1#2{%
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \def\selection{}%
    \edef\tempor{%
        columns = {\selection},%
    }%
    \expandafter\xappto\expandafter\parser\expandafter{\tempor}%
    \pgfplotsforeachungrouped \x/\y in {#2}{
        \ColorColumn{\x}{blue, blue, orange}
    }%
    \xdef\theTable{\noexpand\pgfplotstabletypeset[\parser]}%
    \theTable{\rawdata}%
}%

\begin{document}
\begin{table}
    \buildTable
    {%CSV file
        testnew.csv%
    }
    {%
        1/0.1%
    }%
\end{table}
\end{document}

在此处输入图片描述

答案2

下面是一个使用 的实现expl3。表格行按顺序存储,然后每个项目再次拆分以构建表格主体。

可以为单个表决定特殊列,也可以在开始时设置

\settable{column=2}

对任意数量的列进行处理并不是很困难。

代码如下:

\begin{filecontents*}{\jobname.csv}
ColA, ColB, ColC
0.17, 0.91, 0.67
0.15, 0.17, 0.92
0.48, 0.1, 0.28
\end{filecontents*}

\documentclass{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{xparse}

\ExplSyntaxOn
\ior_new:N \g_kevin_table_readfile_stream
\tl_new:N \l__kevin_table_body_tl
\seq_new:N \l__kevin_table_rows_seq
\seq_new:N \l__kevin_table_singlerow_seq

\keys_define:nn { kevin/table }
 {
  column       .int_set:N = \l__kevin_table_column_int,
  upper-bound  .fp_set:N  = \l__kevin_table_upper_fp,
  lower-bound  .fp_set:N  = \l__kevin_table_lower_fp,
  upper-color  .tl_set:N  = \l__kevin_table_upper_tl,
  lower-color  .tl_set:N  = \l__kevin_table_lower_tl,
  normal-color .tl_set:N  = \l__kevin_table_normal_tl,
 }

\NewDocumentCommand{\settable}{m}
 {
  \kevin_table_set:n { #1 }
 }

\NewDocumentCommand{\buildtable}{O{}m}
 {
  % #1 = options
  % #2 = file name
  \group_begin:
  \settable{#1}
  \kevin_table_build:n { #2 }
  \group_end:
 }

\cs_new_protected:Nn \kevin_table_set:n
 {
  \keys_set:nn { kevin/table } { #1 }
 }

\cs_new_protected:Nn \kevin_table_build:n
 {
  \tl_clear:N \l__kevin_table_body_tl
  \seq_clear:N \l__kevin_table_rows_seq
  \ior_open:Nn \g_kevin_table_readfile_stream { #1 }
  \ior_map_inline:Nn \g_kevin_table_readfile_stream
   {
    \seq_put_right:Nn \l__kevin_table_rows_seq { ##1 }
   }
  % get the number of columns and the header row
  \seq_set_from_clist:Nx \l__kevin_table_singlerow_seq
   {
    \seq_item:Nn \l__kevin_table_rows_seq { 1 }
   }
  \tl_put_right:Nx \l__kevin_table_body_tl
   {
    \seq_use:Nn \l__kevin_table_singlerow_seq { & } \exp_not:N \\
   }
  % process each row
  \int_step_function:nnnN { 2 } { 1 } { \seq_count:N \l__kevin_table_rows_seq } \__kevin_table_process_row:n
  % build the table
  \begin{tabular}{*{100}{c}}
  \tl_use:N \l__kevin_table_body_tl
  \end{tabular}
}
\cs_generate_variant:Nn \seq_set_from_clist:Nn { Nx }

\cs_new_protected:Nn \__kevin_table_process_row:n
 {
  \seq_set_from_clist:Nx \l__kevin_table_singlerow_seq
   {
    \seq_item:Nn \l__kevin_table_rows_seq { #1 }
   }
  \int_step_inline:nnnn { 1 } { 1 } { \seq_count:N \l__kevin_table_singlerow_seq }
   {
    \tl_put_right:Nx \l__kevin_table_body_tl
     {
      \int_compare:nF { ##1 = 1 } { & }
      \int_compare:nT { ##1 = \l__kevin_table_column_int }
       {
        \__kevin_table_addcolor:n { \seq_item:Nn \l__kevin_table_singlerow_seq { ##1 } }
       }
      \seq_item:Nn \l__kevin_table_singlerow_seq { ##1 }
     }
   }
  \tl_put_right:Nn \l__kevin_table_body_tl { \\ }
 }

\cs_new_protected:Nn \__kevin_table_addcolor:n
 {
  \fp_compare:nTF { #1 >= \l__kevin_table_upper_fp }
   { \cellcolor{\l__kevin_table_upper_tl} }
   {
    \fp_compare:nTF { #1 <= \l__kevin_table_lower_fp }
     { \cellcolor{\l__kevin_table_lower_tl} }
     { \cellcolor{\l__kevin_table_normal_tl} }
   }
 }
\ExplSyntaxOff

\settable{upper-color=red,lower-color=blue,normal-color=orange}

\begin{document}

\buildtable[column=2,upper-bound=1,lower-bound=0.1]{\jobname.csv}

\bigskip

\buildtable[column=2,upper-bound=0.5,lower-bound=0.1]{\jobname.csv}


\end{document}

在此处输入图片描述

一个不同的版本,您可以在其中根据需要对任意数量的列进行着色。

\begin{filecontents*}{\jobname.csv}
ColA, ColB, ColC
0.17, 0.91, 0.67
0.15, 0.17, 0.92
0.48, 0.1, 0.28
\end{filecontents*}

\documentclass{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{xparse}

\ExplSyntaxOn
\ior_new:N \g_kevin_table_readfile_stream
\tl_new:N \l__kevin_table_body_tl
\seq_new:N \l__kevin_table_rows_seq
\seq_new:N \l__kevin_table_singlerow_seq

\keys_define:nn { kevin/table }
 {
  column       .clist_set:N = \l__kevin_table_column_clist,
  upper-bound  .fp_set:N    = \l__kevin_table_upper_fp,
  lower-bound  .fp_set:N    = \l__kevin_table_lower_fp,
  upper-color  .tl_set:N    = \l__kevin_table_upper_tl,
  lower-color  .tl_set:N    = \l__kevin_table_lower_tl,
  normal-color .tl_set:N    = \l__kevin_table_normal_tl,
 }

\NewDocumentCommand{\settable}{m}
 {
  \kevin_table_set:n { #1 }
 }

\NewDocumentCommand{\buildtable}{O{}m}
 {
  % #1 = options
  % #2 = file name
  \group_begin:
  \settable{#1}
  \kevin_table_build:n { #2 }
  \group_end:
 }

\cs_new_protected:Nn \kevin_table_set:n
 {
  \keys_set:nn { kevin/table } { #1 }
 }

\cs_new_protected:Nn \kevin_table_build:n
 {
  \tl_clear:N \l__kevin_table_body_tl
  \seq_clear:N \l__kevin_table_rows_seq
  \ior_open:Nn \g_kevin_table_readfile_stream { #1 }
  \ior_map_inline:Nn \g_kevin_table_readfile_stream
   {
    \seq_put_right:Nn \l__kevin_table_rows_seq { ##1 }
   }
  % get the number of columns and the header row
  \seq_set_from_clist:Nx \l__kevin_table_singlerow_seq
   {
    \seq_item:Nn \l__kevin_table_rows_seq { 1 }
   }
  \tl_put_right:Nx \l__kevin_table_body_tl
   {
    \seq_use:Nn \l__kevin_table_singlerow_seq { & } \exp_not:N \\
   }
  % process each row
  \int_step_function:nnnN { 2 } { 1 } { \seq_count:N \l__kevin_table_rows_seq } \__kevin_table_process_row:n
  % build the table
  \begin{tabular}{*{100}{c}}
  \tl_use:N \l__kevin_table_body_tl
  \end{tabular}
}
\cs_generate_variant:Nn \seq_set_from_clist:Nn { Nx }

\cs_new_protected:Nn \__kevin_table_process_row:n
 {
  \seq_set_from_clist:Nx \l__kevin_table_singlerow_seq
   {
    \seq_item:Nn \l__kevin_table_rows_seq { #1 }
   }
  \int_step_inline:nnnn { 1 } { 1 } { \seq_count:N \l__kevin_table_singlerow_seq }
   {
    \int_compare:nF { ##1 = 1 } { \tl_put_right:Nn \l__kevin_table_body_tl { & } }
    \clist_if_in:NnT \l__kevin_table_column_clist { ##1 }
     {
      \tl_put_right:Nx \l__kevin_table_body_tl
       {
        \__kevin_table_addcolor:n { \seq_item:Nn \l__kevin_table_singlerow_seq { ##1 } }
       }
     }
    \tl_put_right:Nx \l__kevin_table_body_tl
     {
      \seq_item:Nn \l__kevin_table_singlerow_seq { ##1 }
     }
   }
  \tl_put_right:Nn \l__kevin_table_body_tl { \\ }
 }

\cs_new_protected:Nn \__kevin_table_addcolor:n
 {
  \fp_compare:nTF { #1 >= \l__kevin_table_upper_fp }
   { \cellcolor{\l__kevin_table_upper_tl} }
   {
    \fp_compare:nTF { #1 <= \l__kevin_table_lower_fp }
     { \cellcolor{\l__kevin_table_lower_tl} }
     { \cellcolor{\l__kevin_table_normal_tl} }
   }
 }
\ExplSyntaxOff

\settable{upper-color=red,lower-color=blue,normal-color=orange}

\begin{document}

\buildtable[column=2,upper-bound=1,lower-bound=0.1]{\jobname.csv}

\bigskip

\buildtable[column={2,3},upper-bound=0.5,lower-bound=0.1]{\jobname.csv}


\bigskip

\buildtable[column={1,3},upper-bound=0.5,lower-bound=0.1]{\jobname.csv}


\end{document}

在此处输入图片描述

相关内容