使用tabularray宏包时,如何以合并单元格为基准设定填充色

发布于 2022-10-24 23:26:01

我想要让美国城市的那两行填充蓝色,日本的城市是白色,俄罗斯又是蓝色。即想以国家那一列的单元格为标准来判定行数奇偶,这样就能自动给单元格填间隔的背景色了。

用的是Windows10,安装的发行版是TEXlive2022,使用的编辑器是vscord,使用的编译命令是xelatex。

\documentclass[]{ctexbook}

\usepackage{tabularray}
\UseTblrLibrary{booktabs}
\usepackage[]{xcolor}

\begin{document}
{\small
\begin{longtblr}[
    caption = {国家与城市}
]{
    width = \textwidth,
    colspec = {X[1,l,h]  X[1,l,h]  X[3,l,h]},
    rowhead = 1, rowfoot = 0, % 每个分页里表头表尾的数量
    row{even} = {azure9},
}
    
    \toprule
    \textbf{城市} & \textbf{国家} & \textbf{性质}\\
    \midrule

    华盛顿 & \SetCell[r=2]{h}美国 & 首都\\
    洛杉矶 &  & a\\
    东京 & 日本 & 首都\\
    莫斯科 & 俄罗斯 & 首都\\
    \bottomrule

\end{longtblr}
}
\end{document}

image.png

查看更多

关注者
0
被浏览
2.5k
4 个回答
行者
行者 2022-10-25
这家伙很懒,什么也没写!

如果不限定 tabularray 宏包,nicematrix 宏包的 rowcolors 命令也许可以实现,请自行测试:

Snipaste_2022-10-25_00-04-15.png

Snipaste_2022-10-25_00-04-37.png

Beatrice
Beatrice 2022-10-25
这家伙很懒,什么也没写!

多看看文档,做到“真”样式和内容分离。

\documentclass{ctexbook}
\usepackage{xcolor}
\usepackage{tabularray}
\begin{document}
\SetTblrStyle{caption}{font=\small}
\begin{longtblr}[caption={国家与城市}]
{
width=\textwidth,
colspec={X[1,l,h]X[1,l,h]X[3,l,h]},
rows={font=\small},
row{1}={font=\small\bfseries},
rowhead=1,
rowfoot=0,
hline{2}={.05em},
hline{1,Z}={.08em},
row{even}={azure9},
}
城市             & 国家   & 性质      \\
{华盛顿\\洛杉矶} & 美国   & {首都\\a} \\
东京             & 日本   & 首都      \\
莫斯科           & 俄罗斯 & 首都      \\
{华盛顿\\洛杉矶} & 美国   & {首都\\a} \\
东京             & 日本   & 首都      \\
莫斯科           & 俄罗斯 & 首都      \\
\end{longtblr}
\end{document}

QQ截图20221025084052.png

拿了橘子跑啊
拿了橘子跑啊 2022-10-26
这家伙很懒,什么也没写!

可以换一个思路,用 csvsimple 结合 tabularray 来完成这个任务。本来你这种长表格就不会自己手动敲入内容,更多是从文件读取,不妨在 csv 文件里加一列指定相应颜色。代码示例如下:

\documentclass{ctexart}
\begin{filecontents*}{temp.csv}
cellcolor,city,country,property
azure9,华盛顿,美国,首都
azure9,洛杉矶,美国,大城市
white,东京,日本,首都
azure9,莫斯科,俄罗斯,首都
\end{filecontents*}
\usepackage{tabularray}
\usepackage{csvsimple-l3}
\usepackage{xcolor}
\begin{document}
\begin{table}
  \caption{测试表}\label{tab:temp}
  \csvreader[
    head to column names,
    tabularray={
      colspec = {X[1,l,h]  X[1,l,h]  X[3,l,h]},
      hline{1,Z}=1.2pt,
      hline{2}=0.8pt,
      cell{2}{2}={r=2}{m,l}
    },
    table head={\textbf{城市} & \textbf{国家} & \textbf{性质}\\}
  ]{temp.csv}{}{
    \SetRow{\cellcolor} 
    \city & \country & \property
  }
\end{table}
\end{document}

效果:
dbbc2314684e14c9926ea0b1bd581ef7.png

如果颜色那一列你想操作得简单一点,那么就用个简单字符,然后用 csvsimple 做判断,具体要看csvsimple 的手册。

