因此,我正在使用 tabu 包(我需要出于多种原因,我使用过其他表格格式)来制作一个跨多页的长表。此表的一列中包含货币金额,我想在每页的开头显示该列的小计。
经过多次尝试使用长度来存储值(我发现这并不合适,因为长度范围对于我需要使用的值的大小来说太有限),我决定使用 fp 包。
此外,经过几次迭代之后,我发现最简单的方法似乎是使用 tabu 的功能为第一页和后续页面定义不同的标题,并将我用作累加器的变量放在标题内。
但是,我看到变量是在总计计算结束时扩展的,而不是在每页上使用标题时扩展的。在下面的 MWE 中,总计正确计算为 4700,但是第二页中的标题显示 4700 作为小计,尽管标题出现时应该仍为 4300 :
\documentclass[11pt,a4paper]{article}
\usepackage{fp}
\usepackage{tabu}
\usepackage{longtable}
\FPset\total{0}
\newcommand{\summa}[1]{#1%
\FPadd\0\total{#1}\global\let\total\0%
}
\newcommand{\resettotal}{%
\FPset\0{0}\global\let\total\0%
}
\begin{document}
\begin{longtabu} to \textwidth {X[l]}
Amount \endfirsthead
Amount \\
subtotal \FPeval{\result}{round(total,2)}\result \endhead
\resettotal \summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00} \\
\summa{100.00}
\end{longtabu}
The global total is \FPeval{\result}{round(total,2)}\result
\end{document}
从我对 tabu 内部工作原理的有限理解来看,这可能是因为只有在完成整个表格后才会定位标题(当 tabu 确切知道表格的长度时)。但是有没有办法告诉解释器在使用标题的地方扩展 \total 变量?
谢谢,干杯。
答案1
我找不到将动态内容放入标题中的方法:我尝试了几次,但每次出现标题只被评估一次的情况;我没有调查源代码(不仅如此,tabu
而且还longtable
使用了 的代码)。
因此,我开发了一种替代方法,其中标题仅用于保留一些空间,部分总数由每个新页面上的第一个表格行记录在那里。为了检测表格行是否是页面上的第一行,我使用标准的\label
和\ref
系统。我之前曾尝试过其他一些使用\pagetotal
或 的方法\pdfsavepos
,但无济于事。
更新后页码提取功能hyperref
兼容。
新的更新添加了代码的第二个版本。需要进行全面修订以解决以下问题:带有机制的页码\label/\ref
通过 打印到辅助文件中\thepage
。因此,\pagenumbering{roman}
例如,这将是一个罗马符号的数字,在\ifnum
测试中不可用。暂时更新\thepage
没有帮助,因为\thepage
让 到完成\relax
,以便在发货时进行扩展。\write
\label
因此,我需要开发自己的\label/\ref
机制(这样就无需特别考虑hyperref
,因此不存在任何交互)。此外,新代码将处理文档中的多个计算:\resettotal
现在是一个宏,带有一个参数,即用户为计算选择的 ID。需要此 ID 来使标签唯一。此自定义\label/\ref
仅将页码数据放入辅助文件中。
该代码的扩展版本位于该答案的底部。
...
\documentclass[11pt]{article}
\usepackage[paperheight=5cm]{geometry}
\usepackage{fp}
\usepackage{tabu}
\usepackage{longtable}
\FPset\total{0}
\newcounter{myindex}
\makeatletter
%% not compatible with hyperref:
%% \def\SANEpageref #1{\expandafter\expandafter\expandafter
%% \@secondoftwo\csname r@#1\endcsname\empty}
%% update, can be used with or without hyperref:
\def\SANEpageref@ #1#2#3\SANEpageref@{#2}
\def\SANEpageref #1{\expandafter\expandafter\expandafter
\SANEpageref@\csname r@#1\endcsname{}\SANEpageref@ }
\newcommand{\summa}[1]{\relax
\refstepcounter{myindex}\label{sum@\arabic{myindex}}%
\ifcsname r@sum@\arabic{myindex}\endcsname
\ifnum 0\summa@currentpage<0\SANEpageref{sum@\arabic{myindex}}
\xdef\summa@currentpage{\SANEpageref{sum@\arabic{myindex}}}%
\smash{\rlap{\raisebox{.5cm}{Current total: \FPround\result\total2\result}}}%
\fi
\fi
#1\FPadd\0\total{#1}\global\let\total\0%
}
\newcommand{\resettotal}{%
\FPset\0{0}\global\let\total\0%
\setcounter{myindex}{-1}%
\refstepcounter{myindex}\label{sum@0}%
\xdef\summa@currentpage{\SANEpageref{sum@0}}%
}
\makeatother
\begin{document}\pagestyle{empty}
\begin{longtabu} to \textwidth {X[l]}
Amount \endfirsthead
Amount \\
\rule [-3pt]{5cm}{1pt}
\endhead
1: \resettotal \summa{100.00} \\
2: \summa{100.00} \\
3: \summa{100.00} \\
4: \summa{100.00} \\
5: \summa{100.00} \\
6: \summa{100.00} \\
7: \summa{100.00} \\
8: \summa{100.00} \\
9: \summa{100.00} \\
10: \summa{100.00} \\
11: \summa{100.00} \\
12: \summa{100.00} \\
13: \summa{100.00} \\
14: \summa{100.00} \\
15: \summa{100.00} \\
16: \summa{100.00} \\
17: \summa{100.00} \\
18: \summa{100.00} \\
19: \summa{100.00} \\
20: \summa{100.00} \\
21: \summa{100.00} \\
22: \summa{100.00} \\
23: \summa{100.00} \\
24: \summa{100.00} \\
25: \summa{100.00} \\
26: \summa{100.00} \\
27: \summa{100.00} \\
28: \summa{100.00} \\
29: \summa{100.00} \\
30: \summa{100.00} \\
31: \summa{100.00} \\
32: \summa{100.00} \\
33: \summa{100.00} \\
34: \summa{100.00} \\
35: \summa{100.00} \\
36: \summa{100.00} \\
37: \summa{100.00} \\
38: \summa{100.00} \\
39: \summa{100.00} \\
40: \summa{100.00} \\
41: \summa{100.00} \\
42: \summa{100.00} \\
43: \summa{100.00} \\
44: \summa{100.00} \\
45: \summa{100.00} \\
46: \summa{100.00} \\
47: \summa{100.00}
\end{longtabu}
The global total is \FPeval{\result}{round(total,2)}\result
\end{document}
代码的扩展版本
\documentclass[11pt]{article}
\usepackage[paperheight=7cm]{geometry}
\usepackage{fp}
\usepackage{tabu}
\usepackage{longtable}
\makeatletter
\newcounter{computindex}
% THIS EXPANDS #1 IMMEDIATELY, BUT DELAYS EXPANSION OF DECIMAL PAGE NUMBER TO
% SHIPOUT TIME
\newcommand*\computpagelabel [1]
{\edef\computpagelabel@tmp
{\noexpand\write\@auxout {\newcomputpagelabel{#1}{\noexpand\the\c@page}}}%
\computpagelabel@tmp }
\providecommand*\newcomputpagelabel {}
\protected\def\newcomputpagelabel #1#2{\global\@namedef{computpage@#1}{#2}}
\newcommand*\computpage [1]{\csname computpage@#1\endcsname }
\newcommand{\StorePageAndPossiblyUpdateHeader}{%
\stepcounter{computindex}%
\computpagelabel{\computID.\arabic{computindex}}%
\ifcsname computpage@\computID.\arabic{computindex}\endcsname
\ifnum 0\comput@currentpage<0\computpage{\computID.\arabic{computindex}}
\xdef\comput@currentpage{\computpage{\computID.\arabic{computindex}}}%
\UpdatePartialHeader
\fi
\fi
}
\newcommand{\UpdatePartialHeader}
{\smash{\rlap{\raisebox{.5cm}{Current total: \FPround\result\total2\result}}}}%
\newcommand{\summa}[1]{\relax\StorePageAndPossiblyUpdateHeader
#1\FPadd\0\total{#1}\global\let\total\0%
}
% NEW VERSION OF \resettotal HAS AN ARGUMENT TO IDENTIFY THE COMPUTATION
\newcommand*{\resettotal}[1]{%
\FPset\0{0}\global\let\total\0%
% attention au cas de plusieurs tables, on a besoin d'un identifiant:
\gdef\computID{#1}%
\setcounter{computindex}{0}%
\computpagelabel{\computID.0}%
\xdef\comput@currentpage{\computpage{\computID.0}}%
}
\makeatother
\begin{document}
\pagenumbering {roman}% this would have invalidated earlier versions
\begin{longtabu} to \textwidth {X[l]}
Amount \endfirsthead
Amount \\
\rule [-3pt]{5cm}{1pt}
\endhead
1: \resettotal {table1}\summa{100.00} \\
2: \summa{100.00} \\
3: \summa{100.00} \\
4: \summa{100.00} \\
5: \summa{100.00} \\
6: \summa{100.00} \\
7: \summa{100.00} \\
8: \summa{100.00} \\
9: \summa{100.00} \\
10: \summa{100.00} \\
11: \summa{100.00} \\
12: \summa{100.00} \\
13: \summa{100.00} \\
14: \summa{100.00} \\
15: \summa{100.00} \\
16: \summa{100.00} \\
17: \summa{100.00} \\
18: \summa{100.00} \\
19: \summa{100.00} \\
20: \summa{100.00} \\
21: \summa{100.00} \\
22: \summa{100.00} \\
23: \summa{100.00} \\
24: \summa{100.00} \\
25: \summa{100.00} \\
26: \summa{100.00} \\
27: \summa{100.00} \\
28: \summa{100.00} \\
29: \summa{100.00} \\
30: \summa{100.00} \\
31: \summa{100.00} \\
32: \summa{100.00} \\
33: \summa{100.00} \\
34: \summa{100.00} \\
35: \summa{100.00} \\
36: \summa{100.00} \\
37: \summa{100.00} \\
38: \summa{100.00} \\
39: \summa{100.00} \\
40: \summa{100.00} \\
41: \summa{100.00} \\
42: \summa{100.00} \\
43: \summa{100.00} \\
44: \summa{100.00} \\
45: \summa{100.00} \\
46: \summa{100.00} \\
47: \summa{100.00}
\end{longtabu}
The global total is \FPeval{\result}{round(total,2)}\result
\begin{longtabu} to \textwidth {X[l]}
Amount \endfirsthead
Amount \\
\rule [-3pt]{5cm}{1pt}
\endhead
1: \resettotal {table2}\summa{123.45} \\
2: \summa{100.00} \\
3: \summa{100.00} \\
4: \summa{100.00} \\
5: \summa{100.00} \\
6: \summa{100.00} \\
7: \summa{100.00} \\
8: \summa{100.00} \\
9: \summa{100.00} \\
10: \summa{100.00} \\
11: \summa{100.00} \\
12: \summa{100.00} \\
13: \summa{100.00} \\
14: \summa{100.00} \\
15: \summa{100.00} \\
16: \summa{100.00} \\
17: \summa{100.00} \\
18: \summa{100.00} \\
19: \summa{100.00} \\
20: \summa{100.00} \\
21: \summa{100.00} \\
22: \summa{100.00} \\
23: \summa{999.00} \\
24: \summa{100.00} \\
25: \summa{100.00} \\
26: \summa{100.00} \\
27: \summa{100.00} \\
28: \summa{100.00} \\
29: \summa{100.00} \\
30: \summa{100.00} \\
31: \summa{100.00} \\
32: \summa{100.00} \\
33: \summa{100.00} \\
34: \summa{100.00} \\
35: \summa{100.00} \\
36: \summa{100.00} \\
37: \summa{100.00} \\
38: \summa{100.00} \\
39: \summa{100.00} \\
40: \summa{100.00} \\
41: \summa{100.00} \\
42: \summa{100.00} \\
43: \summa{100.00} \\
44: \summa{100.00} \\
45: \summa{100.00} \\
46: \summa{100.00} \\
47: \summa{100.00}
\end{longtabu}
The global total is \FPround\result\total2\result.
\end{document}
上述代码输出的两页