将旧代码转换为 expl3 符号

将旧代码转换为 expl3 符号

最近我被介绍使用 xparse 包的 expl3 语法。这个东西很棒,帮了我很多忙。问题是我的文档类现在是混合的,我需要使用一些新的可能性,用于我的一个旧函数,这个函数包含太多东西,\expandfter我从来没有真正理解过。(与对我来说更易读的新语法相反)。所以从学习的角度来看,为了能够让我的类更适合在新的环境中使用,我想将这个旧函数转换为

\makeatletter

\newcommand{\WIT}[3]%
{
    \ifcsname Total#1\endcsname
    \relax
    \else
    \expandafter\def\csname#1Contents\endcsname{}%
    \expandafter\def\csname#1ContentsWCost\endcsname{}%
    \expandafter\pgfmathsetmacro\csname Total#1\endcsname{0}%
    \pgfmathsetmacro\TotalContractH{0.0}%
    \pgfmathsetmacro\TotalContractC{0.0}%
    \expandafter\def\csname#1\endcsname##1##2
    {   
        \pgfkeys{/pgf/fpu=true}%
        \expandafter\pgfmathsetmacro\csname Total#1\endcsname{\csname Total#1\endcsname + ##2}%
        \pgfmathsetmacro\TotalContractH{\TotalContractH + ##2}
        \countCost{##2}{#3}
        \pgfkeys{/pgf/fpu=false}
        \pgfkeys{/pgf/fpu=true}
        \pgfmathsetmacro\TotalContractC{\TotalContractC + \costRes}
        \pgfkeys{/pgf/fpu=false}
        \expandafter\g@addto@macro\csname#1ContentsWCost\endcsname{##1&\showTime{##2}&\countCost{##2}{#3}\showCost{\costRes}\\}%
        \expandafter\g@addto@macro\csname#1Contents\endcsname{##1&\showTime{##2}\\}%
    }%
    \expandafter\def\csname#1TableNC\endcsname{\WITtableNC{#1}{#2}{\csname#1Contents\endcsname}{#3}}%
    \g@addto@macro\SummaryTableNoCost{\csname#1Table\endcsname}%
    \expandafter\def\csname#1TableWC\endcsname{\WITtableWC{#1}{#2}{\csname#1ContentsWCost\endcsname}{#3}}%
    \g@addto@macro\SummaryTableWCost{\csname#1Table\endcsname}%
    \expandafter\def\csname#1Table\endcsname{
        \ifShowCost
            \csname#1TableWC\endcsname
        \else
            \csname#1TableNC\endcsname
        \fi
    }%
}

\makeatother
\newcommand{\countCost}[2]{
    \pgfkeys{/pgf/fpu=true}
    \pgfmathsetmacro\costRes{#1 * #2}
    \pgfkeys{/pgf/fpu=false}
}


\newcommand{\showCost}[1]{
    \pgfkeys{/pgf/fpu=true}
    \pgfmathprintnumber[cashnumber]{#1} \$%
    \pgfkeys{/pgf/fpu=false}
}

\newcommand{\showTime}[1]{
    \pgfkeys{/pgf/fpu=true}
    \showTotalTime{#1}%
    \pgfkeys{/pgf/fpu=false}
}

\newcommand{\showTotalTime}[1]{
    \pgfmathprintnumber[hournumber]{#1} h%
}

变成更灵活的东西。

这是我目前得到的:

\ExplSyntaxOn

\fp_new:N \TotalContractH %Total Contract Hours
\fp_new:N \TotalContractC %Total Contract Cost
\tl_new:N \SummaryTableNoCost %Summary Table without the Cost
\tl_new:N \SummaryTableWCost %Summary Table with the Cost

\NewDocumentCommand{\WIT}{m m m}{ %type desc rate
    \ifcsname Total#1\endcsname
        \relax
    \else
        \fp_new:N \csname Total#1\endcsname 
        \tl_new:N \csname#1Contents\endcsname
        \tl_new:N \csname#1ContentsWCost\endcsname
        \NewDocumentCommand{\csname#1\endcsname}{o m m}{ %[groupe] desc time
            \fp_add:Nn \csname Total#1\endcsname {##3}
            \fp_add:Nn \TotalContractH {##3}
            \fp_add:Nn \TotalContractC {(##3 * #3)}
            \tl_put_right:Nx \csname#1ContentsWCost\endcsname {
                ##2&\pgfmathprintnumber[hournumber]{##3}&\pgfmathprintnumber[cashnumber]{\fp_eval:n {##3 * #3}}\\
            }%
            \tl_put_right:Nx \csname#1Contents\endcsname {
                ##2&\pgfmathprintnumber[hournumber]{##3}\\
            }%

            \cs_new:Npn \csname#1TableNC\endcsname{}{\WITtableNC{#1}{#2}{\csname#1Contents\endcsname}{#3}}%
            \tl_put_right:Nx \SummaryTableNoCost{\csname#1TableNC\endcsname}%

            \cs_new:Npn \csname#1TableWC\endcsname{}{\WITtableWC{#1}{#2}{\csname#1ContentsWCost\endcsname}{#3}}%
            \tl_put_right:Nx \SummaryTableWCost{\csname#1TableWC\endcsname}%

            \NewDocumentCommand{\csname#1Table\endcsname}{}{
                \ifShowCost
                    \csname#1TableWC\endcsname
                \else
                    \csname#1TableNC\endcsname
                \fi
            }%

        }
    \fi

}


\ExplSyntaxOff

当然,这个东西不起作用,主要有三个原因:

  1. 我真的很不擅长\expandafter,我可能搞不清楚这里发生了什么
  2. 我对 expl3 语法还不太熟悉。我尽力了,但可能还是漏掉了一些东西。
  3. 我甚至不确定是否可以csname在 expl 语法中使用这样的定义。

提前致谢,

编辑:这是一个完全可测试的文档

\documentclass[letterpaper, 12pt]{article}


\usepackage{xparse} %LaTeX3 enabled

\RequirePackage{lmodern}
\RequirePackage{graphicx}
\RequirePackage[french]{babel}%
\usepackage{relsize}
\usepackage[margin=12mm]{geometry}
\usepackage{ifluatex, ifxetex}
\newif\ifxetexorluatex
\ifxetex
\xetexorluatextrue
\else
\ifluatex
\xetexorluatextrue
\else
\xetexorluatexfalse
\fi\fi


\ifxetexorluatex
\usepackage{fontspec}
\setmainfont{Calibri}
\setsansfont{Arial}
\setmonofont{Liberation Mono}

\else
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\fi



\usepackage{tabularx}
\usepackage[table]{xcolor}

\usepackage{array}
\usepackage{enumitem}
\usepackage{float}
\usepackage{parskip}

\usepackage{pgfplots,tikz}


\usepackage{hyperref}
\hypersetup{%
    pdfencoding=auto,
    pdfauthor={yourself},
}



\RequirePackage{etoolbox}



\usepackage{framed}

\ifxetexorluatex
\usepackage{dtk-logos}
\hologoFontSetup {general=\fontspec{Times New Roman}}
\renewcommand{\TeX}{\hologo{TeX}}
\newcommand{\TeXStudio}{{\fontspec{Times New Roman}\hologo{TeX}Studio}}
\fi


%%%%%%%%%%%%%%%%%
% WorkItem Types
%%%%%%%%%%%%%%%%%
\newcommand{\countCost}[2]{
    \pgfkeys{/pgf/fpu=true}
    \pgfmathsetmacro\costRes{#1 * #2}
    \pgfkeys{/pgf/fpu=false}
}


\newcommand{\showCost}[1]{
    \pgfkeys{/pgf/fpu=true}
    \pgfmathprintnumber[cashnumber]{#1} \$%
    \pgfkeys{/pgf/fpu=false}
}

\newcommand{\showTime}[1]{
    \pgfkeys{/pgf/fpu=true}
    \showTotalTime{#1}%
    \pgfkeys{/pgf/fpu=false}
}

\newcommand{\showTotalTime}[1]{
    \pgfmathprintnumber[hournumber]{#1} h%
}

%http://tex.stackexchange.com/questions/360031/trying-to-create-dynamic-table-and-commands-alltogether
\newcommand\SummaryTableNoCost{}%
\newcommand\SummaryTableWCost{}%

\newif\ifShowCost
\ShowCosttrue

\newcommand\SummaryTable{
    \ifShowCost
    \SummaryTableWCost
    \else
    \SummaryTableNoCost
    \fi
}%

\makeatletter

\newcommand{\WIT}[3]%
{
    \ifcsname Total#1\endcsname
    \relax
    \else
    \expandafter\def\csname#1Contents\endcsname{}%
    \expandafter\def\csname#1ContentsWCost\endcsname{}%
    \expandafter\pgfmathsetmacro\csname Total#1\endcsname{0}%
    \pgfmathsetmacro\TotalContractH{0.0}%
    \pgfmathsetmacro\TotalContractC{0.0}%
    \expandafter\def\csname#1\endcsname##1##2
    {   
        \pgfkeys{/pgf/fpu=true}%
        \expandafter\pgfmathsetmacro\csname Total#1\endcsname{\csname Total#1\endcsname + ##2}%
        \pgfmathsetmacro\TotalContractH{\TotalContractH + ##2}
        \countCost{##2}{#3}
        \pgfkeys{/pgf/fpu=false}
        \pgfkeys{/pgf/fpu=true}
        \pgfmathsetmacro\TotalContractC{\TotalContractC + \costRes}
        \pgfkeys{/pgf/fpu=false}
        \expandafter\g@addto@macro\csname#1ContentsWCost\endcsname{##1&\showTime{##2}&\countCost{##2}{#3}\showCost{\costRes}\\}%
        \expandafter\g@addto@macro\csname#1Contents\endcsname{##1&\showTime{##2}\\}%
    }%
    \expandafter\def\csname#1TableNC\endcsname{\WITtableNC{#1}{#2}{\csname#1Contents\endcsname}{#3}}%
    \g@addto@macro\SummaryTableNoCost{\csname#1Table\endcsname}%
    \expandafter\def\csname#1TableWC\endcsname{\WITtableWC{#1}{#2}{\csname#1ContentsWCost\endcsname}{#3}}%
    \g@addto@macro\SummaryTableWCost{\csname#1Table\endcsname}%
    \expandafter\def\csname#1Table\endcsname{
        \ifShowCost
        \csname#1TableWC\endcsname
        \else
        \csname#1TableNC\endcsname
        \fi
    }%
}

\makeatother

\newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
\newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}

\newcommand\WITtableWC[4]%
{
    \vbox{
        \begin{flushleft}
            \textbf{#2:} (#4 \$/h)
        \end{flushleft}
        \rowcolors{1}{white}{cyan!10}
        \begin{tabularx}{\textwidth}{|X|r|R{3cm}|}
            \hline\rowcolor{lightgray}
            Description & \iflanguage{french}{Temps Estimé}{Estimated Hours} & \iflanguage{french}{Coût}{Cost}\hspace{5mm}\\
            \hline
            #3
            \hline\rowcolor{lightgray}
            Total #2 & \pgfmathprintnumber[hournumber]{\csname Total#1\endcsname} h & \countCost{\csname Total#1\endcsname}{#4}\showCost{\costRes}\\
            \hline
        \end{tabularx}\\
    }
}

\newcommand\WITtableNC[4]%
{
    \vbox{
        \begin{flushleft}
            \textbf{#2:}
        \end{flushleft}
        \rowcolors{1}{white}{cyan!10}
        \begin{tabularx}{\textwidth}{|X|r|}
            \hline\rowcolor{lightgray}
            Description & \iflanguage{french}{Temps Estimé}{Estimated Hours}\\
            \hline
            #3
            \hline\rowcolor{lightgray}
            Total #2 & \pgfmathprintnumber[hournumber]{\csname Total#1\endcsname} h\\
            \hline
        \end{tabularx}\\
    }
}



\iflanguage{french}{
    \pgfkeys{
        /pgf/number format/cashnumber/.style={
            fixed,
            use comma,
            fixed zerofill,
            precision=0,
            1000 sep={\ },
        },
        /pgf/number format/hournumber/.style={
            use comma,
            fixed,
            precision=2,
            1000 sep={\ },
        },
    }
}{
    \pgfkeys{
        /pgf/number format/cashnumber/.style={
            fixed,
            fixed zerofill,
            precision=0,
            1000 sep={,},
        },
        /pgf/number format/hournumber/.style={
            fixed,
            precision=2,
            1000 sep={,},
        },
    }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\WIT{dev}{Development}{30}

\WIT{other}{Other activities}{20}

\other{somehting}{8}
\other{other thing}{24}

\dev{GUI}{4}
\dev{BackEnd}{16}

\begin{document}

    \SummaryTable

\end{document}

编辑2(最终版本):

在听取了 egreg 的评论并进行了一些操作之后,我得到了最终的结果

\documentclass[letterpaper, 12pt]{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}

\usepackage[top=5mm,left=35mm,bottom=5mm,right=35mm]{geometry}
\usepackage{xparse} %LaTeX3 enabled

\usepackage{tabularx}
\usepackage[table]{xcolor}

\usepackage{array}
\usepackage{tikz}

%%%%%%%%%%%%%%%%%
% WorkItem Types
%%%%%%%%%%%%%%%%%
%https://tex.stackexchange.com/questions/370008/conversion-of-old-code-to-expl3-notation/

\ExplSyntaxOn

\NewDocumentCommand{\showCost}{m}{%
    \pgfmathprintnumber[cashnumber]{#1}~\$%
}

\NewDocumentCommand{\showTime}{m}{%
    \pgfmathprintnumber[hournumber]{#1}~h%
}


\NewDocumentCommand{\WITOptGrp}{mom}{
    \cs_if_exist:cF {  g_hikari_group_#1_contents_tl }{
        \tl_new:c { g_hikari_group_#1_contents_tl }
        \tl_new:c { g_hikari_group_#1_contents_with_cost_tl }
        \fp_new:c { g_hikari_witgroup_#1_totaltime_fp }
        \fp_new:c { g_hikari_witgroup_#1_totalcost_fp }



        \cs_new:cpn { group #1 TableNC }
        {
            \WITGrouptableNC{#1}{#3}{\tl_use:c { g_hikari_group_#1_contents_tl }}{#2}
        }

        \cs_new:cpn { group #1 TableWC }
        {
            \WITGrouptableWC{#1}{#3}{\tl_use:c { g_hikari_group_#1_contents_with_cost_tl }}{#2}
        }

        \cs_new:cpn { group #1 Table }
        {
            \bool_if:NTF \g_hikari_wit_showcost_bool
            { \use:c { group #1 TableWC } }
            { \use:c { group #1 TableNC } }
        }

        \tl_gput_right:Nn \g_hikari_group_summary_table_no_cost_tl { \use:c { group #1 TableNC } }
        \tl_gput_right:Nn \g_hikari_group_summary_table_with_cost_tl { \use:c { group #1 TableWC } }
    }
}

\NewDocumentCommand\WITGrouptableWC{m m m m}
{
    \par\addvspace{\medskipamount}\noindent
    \begin{minipage}{\textwidth}
        \raggedright
        \textbf{\IfNoValueTF{#4}{#2}{#4}}\par\medskip
        \rowcolors[\hline]{1}{cyan!10}{white}
        \begin{tabularx}{\textwidth}{|X|r|r|R{3cm}|}
            \hline\rowcolor{lightgray}
            Description &
            \iflanguage{french}{Temps~Estimé}{Estimated~Hours} &
            \iflanguage{french}{Taux~Horraire}{Rate} &
            \iflanguage{french}{Coût}{Cost}\hspace{5mm}\\
            \hline
            #3
            \hline\rowcolor{lightgray}
            Total~#2 &
            \showTime{\fp_use:c { g_hikari_witgroup_#1_totaltime_fp } } &
            ~ &
            \showCost{\fp_use:c { g_hikari_witgroup_#1_totalcost_fp } } \\
            \hline
        \end{tabularx}
    \end{minipage}
}

\NewDocumentCommand\WITGrouptableNC{m m m m}
{
    \par\addvspace{\medskipamount}\noindent
    \begin{minipage}{\textwidth}
        \raggedright
        \textbf{\IfNoValueTF{#4}{#2}{#4}}\par\medskip
        \rowcolors[\hline]{1}{cyan!10}{white}
        \begin{tabularx}{\textwidth}{|X|r|}
            \hline\rowcolor{lightgray}
            Description & \iflanguage{french}{Temps Estimé}{Estimated Hours}\\
            \hline
            #3
            \hline\rowcolor{lightgray}
            Total~#2 & \showTime{\fp_use:c { g_hikari_witgroup_#1_totaltime_fp }} \\
            \hline
        \end{tabularx}
    \end{minipage}
}

\NewDocumentCommand{\WIT}{mmm}
{
    \cs_if_exist:cF { #1 }
    {
        \tl_new:c { g_hikari_wit_#1_contents_tl }
        \tl_new:c { g_hikari_wit_#1_contents_with_cost_tl }
        \fp_new:c { g_hikari_wit_#1_totaltime_fp }
        \fp_new:c { g_hikari_wit_#1_totalcost_fp }

        \exp_args:Nc \NewDocumentCommand { #1 } {mmD<>{default}o}
        {
            \WITOptGrp{##3}{##4}

            \fp_gadd:cn { g_hikari_wit_#1_totaltime_fp } { ##2 }
            \fp_gadd:cn { g_hikari_wit_#1_totalcost_fp } { ##2 * #3 }

            \fp_gadd:cn { g_hikari_witgroup_##3_totaltime_fp } { ##2 }
            \fp_gadd:cn { g_hikari_witgroup_##3_totalcost_fp } { ##2 * #3 }


            \tl_gput_right:cn { g_hikari_wit_#1_contents_with_cost_tl }
            {
                ##1 \IfNoValueF{##4}{~(##4)} & \showTime{##2} & \showCost{\fp_eval:n { ##2 * #3 }} \\
            }

            \tl_gput_right:cn { g_hikari_wit_#1_contents_tl } { ##1 \IfNoValueF{##4}{~(##4)} & \showTime{##2} \\ }

            \tl_gput_right:cn { g_hikari_group_##3_contents_tl }{ ##1 ~ (#2) & \showTime{##2} \\ }

            \tl_gput_right:cn { g_hikari_group_##3_contents_with_cost_tl }
            {
                ##1 ~ (#2) & \showTime{##2} & #3 ~\$/h & \showCost{\fp_eval:n { ##2 * #3 }} \\
            }

        }

        \cs_new:cpn { #1 TableNC }
        {
            \WITtableNC{#1}{#2}{\tl_use:c { g_hikari_wit_#1_contents_tl }}
        }



        \cs_new:cpn { #1 TableWC }
        {
            \WITtableWC{#1}{#2}{\tl_use:c { g_hikari_wit_#1_contents_with_cost_tl }}{#3}
        }



        \tl_gput_right:Nn \g_hikari_wit_summary_table_no_cost_tl { \use:c { #1 TableNC } }
        \tl_gput_right:Nn \g_hikari_wit_summary_table_with_cost_tl { \use:c { #1 TableWC } }

        \cs_new:cpn { #1 Table }
        {
            \bool_if:NTF \g_hikari_wit_showcost_bool
            { \use:c { #1 TableWC } }
            { \use:c { #1 TableNC } }
        }
    }
}

\NewDocumentCommand\SummaryTable{}
{
    \bool_if:NTF \g_hikari_wit_showcost_bool
    { \tl_use:N \g_hikari_wit_summary_table_with_cost_tl }
    { \tl_use:N \g_hikari_wit_summary_table_no_cost_tl }
}

\NewDocumentCommand\SummaryTableByOpt{}
{
    \bool_if:NTF \g_hikari_wit_showcost_bool
    { \tl_use:N \g_hikari_group_summary_table_with_cost_tl }
    { \tl_use:N \g_hikari_group_summary_table_no_cost_tl }
}

\NewDocumentCommand{\ShowCostTrue}{}
{
    \bool_gset_true:N \g_hikari_wit_showcost_bool
}
\NewDocumentCommand{\ShowCostFalse}{}
{
    \bool_gset_false:N \g_hikari_wit_showcost_bool
}

\bool_new:N \g_hikari_wit_showcost_bool
\tl_new:N \g_hikari_wit_summary_table_with_cost_tl
\tl_new:N \g_hikari_wit_summary_table_no_cost_tl
\tl_new:N \g_hikari_group_summary_table_with_cost_tl
\tl_new:N \g_hikari_group_summary_table_no_cost_tl

\NewDocumentCommand\WITtableWC{m m m m}
{
    \par\addvspace{\medskipamount}\noindent
    \begin{minipage}{\textwidth}
        \raggedright
        \textbf{#2:}~(#4 \$/h)\par\medskip
        \rowcolors[\hline]{1}{cyan!10}{white}
        \begin{tabularx}{\textwidth}{|X|r|R{3cm}|}
            \hline\rowcolor{lightgray}
            Description &
            \iflanguage{french}{Temps~Estimé}{Estimated~Hours} &
            \iflanguage{french}{Coût}{Cost}\hspace{5mm}\\
            \hline
            #3
            \hline\rowcolor{lightgray}
            Total~#2 &
            \showTime{ \fp_use:c { g_hikari_wit_#1_totaltime_fp } } &
            \showCost{ \fp_use:c { g_hikari_wit_#1_totalcost_fp } } \\
            \hline
        \end{tabularx}
    \end{minipage}
}

\NewDocumentCommand\WITtableNC{m m m}
{
    \par\addvspace{\medskipamount}\noindent
    \begin{minipage}{\textwidth}
        \raggedright
        \textbf{#2:}\par\medskip
        \rowcolors[\hline]{1}{cyan!10}{white}
        \begin{tabularx}{\textwidth}{|X|r|}
            \hline\rowcolor{lightgray}
            Description & \iflanguage{french}{Temps Estimé}{Estimated Hours}\\
            \hline
            #3
            \hline\rowcolor{lightgray}
            Total~#2 & \showTime{ \fp_use:c { g_hikari_wit_#1_totaltime_fp }} \\
            \hline
        \end{tabularx}
    \end{minipage}
}

\ExplSyntaxOff

\newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
\newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}


\iflanguage{french}{
    \pgfkeys{
        /pgf/number format/cashnumber/.style={
            fixed,
            use comma,
            fixed zerofill,
            precision=0,
            1000 sep={\ },
        },
        /pgf/number format/hournumber/.style={
            use comma,
            fixed,
            precision=2,
            1000 sep={\ },
        },
    }
}{
    \pgfkeys{
        /pgf/number format/cashnumber/.style={
            fixed,
            fixed zerofill,
            precision=0,
            1000 sep={,},
        },
        /pgf/number format/hournumber/.style={
            fixed,
            precision=2,
            1000 sep={,},
        },
    }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\WIT{dev}{Development}{30}

\WIT{other}{Other activities}{20}

\WITOptGrp{optB}[Forcing a long name for Option B]{Option B}

\other{something}{8}[Option A]
\other{other thing}{24}<optB>[Option B]
\other{wow}{2}<optC>[Option C]

\dev{GUI}{4}[Option A]
\dev{BackEnd}{16}<optB>[Option B]
\dev{Command Line}{8}<optC>[Option C]

\begin{document}
    \ShowCostTrue   
    \SummaryTable
    \vspace{1cm}
    \SummaryTableByOpt
\vspace{2cm}
    \ShowCostFalse
    \SummaryTable
    \vspace{1cm}
    \SummaryTableByOpt

\end{document}

答案1

你可以研究一下这个代码:

\documentclass[letterpaper, 12pt]{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}


\usepackage{xparse} %LaTeX3 enabled

\usepackage{tabularx}
\usepackage[table]{xcolor}

\usepackage{array}
\usepackage{pgfplots,tikz}

%%%%%%%%%%%%%%%%%
% WorkItem Types
%%%%%%%%%%%%%%%%%

\newcommand{\showCost}[1]{%
    \pgfkeys{/pgf/fpu=true}%
    \pgfmathprintnumber[cashnumber]{#1} \$%
    \pgfkeys{/pgf/fpu=false}%
}

\newcommand{\showTime}[1]{%
    \pgfkeys{/pgf/fpu=true}%
    \showTotalTime{#1}%
    \pgfkeys{/pgf/fpu=false}%
}

\newcommand{\showTotalTime}[1]{%
    \pgfmathprintnumber[hournumber]{#1} h%
}

\ExplSyntaxOn

\NewDocumentCommand{\WIT}{mmm}
 {
  \cs_if_exist:cF { #1 }
   {
    \hikari_wit:nnn { #1 } { #2 } { #3 }
   }
 }

\NewDocumentCommand\SummaryTable{}
 {
  \bool_if:NTF \g_hikari_wit_showcost_bool
   { \tl_use:N \g_hikari_wit_summary_table_with_cost_tl }
   { \tl_use:N \g_hikari_wit_summary_table_no_cost_tl }
 }

\NewDocumentCommand{\ShowCostTrue}{}
 {
  \bool_gset_true:N \g_hikari_wit_showcost_bool
 }
\NewDocumentCommand{\ShowCostFalse}{}
 {
  \bool_gset_false:N \g_hikari_wit_showcost_bool
 }

\bool_new:N \g_hikari_wit_showcost_bool
\tl_new:N \g_hikari_wit_summary_table_with_cost_tl
\tl_new:N \g_hikari_wit_summary_table_no_cost_tl

\cs_new_protected:Nn \hikari_wit:nnn
 {
  \tl_new:c { g_hikari_wit_#1_contents_tl }
  \tl_new:c { g_hikari_wit_#1_contents_with_cost_tl }
  \fp_new:c { g_hikari_wit_#1_total_fp }

  \cs_new_protected:cpn { #1 } ##1 ##2
   {
    \fp_gadd:cn { g_hikari_wit_#1_total_fp } { ##2 }
    \tl_gput_right:cn { g_hikari_wit_#1_contents_with_cost_tl }
     {
      ##1 & \showTime{##2} & \showCost{\fp_eval:n { ##2 * #3 }} \\
     }
    \tl_gput_right:cn { g_hikari_wit_#1_contents_tl } { ##1 & \showTime{##2} \\ }
   }
  \cs_new:cpn { #1 TableNC }
   {
    \WITtableNC{#1}{#2}{\tl_use:c { g_hikari_wit_#1_contents_tl }}{#3}
   }
  \cs_new:cpn { #1 TableWC }
   {
    \WITtableWC{#1}{#2}{\tl_use:c { g_hikari_wit_#1_contents_with_cost_tl }}{#3}
   }
  \tl_gput_right:Nn \g_hikari_wit_summary_table_no_cost_tl { \use:c { #1 Table } }
  \tl_gput_right:Nn \g_hikari_wit_summary_table_with_cost_tl { \use:c { #1 Table } }
  \cs_new:cpn { #1 Table }
   {
    \bool_if:NTF \g_hikari_wit_showcost_bool
     { \use:c { #1 TableWC } }
     { \use:c { #1 TableNC } }
   }
 }

\NewDocumentCommand\WITtableWC{mmmm}
 {
  \par\addvspace{\medskipamount}\noindent
  \begin{minipage}{\textwidth}
  \raggedright
  \textbf{#2:}~(#4 \$/h)\par\medskip
  \rowcolors{1}{white}{cyan!10}
  \begin{tabularx}{\textwidth}{|X|r|R{3cm}|}
  \hline\rowcolor{lightgray}
  Description &
    \iflanguage{french}{Temps~Estimé}{Estimated~Hours} &
    \iflanguage{french}{Coût}{Cost}\hspace{5mm}\\
  \hline
  #3
  \hline\rowcolor{lightgray}
  Total~#2 &
    \pgfmathprintnumber[hournumber]{\fp_eval:n { \fp_use:c { g_hikari_wit_#1_total_fp } }}~h &
    \showCost{\fp_eval:n { \fp_use:c { g_hikari_wit_#1_total_fp } * #4 }} \\
  \hline
  \end{tabularx}
  \end{minipage}
 }

\NewDocumentCommand\WITtableNC{mmmm}
 {
  \par\addvspace{\medskipamount}\noindent
  \begin{minipage}{\textwidth}
  \raggedright
  \textbf{#2:}\par\medskip
  \rowcolors{1}{white}{cyan!10}
  \begin{tabularx}{\textwidth}{|X|r|}
  \hline\rowcolor{lightgray}
  Description & \iflanguage{french}{Temps Estimé}{Estimated Hours}\\
  \hline
  #3
  \hline\rowcolor{lightgray}
  Total #2 & \pgfmathprintnumber[hournumber]{\fp_eval:n {\fp_use:c { g_hikari_wit_#1_total_fp }}}~h \\
  \hline
  \end{tabularx}
  \end{minipage}
 }

\ExplSyntaxOff

\newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
\newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}


\iflanguage{french}{
    \pgfkeys{
        /pgf/number format/cashnumber/.style={
            fixed,
            use comma,
            fixed zerofill,
            precision=0,
            1000 sep={\ },
        },
        /pgf/number format/hournumber/.style={
            use comma,
            fixed,
            precision=2,
            1000 sep={\ },
        },
    }
}{
    \pgfkeys{
        /pgf/number format/cashnumber/.style={
            fixed,
            fixed zerofill,
            precision=0,
            1000 sep={,},
        },
        /pgf/number format/hournumber/.style={
            fixed,
            precision=2,
            1000 sep={,},
        },
    }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\WIT{dev}{Development}{30}

\WIT{other}{Other activities}{20}

\other{something}{8}
\other{other thing}{24}

\dev{GUI}{4}
\dev{BackEnd}{16}

\begin{document}

\ShowCostTrue

\SummaryTable

\ShowCostFalse

\SummaryTable

\end{document}

我已经使用 PGF 打印了数字,尽管我相信它siunitx也是可行的。

可能还可以做更多优化。

在此处输入图片描述

相关内容