我正在使用此发票包 https://github.com/treyhunner/invoices/blob/master/invoice.cls
我的发票表行如下:
\documentclass{invoice}
\def \tab {\hspace*{3ex}}
\begin{document}
\hfil{\Huge\bf me}\hfil
\bigskip\break % Whitespace
\hrule % Horizontal line
my address \hfill (999) 111-2222 \\
my address \hfill [email protected]
\\ \\
{\bf Invoice To:} \\
\tab client \\
\tab client address \\
{\bf Date:} \\
\tab \today \\
\begin{invoiceTable}
\feetype{Consulting Services}
\hourrow{2016-09-27}{0.3}{150}
\hourrow{2016-09-26}{0.1}{150}
\hourrow{2016-09-25}{1.2}{150}
\hourrow{2016-09-09}{0.1}{150}
\hourrow{2016-08-23}{0.2}{150}
\hourrow{2016-08-19}{0.3}{150}
\subtotal
\end{invoiceTable}
\end{document}
什麼?
答案1
该类在计算中使用了(高度准确)和(严重不准确)invoice
的错误混合,因此预计会出现舍入误差。fp
calc
这是该类的修复版本。
%%% modified by egreg for TeX.Stackexchange
%%% http://tex.stackexchange.com/questions/331898/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2011 Trey Hunner %
% %
% Permission is hereby granted, free of charge, to any person obtaining %
% a copy of this software and associated documentation files (the %
% "Software"), to deal in the Software without restriction, including %
% without limitation the rights to use, copy, modify, merge, publish, %
% distribute, sublicense, and/or sell copies of the Software, and to %
% permit persons to whom the Software is furnished to do so, subject to %
% the following conditions: %
% %
% The above copyright notice and this permission notice shall be %
% included in all copies or substantial portions of the Software. %
% %
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %
% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %
% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE %
% LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION %
% OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION %
% WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ProvidesClass{invoice3}
\LoadClass[12pt]{article}
\usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry}
\usepackage[parfill]{parskip} % Do not indent paragraphs
\usepackage{xparse} % Fixed-point arithmetic, among many other things
\usepackage{siunitx} % for displaying numbers
\usepackage{longtable}
\pagestyle{empty} % No page numbers
\linespread{1.5}
\setlength{\doublerulesep}{\arrayrulewidth} % Double rules look like one thick one
% Command for setting a default hourly rate
\ExplSyntaxOn
\NewDocumentCommand{\hourlyrate}{m}
{
\fp_set:Nn \l_invoice_hourlyrate_fp { #1 }
}
\fp_new:N \l_invoice_hourlyrate_fp
\hourlyrate{1} % initialize
\NewDocumentCommand{\feetype}{m}
{
\textbf{#1} \\
}
% Counters for totaling up hours and dollars
\fp_new:N \g_invoice_hours_fp
\fp_new:N \g_invoice_subhours_fp
\fp_new:N \g_invoice_cost_fp
\fp_new:N \g_invoice_subcost_fp
% Formats input number with 2 digits after the decimal place
\NewDocumentCommand{\formatNumber}{m}
{
\num[detect-all,round-integer-to-decimal,round-mode=places,round-precision=2]{\fp_eval:n {#1}}
}
% Returns the total of counter
\NewDocumentCommand{\total}{m}
{
\formatNumber{#1}
}
% Create a new row from title, unit quantity, unit rate, and unit name
\NewDocumentCommand{\unitrow}{mmmm}
{
\fp_gadd:Nn \g_invoice_cost_fp { (#2) * (#3) }
\fp_gadd:Nn \g_invoice_subcost_fp { (#2) * (#3) }
#1 &
\formatNumber{#2} ~ #4 &
\$\formatNumber{#3} &
\$\formatNumber{#2 * #3}
\\
}
% Create a new row from title and expense amount
\NewDocumentCommand{\feerow}{mm}
{
\fp_gadd:Nn \g_invoice_cost_fp { #2 }
\fp_gadd:Nn \g_invoice_subcost_fp { #2 }
#1 & & \$\formatNumber{#2} & \$\formatNumber{#2} \\
}
\DeclareExpandableDocumentCommand{\subtotal}{}
{
\hline
\subtotalaux
}
\NewDocumentCommand{\subtotalaux}{s}
{
\textbf{Subtotal} &
\IfBooleanF{#1}{\textbf{\total{\g_invoice_subhours_fp} ~ hours}} &
&
\textbf{\$\formatNumber{\g_invoice_subcost_fp}}
\fp_gzero:N \g_invoice_subcost_fp
\IfBooleanF{#1}{\fp_gzero:N \g_invoice_subhours_fp}
\\*[1.5ex]
}
% Create a new row from date and hours worked (use stored fee type and hourly rate)
\NewDocumentCommand{\hourrow}{mm}
{
\fp_gadd:Nn \g_invoice_hours_fp { #2 }
\fp_gadd:Nn \g_invoice_subhours_fp { #2 }
\unitrow{#1}{#2}{\l_invoice_hourlyrate_fp}{hours}
}
% Create an invoice table
\NewDocumentEnvironment{invoiceTable}{}
{
\setlength{\tabcolsep}{0.8ex}
\setlength\LTleft{0pt}
\setlength\LTright{0pt}
\begin{longtable}{@{\extracolsep{\fill}\hspace{\tabcolsep}} l r r r }
\hline
\textbf{Description~of~Services} &
\multicolumn{1}{c}{\bfseries Quantity} &
\multicolumn{1}{c}{\bfseries Unit~Price} &
\multicolumn{1}{c}{\bfseries Amount} \\*
\hline\hline
\endhead
}
{
\\*[-\normalbaselineskip]
\hline\hline\hline
{\bfseries Balance Due} & & & {\bfseries \$\formatNumber{\g_invoice_cost_fp}} \\
\end{longtable}
}
\ExplSyntaxOff
如果您将示例文件修改为
\documentclass{invoice3} % Use the custom invoice class (invoice.cls)
\begin{document}
\hourlyrate{150}
\begin{invoiceTable}
\feetype{Consulting Services}
\hourrow{2016-09-27}{0.3}
\hourrow{2016-09-26}{0.1}
\hourrow{2016-09-25}{1.2}
\hourrow{2016-09-09}{0.1}
\hourrow{2016-08-23}{0.2}
\hourrow{2016-08-19}{0.3}
\subtotal
\end{invoiceTable}
\end{document}
这些数字是正确的。
fp
这是另一个仅使用并避免舍入问题的版本。
%%% modified by egreg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2011 Trey Hunner %
% %
% Permission is hereby granted, free of charge, to any person obtaining %
% a copy of this software and associated documentation files (the %
% "Software"), to deal in the Software without restriction, including %
% without limitation the rights to use, copy, modify, merge, publish, %
% distribute, sublicense, and/or sell copies of the Software, and to %
% permit persons to whom the Software is furnished to do so, subject to %
% the following conditions: %
% %
% The above copyright notice and this permission notice shall be %
% included in all copies or substantial portions of the Software. %
% %
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %
% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %
% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE %
% LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION %
% OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION %
% WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ProvidesClass{invoice}
\LoadClass[12pt]{article}
\usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry}
\usepackage[parfill]{parskip} % Do not indent paragraphs
\usepackage{fp} % Fixed-point arithmetic
\usepackage{longtable}
\pagestyle{empty} % No page numbers
\linespread{1.5}
\setlength{\doublerulesep}{\arrayrulewidth} % Double rules look like one thick one
% variables for total cost and subcost, total hours and subhours
\def\totalcost{0}\def\subcost{0}
\def\totalhours{0}\def\subhours{0}
% Command for setting a default hourly rate
\newcommand{\hourlyrate}[1]{\def \@hourlyrate {#1}}
\hourlyrate{1}
\newcommand{\feetype}[1]{
\textbf{#1}
\\
}
% Formats inputed number with 2 digits after the decimal place
\newcommand*{\formatNumber}[1]{\FPround{\temp}{#1}{2}\temp} %
% Returns the total of counter
\newcommand*{\total}[1]{\formatNumber{#1}}
% Create an invoice table
\newenvironment{invoiceTable}{%
% Create a new row from title, unit quantity, unit rate, and unit name
\newcommand*{\unitrow}[4]{%
\FPmul{\tempa}{##2}{##3}%
\FPadd{\tempb}{\totalcost}{\tempa}%
\global\let\totalcost\tempb
\FPadd{\tempb}{\subcost}{\tempa}%
\global\let\subcost\tempb
##1 & \formatNumber{##2} ##4 & \$\formatNumber{##3} & \$\FPmul{\temp}{##2}{##3}\formatNumber{\temp}%
\\
}%
% Create a new row from title and expense amount
\newcommand*{\feerow}[2]{%
\FPadd{\tempa}{\totalcost}{##2}%
\global\let\totalcost\tempa
\FPadd{\tempa}{\subcost}{##2}%
\global\let\subcost\tempa
##1 & & \$\formatNumber{##2} & \$\formatNumber{##2}%
\\
}%
\newcommand{\subtotalNoStar}{%
\textbf{Subtotal} & \textbf{\total{\subhours} hours} & & \textbf{\$\total{\subcost}}%
\gdef\subcost{0}%
\gdef\subhours{0}%
\\*[1.5ex]
}%
\newcommand{\subtotalStar}{%
\textbf{Subtotal} & & & \textbf{\$\total{\subcost}}
\gdef\subcost{0}%
\\*[1.5ex]
}%
\newcommand{\subtotal}{%
\hline
\@ifstar
\subtotalStar
\subtotalNoStar
}%
% Create a new row from date and hours worked (use stored fee type and hourly rate)
\newcommand*{\hourrow}[2]{%
\FPadd{\tempa}{\totalhours}{##2}%
\global\let\totalhours\tempa
\FPadd{\tempa}{\subhours}{##2}%
\global\let\subhours\tempa
\unitrow{##1}{##2}{\@hourlyrate}{hours}%
}%
\setlength{\tabcolsep}{0.8ex}%
\setlength\LTleft{0pt}%
\setlength\LTright{0pt}%
\begin{longtable}{@{\extracolsep{\fill}\hspace{\tabcolsep}} l r r r }
\hline
\bfseries Description of Services & \multicolumn{1}{c}{\bfseries Quantity} & \multicolumn{1}{c}{\bfseries Unit Price} & \multicolumn{1}{c}{\bfseries Amount} \\*
\hline\hline
\endhead
}{
\hline\hline\hline
\bfseries Balance Due & & & \bfseries \$\total{\totalcost} \\
\end{longtable}
}