\newcounter
我曾在长表中使用过带有和的总和\addtocounter
,一切运行正常,但使用起来有点复杂。
在 egreg 的帮助下,我能够创建一个 latex3 版本来创建不同时间单位的总和,然后以可理解的形式显示结果:先前的问题已得到回答
一切正常,但当我尝试在 longtable 中使用它时,总和每行都会重置。为什么会这样?我该如何避免这种情况?
\documentclass[parskip=full]{scrlttr2}
\renewcommand\familydefault{\sfdefault}
\usepackage[defaultsans, scale=0.9]{opensans}
\ExplSyntaxOn
\NewDocumentCommand{\newtime}{m}
{
\fp_new:c { l_timecalc_time_#1_fp }
}
\newtime{default} % initialize one
% \addtime* will also show the added time
\NewDocumentCommand{\addtime}{sO{default}mm}
{
\timecalc_time_add:nnn { #2 } { #3 } { #4 }
% with \addtime* also show what's been added
\IfBooleanT{#1}{#3\,\textup{#4}}
}
\NewDocumentCommand{\strtime}{O{default}}
{
\timecalc_time_str:n { #1 }
}
\int_new:N \l__timecalc_time_days_int
\int_new:N \l__timecalc_time_hours_int
\int_new:N \l__timecalc_time_minutes_int
\cs_new_protected:Nn \timecalc_time_add:nnn
{
\str_case:nnF { #3 }
{
{h}{ \fp_add:cn { l_timecalc_time_#1_fp } { #2 * 60 } }
{d}{ \fp_add:cn { l_timecalc_time_#1_fp } { #2 * 60 * 24 } }
{min}{ \fp_add:cn { l_timecalc_time_#1_fp } { #2 } }
}
{\ERROR}
}
\cs_new_protected:Nn \int_div_mod:nnn {
\int_set:Nn #3
{ \int_div_truncate:nn { #1 } { #2 } }
\int_set:Nn #1
{ \int_mod:nn { #1 } { #2 } }
}
\cs_new_protected:Nn \timecalc_time_str:n
{
% round to an integral number of minutes
\int_set:Nn \l__timecalc_time_minutes_int
{ \fp_eval:n { round( \fp_use:c { l_timecalc_time_#1_fp }, 0 ) } }
% compute and remove the number of days
\int_div_mod:nnn{\l__timecalc_time_minutes_int}{1440}{\l__timecalc_time_days_int}
% compute and remove the number of hours
\int_div_mod:nnn{\l__timecalc_time_minutes_int}{60}{\l__timecalc_time_hours_int}
% now print the days
\int_compare:nT { \l__timecalc_time_days_int > 0 }
{ \int_eval:n { \l__timecalc_time_days_int }\,\textup{d}\; }
% now print the hours
\int_compare:nTF { \l__timecalc_time_hours_int > 0 }
{
\int_eval:n { \l__timecalc_time_hours_int }\,\textup{h}\;
}
{% no hours
%\unkern
}
% now print the minutes
\int_compare:nTF { \l__timecalc_time_minutes_int > 0 }
{
\int_eval:n { \l__timecalc_time_minutes_int }\,\textup{min}
}
{% no minutes
%\unkern
}
}
\ExplSyntaxOff
\usepackage{longtable}[=v4.13]
\usepackage{tabu}%
\begin{document}
\begin{letter}{recipient}
\opening{opening}
\begin{longtable}{c}
\textbf{time}
\endhead
\addtime*{20.5}{h}\\
\addtime*{30}{min}\\
\addtime*{2.7}{d}\\
\end{longtable}
This leads to a complete time of \strtime.
Normal sum:
\addtime*{20.5}{h}
\addtime*{30}{min}
\addtime*{2.7}{d}
This leads to a complete time of \strtime.
\closing{concluding text}
\end{letter}
\end{document}
PS:还\unkern
破坏了 longtable,因此必须取消注释。
答案1
在 David Carlisle 的帮助下,我能够使它工作,使用g_
变量存储总和,而\fp_gadd
不是\fp_add
用于添加到总和:
\documentclass[parskip=full]{scrlttr2}
\renewcommand\familydefault{\sfdefault}
\usepackage[defaultsans, scale=0.9]{opensans}
\ExplSyntaxOn
\NewDocumentCommand{\newtime}{m}
{
\fp_new:c { g_timecalc_time_#1_fp }
}
\newtime{default} % initialize one
% \addtime* will also show the added time
\NewDocumentCommand{\addtime}{sO{default}mm}
{
\timecalc_time_add:nnn { #2 } { #3 } { #4 }
% with \addtime* also show what's been added
\IfBooleanT{#1}{#3\,\textup{#4}}
}
\NewDocumentCommand{\strtime}{O{default}}
{
\timecalc_time_str:n { #1 }
}
\int_new:N \l__timecalc_time_days_int
\int_new:N \l__timecalc_time_hours_int
\int_new:N \l__timecalc_time_minutes_int
\cs_new_protected:Nn \timecalc_time_add:nnn
{
\str_case:nnF { #3 }
{
{h}{ \fp_gadd:cn { g_timecalc_time_#1_fp } { #2 * 60 } } % <= using \fp_gadd
{d}{ \fp_gadd:cn { g_timecalc_time_#1_fp } { #2 * 60 * 24 } } % <= using \fp_gadd
{min}{ \fp_gadd:cn { g_timecalc_time_#1_fp } { #2 } } % <= using \fp_gadd
}
{\ERROR}
}
\cs_new_protected:Nn \int_div_mod:nnn {
\int_set:Nn #3
{ \int_div_truncate:nn { #1 } { #2 } }
\int_set:Nn #1
{ \int_mod:nn { #1 } { #2 } }
}
\cs_new_protected:Nn \timecalc_time_str:n
{
% round to an integral number of minutes
\int_set:Nn \l__timecalc_time_minutes_int
{ \fp_eval:n { round( \fp_use:c { g_timecalc_time_#1_fp }, 0 ) } }
% compute and remove the number of days
\int_div_mod:nnn{\l__timecalc_time_minutes_int}{1440}{\l__timecalc_time_days_int}
% compute and remove the number of hours
\int_div_mod:nnn{\l__timecalc_time_minutes_int}{60}{\l__timecalc_time_hours_int}
% now print the days
\int_compare:nT { \l__timecalc_time_days_int > 0 }
{ \int_eval:n { \l__timecalc_time_days_int }\,\textup{d}\; }
% now print the hours
\int_compare:nTF { \l__timecalc_time_hours_int > 0 }
{
\int_eval:n { \l__timecalc_time_hours_int }\,\textup{h}\;
}
{% no hours
%\unkern
}
% now print the minutes
\int_compare:nTF { \l__timecalc_time_minutes_int > 0 }
{
\int_eval:n { \l__timecalc_time_minutes_int }\,\textup{min}
}
{% no minutes
%\unkern
}
}
\ExplSyntaxOff
\usepackage{longtable}[=v4.13]
\usepackage{tabu}%
\begin{document}
\begin{letter}{recipient}
\opening{opening}
\begin{longtable}{c}
\textbf{time}
\endhead
\addtime*{20.5}{h}\\
\addtime*{30}{min}\\
\addtime*{2.7}{d}\\
\end{longtable}
This leads to a complete time of \strtime.
Normal sum:
\addtime*{20.5}{h}
\addtime*{30}{min}
\addtime*{2.7}{d}
This leads to a complete time of \strtime.
\closing{concluding text}
\end{letter}
\end{document}
答案2
解决方案lualatex
:
\documentclass[parskip=full]{scrartcl}
\usepackage{luacode}
\begin{luacode*}
function addtime(value, unit)
if unit == "d" then
value = value * 24 * 60
elseif unit == "h" then
value = value * 60
end
return value
end
function gettime(name)
days = name//1440
name = name - days * 1440
hours = name//60
minutes = math.floor(name - hours * 60)
return (tostring(days).."\\,d, "..tostring(hours).."\\,h, "..tostring(minutes).."\\,min")
end
\end{luacode*}
\newcommand*\settime[1][default]{\directlua{ #1 = 0 }}
\settime
\newcommand*\addtime[3][default]{%
#2 #3
\directlua{ #1 = #1 + addtime(#2,"#3") }}
\newcommand*\gettime[1][default]{%
\directlua{ tex.print( gettime(#1)) }}
\usepackage{longtable}
\begin{document}
\begin{longtable}{c}
\textbf{time}
\endhead
\addtime{20.5}{h}\\
\addtime{30}{min}\\
\addtime{2.7}{d}\\
\end{longtable}
This leads to a complete time of \gettime.
Normal sum:
\addtime{20.5}{h}
\addtime{30}{min}
\addtime{2.7}{d}
This leads to a complete time of \gettime.
\end{document}