我正在尝试根据作为参数传递的边界,用不同的颜色为几列中的单元格着色。我想要一个接受两个参数的宏:一个.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}