我细看了你的例子,就这个例子而言,还需要用些权宜之计,主要问题在于:

  1. csvsimple 没有给 longtblr[<option>] 参数的接口,表格标题要自己处理。
  2. 单元格中含 , 字符,标准的 csv 是将单元格字符串用 "" 包裹,但 csvsimple 不支持,可能会导致列错误,因此要用其他不包含的字符作为分隔符,比如 |,但这样的 csv 在 Microsoft Excel 中修改处理就比较麻烦了。
  3. tipa 的音标字符通过 csvsimple 处理会出错,这里用了\newsavebox \sbox\usebox 处理(没去深究,权宜之计)。

这一段的代码如下:

\documentclass{ctexart}
\usepackage{tabularray}
\usepackage{csvsimple-l3}
\usepackage{xcolor}
\usepackage{tipa}
%%% 因为你这里用到了 comma 作为标点符号,如果是严格的 csv 将用 "" 包裹含 comma 的字符串
%%% 但 csvsimple 并不支持这样的用法,所以这里文件用 | 作为分隔符 
%%% 不过这样 Microsoft Excel 就不支持了。这些细节上的困难要自己去克服。 
\begin{filecontents*}{PfN.csv}
ccolor|Meaning|Prefixes|Example
azure9|{a half \\ $\frac{1}{2}$} |semi- |{semilunar valve 半月瓣\\  (lun/o: moon; -ar: pertaining to)}
azure9|                          |hemi- |{hemisphere \\ hemiplegia 半瘫\\  (-plegia/\usebox{\plegia}/: paralysis)}
white |{one,single \\ 1}         |mono- |{monocyte 单核细胞}
white |                          |uni-  |{unicellular 单细胞的}
azure9|{two \\ 2}                |bi-   |{bicuspid 二尖瓣的 \\  (cusp/i: point)}
azure9|                          |di-   |{dioxide 二氧化物 \\ diplegia 双侧瘫痪}
white |double                    |dipl/o|{diploid n.【生】二倍体;(结晶)偏方24面体 adj.二倍体的(含有两套染色体)}
azure9|{three \\ 3}              |tri-  |{triplet \\ triceps 三头肌 \\  (-ceps: head)}
white |{four \\ 4}               |quadr-|quadrant
white |                          |tetra-|tetracycline/\usebox{\tetracycline}/ 四环素
azure9|many                      |multi-|{multipara /\usebox{\multipara}/ 经产妇 \\  (-para: to bring forth to, bear)}
azure9|                          |poly- |polycystic kidney 多囊肾
\end{filecontents*}
%%% 有几个 tipa 字符好像没法通过 csvsimple 中处理,这里用了权宜之计
\newsavebox\plegia
\sbox\plegia{\textipa{"pli:\textdyoghlig I@}}
\newsavebox\multipara
\sbox\multipara{\textipa{m2l"tIp@r@}}
\newsavebox\tetracycline
\sbox\tetracycline{\textipa{""tetr@"saIklm}}

\begin{document}
%%% 由于 csvsimple 没有给 longtblr 的 option 参数的接口
%%% 长表格的标题要用这种黑科技处理一下,用完好像要恢复成 normal
\DefTblrTemplate{caption-text}{empty}{Prefixes for Numbers}
\SetTblrTemplate{caption-text}{empty}
%%% 下面使用 csvsimple
\csvreader[
  head to column names,
  separator=pipe,
  long tabularray={
    colspec = {X[1,l,h]  X[1,l,h]  X[3,l,h]},
    rowhead = 1, rowfoot = 0,
    column{2}={font=\bfseries},
    hline{1,Z}=1.2pt,
    hline{2}=0.8pt,
    cell{2,4,6,10,12}{1,1,1,1,1}={r=2}{m,l}
  },
  table head={\textbf{Meaning} & \textbf{Prefixes} & \textbf{Example}\\}
]{PfN.csv}{}{
  \SetRow{\ccolor} 
  {\Meaning} & \Prefixes & {\Example}
}
%%% 恢复
\SetTblrTemplate{caption-text}{normal}
\end{document}

效果:
image.png

M
M 2022-10-26
这家伙很懒,什么也没写!

如果只是要按某一列内各行合并单元格后的情况来交替颜色,思路是可以写一小段逻辑来控制新的行索引,这样就能根据这个新的索引来交替行的颜色。

tabularray提供了inner key process接口,可以通过\UseTblrLibrary{functional}提供的类l3风格函数,构造出符合要求的 hook。

tabularray中,SetCell会设置合并行的首个原始单元格的rowspan属性为xx视合并的行数而定。如果能够拿到这个值,就可以确定每一组的边界,再重新定义行索引就很容易了。

不过tabularray并没有直接暴露获取rowspan数据的接口,目前只提供了获取单元格内容的接口cellGetText。当然也可以选择魔改tabularray,仿照cellGetText添一个cellGetSpan

这里选择一个讨巧的方法,在确定某一列为key的情况下,一般来说,合并的单元格中,首个原始的单元格必定不是空,剩下的一定是空,这样就可以区分出哪些是被合并的行,只需要将这些行的新索引默认与首行的索引相同即可。

\documentclass[]{ctexbook}

\usepackage{tabularray}
\UseTblrLibrary{booktabs}
\UseTblrLibrary{functional}
\usepackage[]{xcolor}
\usepackage[]{amsmath}
\usepackage[]{tipa}

\begin{document}

\IgnoreSpacesOn

\prgNewFunction \groupByCol { m } {
  \intZero \lTmpaInt
  \intStepOneInline {2} {\arabic{rowcount}} {% ignore head
    \tlSet \lTmpaTl {\cellGetText {##1} {#1}}
    \tlVarIfEmptyF \lTmpaTl
      { \intIncr \lTmpaInt }
    \intCompareT {\intMathMod {\lTmpaInt-1} {2}} = {0}
      { \rowSetStyle {##1} {bg=azure9} }
  }
}

\IgnoreSpacesOff

{\small
\begin{longtblr}[
  caption = {国家与城市}
]{
  width = \textwidth,
  colspec = {X[1,l,h]  X[1,l,h]  X[3,l,h]},
  rowhead = 1, rowfoot = 0, % 每个分页里表头表尾的数量
  process = \groupByCol{2}
}
  
  \toprule
  \textbf{城市} & \textbf{国家} & \textbf{性质}\\
  \midrule

  华盛顿 & \SetCell[r=2]{h}美国 & 首都\\
  洛杉矶 &  & a\\
  东京 & 日本 & 首都\\
  莫斯科 & 俄罗斯 & 首都\\
  \bottomrule

\end{longtblr}

\begin{longtblr}[
    caption = {Prefixes for Numbers},
]{
    width = \textwidth,
    colspec = {X[1,c,h]  X[1,l,h]  X[3,l,h]},
    rowhead = 1, rowfoot = 0, % 每个分页里表头表尾的数量
    % row{even} = {azure9},
    process = \groupByCol{1},
}
    
    \toprule
    \textbf{Meaning} & \textbf{Prefixes} & \textbf{example} \\ \midrule
    \SetCell[r=2]{c} {a half \\ $\frac{1}{2}$} & \textbf{semi-} & {semilunar valve 半月瓣\\ \hspace*{1em}(lun/o: moon; -ar: pertaining to)}\\
    & \textbf{hemi-} & {hemisphere \\ hemiplegia 半瘫\\ \hspace*{1em}(-plegia/\textipa{"pli:\textdyoghlig I@}/: paralysis)}\\

    \SetCell[r=2]{c} {one, single \\ 1} & \textbf{mono-} & monocyte 单核细胞\\
    & \textbf{uni-} & unicellular 单细胞的\\

    \SetCell[r=2]{c} {two \\ 2} & \textbf{bi-} & {bicuspid 二尖瓣的 \\ \hspace*{1em}(cusp/i: point)}\\
    & \textbf{di-} & {dioxide 二氧化物 \\ diplegia 双侧瘫痪}\\

    double & \textbf{dipl/o} & diploid n.【生】二倍体;(结晶)偏方24面体
    adj.二倍体的(含有两套染色体)\\

    {three \\ 3} & \textbf{tri-} & {triplet \\ triceps 三头肌 \\ \hspace*{1em}(-ceps: head)}\\

    \SetCell[r=2]{c} {four \\ 4} & \textbf{quadr-} & quadrant\\
    & \textbf{tetra-} & tetracycline/\textipa{""tetr@"saIklm}/ 四环素\\

    \SetCell[r=2]{c} many & \textbf{multi-} & {multipara/\textipa{m2l"tIp@r@}/ 经产妇 \\ \hspace*{1em}(-para: to bring forth, to bear)}\\
    & \textbf{poly-} & polycystic kidney 多囊肾\\
    \bottomrule

\end{longtblr}
}
\end{document}

效果:
88a38abd3e6b7b6afa6d56c47a7a33ec.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览