我正在尝试实现这样的目标:
\newcommand{\test}[2]{#1 & :={#2} € & :={[-2,0] * [-1,0]} € \\}
\begin{spreadtab}{{tabularx}{\textwidth}{|X|r|r|}}
@ Col 1 & @ Col 2 & @ Col 3 \\
\hline
\test{2}{50}
\test{3}{100}
\hline
\multicolumn{2}{|r|}{@ Total} & :={sum(c2:[0,-1])} € \\
\end{spreadtab}
这不起作用,它只显示公式而不是结果。
我知道公式无法被处理因为它们在命令中,但我不知道如何解决它。
----- 5 个月后编辑 -----
接受的答案对于我所问的问题来说是一个很好的答案,但是过了一段时间却无法真正得到我想要的东西,我放弃了它,等有时间的时候再回来,用另一种技术,根本不使用spreadtab(这是一个很好的模块,但不适合我的情况)。
对于那些阅读这个问题的人,这是我的解决方案:
\newcounter{total}
\setcounter{total}{0}
\newcommand{\test}[2]{
\addtocounter{total}{\fpeval{#1 * #2}}
#1 & #2 € & {\fpeval{#1 * #2} €} \\
}
\begin{tabularx}{\textwidth}{|X|r|r|}
Col 1 & Col 2 & Col 3 \\
\hline
\test{2}{50}
\test{3}{100}
\hline
\multicolumn{2}{|r|}{Total} & \the\numexpr\value{total} € \\
\end{tabularx}
这是一个比我想要的更长的解决方案,带有“手动”公式,但效果很好。
答案1
好些了吗?答案
一种不需要您将其放在\noexpand
任何地方的变体,但仅扩展一组已定义的宏(按照您添加这些宏的顺序)。宏需要可扩展且一步扩展(因此,没有可选参数,也没有太花哨的东西,即使它们需要更多,它们仍然只会扩展一次)。应该扩展的宏不能位于任何括号组中,因为这样它们将无法找到并且不会扩展。
\AddXspreadtabMacro
在 主体中应展开的宏上使用Xspreadtab
,也可以使用\RemXspreadtabMacro
从列表中删除应展开的宏。\Add...
和均\RemXspreadtabMacro
在本地范围内工作。
\documentclass[]{article}
\usepackage{tabularx}
\usepackage{spreadtab}
\usepackage{xparse}
\ExplSyntaxOn
% will store the body of the spreadtab on which we're working
\tl_new:N \l_guildem_spreadtab_tl
% will store the macro names which should be expanded
\seq_new:N \l_guildem_expansion_seq
% used to signal that we should do another expansion loop for a macro
\bool_new:N \l__guildem_loop_bool
% add the macro to the list of macros which should be expanded
\NewDocumentCommand \AddXspreadtabMacro { m }
{
\seq_if_in:NnF \l_guildem_expansion_seq { #1 }
{
\seq_put_right:Nn \l_guildem_expansion_seq { #1 }
}
}
% remove a macro from the list
\NewDocumentCommand \RemXspreadtabMacro { m }
{
\seq_remove_all:Nn \l_guildem_expansion_seq { #1 }
}
\cs_new_protected:Npn \__guildem_sanitize_spreadtab_aux:w #1 \q_nil \q_stop
{
\tl_set:No \l_guildem_spreadtab_tl { \use_none:n #1 }
}
\cs_new_protected:Npn \__guildem_sanitize_spreadtab:
{
\exp_after:wN
\__guildem_sanitize_spreadtab_aux:w \l_guildem_spreadtab_tl \q_stop
}
\cs_new_protected:Npn \__guildem_expand_macro:n #1
{
% check whether the macro is in the body of the spreadtab
\tl_if_in:NnT \l_guildem_spreadtab_tl { #1 }
{
\bool_set_true:N \l__guildem_loop_bool
% define a helper function that expands the macro
\cs_set:Npn \__guildem_expand_macro_aux:w ##1 #1 ##2 \q_stop
{
\tl_set:Nn \l_guildem_spreadtab_tl { ##1 }
\tl_put_right:No \l_guildem_spreadtab_tl { #1 ##2 }
}
}
% \l__guildem_loop_bool is true as long as the macro is still contained in
% the body and not yet expanded
\bool_while_do:Nn \l__guildem_loop_bool
{
% call the helper macro that expands the macro
\exp_after:wN
\__guildem_expand_macro_aux:w \l_guildem_spreadtab_tl \q_stop
% check whether there is another occurrence of macro in the body
\tl_if_in:NnF \l_guildem_spreadtab_tl { #1 }
{ \bool_set_false:N \l__guildem_loop_bool }
}
}
\cs_new_protected:Npn \__guildem_spreadtab:nn #1 #2
{
\begin{spreadtab}#1#2\end{spreadtab}
}
\cs_generate_variant:Nn \__guildem_spreadtab:nn { nV }
\NewDocumentEnvironment{Xspreadtab}{O{} m b}
{
% adding \q_nil on both sides to not accidentally remove a group while later
% parsing.
\tl_set:Nn \l_guildem_spreadtab_tl { \q_nil #3 \q_nil }
% step over the macros which should be expanded and expand those
\seq_map_function:NN \l_guildem_expansion_seq \__guildem_expand_macro:n
% remove the \q_nil from both ends
\__guildem_sanitize_spreadtab:
% output the spreadtab
\__guildem_spreadtab:nV { [{#1}]{#2} } \l_guildem_spreadtab_tl
}
{}
\ExplSyntaxOff
\newcommand{\test}[2]{#1 & :={#2} € & :={[-2,0] * [-1,0]} €}
\AddXspreadtabMacro\test
\begin{document}
\begin{Xspreadtab}{{tabularx}{\textwidth}{|X|r|r|}}
@ Col 1 & @ Col 2 & @ Col 3 \\
\hline
\test{2}{50} \\
\test{3}{100} \\
\hline
\multicolumn{2}{|r|}{@ Total} & :={sum(c2:[0,-1])} € \\
\end{Xspreadtab}
\end{document}
原始答案
问题是,spreadtab
在搜索公式之前不会扩展其内容。理论上,您可以创建一个类似于的环境,spreadtab
但在将其转发到之前会扩展其内容spreadtab
,但这需要\noexpand
在每个不应扩展的宏之前放置,因此输入实际上并不会变得更容易。
\documentclass[]{article}
\usepackage{tabularx}
\usepackage{spreadtab}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn \Xspreadtab_expansion_helper:nn #1 #2 { #1 #2 }
\cs_generate_variant:Nn \Xspreadtab_expansion_helper:nn { nx }
\NewDocumentEnvironment{Xspreadtab}{O{} m b}
{
\Xspreadtab_expansion_helper:nx { \begin{spreadtab}[{#1}]{#2} } { #3 }
\end{spreadtab}
}
{}
\ExplSyntaxOff
\newcommand{\test}[2]{#1 & :={#2} € & :={[-2,0] * [-1,0]} €}
\begin{document}
\begin{Xspreadtab}{{tabularx}{\textwidth}{|X|r|r|}}
@ Col 1 & @ Col 2 & @ Col 3 \noexpand\\
\noexpand\hline
\test{2}{50} \noexpand\\
\test{3}{100} \noexpand\\
\noexpand\hline
\noexpand\multicolumn{2}{|r|}{@ Total} & :={sum(c2:[0,-1])} € \noexpand\\
\end{Xspreadtab}
\end{document}