长表中求和不起作用

长表中求和不起作用

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

相关内容