是否有一个参数或方法可以知道有多少已声明tabular
给定或有多少个列array
?
我需要第一次使用后才知道\\
主要目标是让表格的每个单元格的每个角上都有一个标记,我实际上知道该怎么做。但为此,我使用了一个以列数为参数的命令。我更喜欢自动获得此参数。
\documentclass{article}
\usepackage{array,xparse}
\NewDocumentEnvironment{TikzTable}{md<>O{c}m}{%
\IfNoValueTF{#2}{%
\begin{#1}[#3]{#4}}{%
\begin{#1}{#2}[#3]{#4}}
}{\end{#1}}
\begin{document}
\begin{TikzTable}{tabular}[b]{clrm{3cm}}\hline
a&b&c& 4 columns \\% At this point
\hline
1&1&1&1\\
\end{TikzTable}bob
\end{document}
答案1
您可以计算生成的前导码&
中的\halign
\documentclass{article}
\usepackage{array,xparse}
\NewDocumentEnvironment{TikzTable}{md<>O{c}m}{%
\IfNoValueTF{#2}{%
\begin{#1}[#3]{#4}}{%
\begin{#1}{#2}[#3]{#4}}
}{\end{#1}}
\makeatletter
\def\zzz#1#2{%
\ifx\zzz#3#1\expandafter\@gobble\else
\expandafter\@firstofone
\fi
{\zzz{\the\numexpr#1+1\relax}#3}}
\def\zz{\noalign{%
\xdef\nocols{\expandafter\zzz\expandafter1\@preamble&\zzz}%
}}
\makeatother
\begin{document}
\begin{TikzTable}{tabular}[b]{clrm{3cm}}
\zz
\hline
a&b&c& \nocols\ columns \\% At this point
\hline
1&1&1&1\\
\end{TikzTable}bob
\end{document}
答案2
使用与 David 相同的想法,但使用更精美的expl3
代码;这使得它\nocols
可以在每个TikzTable
环境中使用,但如果您需要嵌套这些表,则可以在尾随可选参数中自定义名称。
\documentclass{article}
\usepackage{array,xparse}
\NewDocumentEnvironment{TikzTable}{md<>O{c}mO{\nocols}}
{%
\IfNoValueTF{#2}
{%
\begin{#1}[#3]{#4}
}{%
\begin{#1}{#2}[#3]{#4}
}%
\noalign{\CountColumns{#5}}
}
{\end{#1}}
\ExplSyntaxOn
\NewDocumentCommand{\CountColumns}{m}
{% count the number of & tokens in \@preamble
\regex_count:nvN { \cT\& } { @preamble } \l_tmpa_int
% they're one less than the columns
\cs_gset:Npx #1 { \int_eval:n { 1 + \l_tmpa_int } }
}
\cs_generate_variant:Nn \regex_count:nnN { nv }
\ExplSyntaxOff
\begin{document}
\begin{TikzTable}{tabular}[b]{clrm{3cm}}
\hline
a&b&c& This table has \nocols\ columns \\
\hline
1&1&1&1\\
\end{TikzTable}bob
\begin{TikzTable}{tabular}[b]{clrm{3cm}}[\foo]
\hline
a&b&c& This table has \foo\ columns \\
\hline
1&1&1&1\\
\end{TikzTable}bob
\end{document}
答案3
这是一个基于 LuaLaTeX 的解决方案。它可以处理tabular
、array
、tabular*
、tabularx
和tabulary
环境,以及TikzTable
您在帖子中提出的环境。
最近遇到的tabular
类环境的声明列数存储在名为 的 Lua 变量中num_cols
。(请注意,无需手动执行任何操作即可获取每个tabular
类环境的声明列数 - 计算完全自动完成。)要从 LaTeX 端访问此数字,代码提供了名为 的 LaTeX 宏\numcols
。
唯一的输入要求是所有\begin{tabular}...{<columnspec>}
材料必须位于同一条线上。
请注意,代码设计用于处理诸如\begin{tabular} {@{} c >{$}c<{$} >{\raggedleft\arraybackslash\tt}p{1cm} @{}} \\
列数为“3”的情况。解决方案还可以处理更复杂的列定义,例如*{6}{l}
。
% !TEX TS-program = lualatex
\documentclass{article}
%% next few lines from the OP's query
\usepackage{array,xparse}
\NewDocumentEnvironment{TikzTable}{md<>O{c}m}{%
\IfNoValueTF{#2}{%
\begin{#1}[#3]{#4}}{%
\begin{#1}{#2}[#3]{#4}}}{%
\end{#1}}
\usepackage{tabularx,tabulary}
\usepackage{luacode} % for 'luacode' environment
\begin{luacode}
-- Define a global variable (num_cols), set up two
-- Lua functions, and assign one of them to the
-- 'process_input_buffer' callback.
-- Initialize counter variable
num_cols = 0
-- The next function computes the number of columns from
-- contents of string 'zz'
function calc_nums ( zz )
-- retain the first "{....}" substring
zz = zz:gsub ( "^.-(%b{}).-$", "%1" )
-- remove outermost pair of curly braces
zz = zz:sub ( 2 , -2 )
-- expand expressions such as "*{5}{l}" to "lllll"
zz = zz:gsub ( "%*%s-{(%d-)}%s-(%b{})" ,
function ( y , z )
z = z:sub ( 2 , -2 )
return string.rep ( z , y )
end )
-- omit all stuff in curly braces
zz = zz:gsub ( "%b{}" , "" )
-- some more characters to ignore
zz = zz:gsub ( "[@!|><%s%*]" , "" )
-- Number of remaining chars in "zz" is the number
-- of columns in the tabular-like environment.
num_cols = string.len ( zz )
end
-- Next the main Lua function. Scan all input lines.
-- If we detect start of a tabular-like env., lop off
-- the prefix and pass the remainder of the input line
-- to the 'calc_nums' function to determine number of cols.
-- ("%s-" means "0 or more instances of whitespace")
function get_col_spec ( s )
local zz
if string.find ( s , "\\begin.-{tabular}" ) then
zz = s:gsub ( "^.-\\begin.-{tabular}" , "" )
calc_nums ( zz )
elseif string.find ( s , "\\begin%s-{array}" ) then
zz = s:gsub ( "^.-\\begin%s-{array}" , "" )
calc_nums ( zz )
elseif string.find ( s , "\\begin%s-{tabular.}" ) then
zz = s:gsub ( "^.-\\begin%s-{tabular.}%s-%b{}" , "" )
calc_nums ( zz )
end
-- Do nothing if no match occurred.
end
-- Finally, assign 'get_col_spec' to the LuaTeX
-- 'process_input_buffer' callback.
luatexbase.add_to_callback( "process_input_buffer",
get_col_spec, "get_cols" )
\end{luacode}
%% LaTeX-side code: a macro to print out the number of columns
\newcommand\numcols{\directlua{tex.sprint(num_cols)}}
\begin{document}
%% Example 1
\begin{tabular} [b] { | * {6} { m{4mm }|} p { 12mm }|} \multicolumn{3}{@{}l}{\numcols\ columns}
\\ \hline a & b & c & d & e & f & g \\ \hline
\end{tabular}
\bigskip
%% Example 2
\begin{tabular} {@{} c *{2}{>{$}c<{$}} >{\raggedleft\arraybackslash\tt}p{3cm} @{}}
\hline
a & b & c & \numcols\ columns\\
\hline
\end{tabular}
\bigskip
%% Example 3: the 'TikzTable' case
aaa\begin{TikzTable}{tabular}[b]{@{}cllrm{1.55cm}@{}}\hline
a&b&c&d& \numcols\ columns \\
\hline
1&1&1&1&1\\
\hline
\end{TikzTable}zzz
\bigskip
%% Examples 4 to 6: array, tabular*, and tabularx
$\begin{array}{@{}*{6}{c}@{}} \hline a & b & c & d & e & \numcols \\ \hline \end{array}$
\bigskip
\begin{tabular*}{0.5\textwidth}{@{\extracolsep{\fill}}*{7}{l}@{}} \hline
z & y & x & w & v & u & \numcols\\ \hline
\end{tabular*}
\bigskip
\begin{tabularx}{0.7\textwidth}{@{}l*{8}{>{\centering\arraybackslash}X}r@{}} \hline
z & y & x & w & v & u & t & s & r & \numcols\\ \hline
\end{tabularx}
\end{document}