对于我正在开展的项目,我想编写一个包装器宏\fancyTable
,它在后台进行通信pgfplotstable
。用户应该能够将列对齐指定为逗号分隔的列表,并指定包含表数据的文件的路径。额外的复杂之处在于数据通常是任意字符串;它可以是时间戳、句子的一部分或数字。在当前测试阶段,包装器宏如下所示:
\fancyTable[r,c,c,l]{FILEPATH}
当前的设计要求是它必须适用于任意数量的列(因此无法针对特定情况进行硬编码)。但是,我为程序分配所做的所有尝试column style
均未奏效(甚至更糟的是,每次编译都会导致不同的故障)。
由于我已经尝试了很多可能性,我决定给出一个完整的概述。我剩下的未解决的问题在最后部分问题。因此请随意滚动到末尾。
初始点
目前,我设法对表进行硬编码。
\documentclass{scrreprt} % standalone or minimal do not work well with longtable
\usepackage{pgfplotstable}
\usepackage{longtable}
\usepackage{colortbl}
\usepackage{booktabs}
\begin{document}
\begin{filecontents}{pgfplotstable_proc-column-style_example.csv}
date, time, time zone, event
2019/01/01, 00:00, CET, server installation finished
2019/01/01, 00:05, CET, server successfully booted
2019/01/01, 00:06, CET, starting xyz daemon
2019/01/01, 00:10, CET, admin login
2019/12/31, 23:58, CET, sudo reboot
2019/12/31, 23:59, CET, server reboot
\end{filecontents}
\pgfplotstabletypeset[
begin table=\begin{longtable},%
end table=\end{longtable},%
header=false,% no specific header data
col sep=comma,%
every head row/.style={%
output empty row,% prevent printing of column numbers
},%
every odd row/.style={before row={\rowcolor[gray]{0.9}}},% highlighting of every second data row
every first row/.append style={after row={\midrule}},% horizontal line after header
string type,% necessary for correct processing of table content
columns/0/.style={column type=r},%
columns/3/.style={column type=l},%
% modified from: https://tex.stackexchange.com/questions/130835/pgfplotstable-one-row-in-bold
postproc cell content/.append code={% setting first row bold
\count0=\pgfplotstablerow %
\advance\count0 by1 %
\ifnum\count0=1 %
\pgfkeysalso{@cell content=\textbf{#1}}%
\fi %
},
]{pgfplotstable_proc-column-style_example.csv}
\end{document}
但是,列对齐是固定的:
columns/0/.style={column type=r},%
columns/3/.style={column type=l},%
如果输入数据发生变化,就会导致问题。
尝试 1:pgfplotstable
宏
我的第一个想法是使用 已经提供的宏pgfplotstable
,但我只能用 打印与列相关的内容\pgfplotstableforeachcolumn
。接下来,我尝试用 创建一个 for 循环\pgfplotsforeachungrouped
,但也失败了。就我对pgf
和的有限理解而言pgfplotstable
,它要么不起作用,因为我无法正确访问表数据,要么宏不是为执行我试图要求它执行的操作而设计的。
尝试 2:\foreach
使用\protected@xappto
我的另一个想法是创建一个包含辅助宏中的对齐信息的字符串\columnAlign
,并将宏的内容插入到中。对于原型设计,我使用了与\pgfplotstabletypeset[\columnAlign]{FILENAME}
相结合的 hack 方法,过去我曾使用这种方法成功创建了表格内容。当然,这行不通;所以不会编译...\foreach
\protected@xappto
MWE
\documentclass{minimal}
\usepackage{pgfplotstable}
\usepackage{etoolbox}
\begin{document}
\begin{filecontents}{pgfplotstable_proc-column-style_example.csv}
date,time,time zone, event
2019/01/01, 00:00, CET, server installation finished
2019/01/01, 00:05, CET, server successfully booted
2019/01/01, 00:06, CET, starting xyz daemon
2019/01/01, 00:10, CET, admin login
2019/12/31, 23:58, CET, sudo reboot
2019/12/31, 23:59, CET, server reboot
\end{filecontents}
\pgfplotstableread[header=false,col sep=comma]{pgfplotstable_proc-column-style_example.csv}\loadedtable
\def\columnAlign{}% define empty helper macro
\makeatletter
\foreach \col in {0,1} {% iterate over all columns in \loadedtable
\protected@xappto\columnAlign{% append column style definition
columns/\col/.style=\{column type=l\},
}%
}%
\makeatother
\pgfplotstabletypeset[
every head row/.style={%
output empty row,%
},%
string type,%
\columnAlign
]\loadedtable
\end{document}
转义字符(如 )存在许多问题, = { }
,我无法修复。我尝试了\csname ... \endcsname
、\expandafter
等。
尝试 3:(\input{}
不要尝试!)
从一开始,我就确信这一定会破裂pgfplotstable
;但如果你不尝试,你就无法确定……
我的想法是,我可能可以加载一个外部生成的 tex 文件,该文件pgfplotstable
能够加载而不会\csname
出现扩展问题。或者,这可能是一种通过 生成管道的方法\input{|"PIPE CONTENT"}
。
和预期的一样,调用编译\pgfplotstable[\input{FILE1}]{FILE2}
不正确。编译冻结/循环,甚至没有生成错误消息。
尝试 4:自定义列样式和./list
尝试 4 与尝试 2 非常相似。但是,它试图利用pgfplotstable
可以在输出表域中定义自定义列样式的功能,并可以对其进行迭代。
\pgfplotstableset{%
left column/.style={%
/pgfplots/table/display columns/#1/.style={column type=l}%
},%
center column/.style={%
/pgfplots/table/display columns/#1/.style={column type=c}%
},%
right column/.style={%
/pgfplots/table/display columns/#1/.style={column type=r}%
},%
}%
如果调用样式,例如left column/.list={LIST}
,则样式将应用于中提供的所有列索引LIST
。
样式也接受宏作为输入。这样就可以使用 生成多个“宏数组” \protected@xappto
,其中包含应应用样式的列的索引。如果没有列应应用某种样式,则相应的“样式宏数组”将为空。
作为原型,我手动创建了宏。
\def\cCenter{0,1,2}
\def\cLeft{3}
\def\cRight{}
\pgfplotstabletypeset[
left column/.list={\cLeft}, %
center column/.list={\cCenter}, %
right column/.list={\cRight}, %
]{FILE}
只要“宏数组”不为空,它就会编译。如果“数组”为空,则编译停止。使用 if-case 仅包含应应用的列样式也不起作用。这使得无法从程序上影响列对齐。
问题:
- 我是否错过了一个
pgfplotstable
可以让我做我想做的事情的宏? - 有没有其他语法方法
expl3
? - 或者,在最坏的情况下,是否根本无法
pgfplotstable
实现我的目标?如果是这样,是否有其他方法可以从文件中解析表格(例如使用datatool
),从而提供类似的功能pgfplotstable
(尤其是preproc cell content
,postproc cell content
将来我的项目将需要它)?
答案1
另一种解决方案是catchfile
和tabularray
基于我的包回答另一个问题:
\documentclass{scrreprt}
%% % used to make page size smaller and therewith facilitate page break testing
%\usepackage[
% paperheight=7.5cm, paperwidth=13cm,
% left=0.5cm, right=0.5cm, top=0.25cm,
% bottom=0.25cm, includeheadfoot
%]{geometry}
\usepackage{xcolor}
\usepackage{catchfile}
\usepackage{tabularray}
\ExplSyntaxOn
\group_begin:
\catcode`\^^M=\active %
\cs_gset_protected:Npn \NormalizeData #1 {%
\regex_replace_once:nnN { \s * \r ? $ } {} #1
\tl_greplace_all:Nnn #1 {^^M} {\\}%
\tl_greplace_all:Nnn #1 {,} {&}%
}%
\group_end:
\ExplSyntaxOff
\newcommand{\fancyTable}[2][]{
\CatchFileDef{\mydata}{#2}{\catcode`\^^M=\active}
\NormalizeData{\mydata}
\begin{longtblr}[
expand = \mydata,
caption = {The Caption of the Table},
]{
colspec = {#1},
hline{1,Z} = {0.08em},
hline{2} = {0.05em},
row{even} = {gray9},
row{1} = {font=\bfseries},
rowhead = 1,
}
\mydata
\end{longtblr}
}
\begin{document}
\begin{filecontents*}{628719.csv}
date, time, time zone, event
2019/01/01, 00:00, CET, server installation finished
2019/01/01, 00:05, CET, server successfully booted
2019/01/01, 00:06, CET, starting xyz daemon
2019/01/01, 00:10, CET, admin login
2019/12/31, 23:58, CET, sudo reboot
2019/12/31, 23:59, CET, server reboot
\end{filecontents*}
%\fancyTable[r]{628719.csv} % specify only the first column
\fancyTable[rc]{628719.csv} % specify only the first two columns
%\fancyTable[rcc]{628719.csv} % specify only the first three columns
\fancyTable[rccl]{628719.csv} % specify all of the four columns
\end{document}