在 longtabu 标头中使用 fp 变量

在 longtabu 标头中使用 fp 变量

因此,我正在使用 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仅将页码数据放入辅助文件中。

该代码的扩展版本位于该答案的底部。

部分1

部分2

部分 3

部分 4 ... 部分 8

部分 9

部分 10

\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}

上述代码输出的两页

部分 1

部分 2

相关内容