4

In this question here on the TeX-forum, I asked for a method to store variables in a convenient way, so that non-techies are not scared off to work with LaTeX. To bring this up to a new level, I'd like to define the complete structure of the document, in this case an invoice, in the .cls file, including text output.

This is not really possible, as you are not allowed to print content before the \begin{document} command.

What I'd like to have is a two documents folder setup. The invoice.clsdocument class file, preformatting everything and the main.tex file in which the end user can enter the variables as shown in the previous question and set up the bill.

For the bill I defined a newenvironment with some custom commands and counters, so that the total amount is calculated by LaTeX and printed on the page.

Ideally the main.tex should only contain these two things:

\documentclass{invoice}

\begin{document}

    \StoreInvoiceData{%
        %% %%%%%%
        %% Sender
        %% %%%%%%
        Tagline     =   {Hello World},
        FirstName   =   {Victor K.},
        LastName    =   {Driscoll},
        Street      =   {1616 Hill Croft Farm Road},
        Zip         =   {95932},
        Town        =   {Colusa},
        Country     =   {USA},
        IBAN        =   {YY24KIHB12476423125915947930915268},
        SWIFT       =   {ANTSUB4L},

        %% %%%%%%%%
        %% Receiver
        %% %%%%%%%%
        ClientFirstName     =   {John},
        ClientLastName      =   {Doe},
        ClientStreet        =   {123 Main St},
        ClientZip           =   {43221},
        ClientTown          =   {Anytown},
        ClientCountry       =   {USA}
    }

    \begin{invoicetable}
        %% %%%%%%%
        %% Hosting
        %% %%%%%%%
        \feetype{Hosting Expenses}
        \unitrow{Test 1}{1}{10}    % \unitrow{Name}{Quantity}{Item price}
        \unitrow{Test 2}{1}{15}
        \unitrow{Test 3}{1}{20}
        \subtotal

        %% %%%%%%%%%%%%
        %% Maintainance
        %% %%%%%%%%%%%%
        \feetype{Maintenance Fees}
        \unitrow{Test 4}{2}{15}
        \unitrow{Test 5}{1}{20}
        \unitrow{Test 6}{5}{25}
        \unitrow{Test 7}{1}{30}
        \subtotal
    \end{invoicetable}

\end{document}

The invoice.cls should handle all the rest. If no values are entered in the \StoreInvoiceData-list, blank fields should be printed. The class should automatically print the header (a TikZ rectangle with nodes that include the name an the tagline), the address field (also a TikZ rectangle placed at the correct coordinates to match the window in an envelope) and so on.

At the moment this is all done by \newcommands which are then called in the main.tex, but as I said, I want tho keep that file as clean as possible and I'm sure that there is a possibility to define the complete layout in a LaTeX class.


If something is not clear, please feel free to ask.

Thanks for your help, I really appreciate it!

  • 1
    This seems like an awful lot of work for the user, especially since the data it presumably entered somewhere else too. I would create these invoices using datatool and have the users simply enter data in Excel. – Alan Munn Aug 4 '17 at 17:04
  • Why do you think that that's a lot of work for the user? He does only need to define the document class and type in the variables in the main.tex file. The invoice.cls is ready to use and should not be modified by the end user. That's pretty easy I'd say, isn't it? – Sam Aug 4 '17 at 18:04
  • 1
    But user input into markup is more complicated than user input into cells of a spreadsheet (not to mention the ability to do input validation etc.) And since this is an invoice, it's likely that the information would usefully stored in Excel or equivalent anyway. So using markup as storage is not the right way to do things. – Alan Munn Aug 4 '17 at 18:11
  • For example, I have a document class for a form that my department requires. The input for the form is collected by a Google form and the class assigns the markup to the CSV data and formats the form(s). In this case, the students enter their data into the Google form, but a similar thing could be done with regular users entering into a Google sheet or Excel directly. – Alan Munn Aug 4 '17 at 18:15
  • 1
    @sam I guess my point is you're focusing (it seems) on the wrong thing, i.e., the automation, rather than the invoice design. Mock up a class first to format the fields you want, and then worry about the input later. Then the user document would be trivial: \documentclass{invoice}\InputFile{myfile.csv}\begin{document}\printinvoice\end{document} (which could itself be scripted if you wanted.) (Where \InputFile and \printinvoice are the only user commands of the class.) Everything else is taken from the CSV file using datatool and marked up and formatted by the class. – Alan Munn Aug 4 '17 at 19:15
11

Here's a sample of a standard US commercial invoice class which I hacked up a while ago. It defines some user commands for the invoice document, and takes the values for the invoice itself from a CSV file. The class itself formats everything, and the user document is very simple.

There are various ways in which this could be made better, but it should give you enough of a start to see how this kind of thing can be done.

Update (January 2019)

I've now packaged this as a document class, with support for multipage invoices, return address config files and documentation. It's available on CTAN and included in TeX Live and MikTeX.

invoice-class

% US Commericial Invoice Class
% Copyright 2008-2017 by Alan Munn amunn@msu.edu
%
% This class may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This package has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this package is Alan Munn amunn@msu.edu
%
\def\invc@date{2008/07/15}
\def\invc@version{1.0}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{invoice-class}[\invc@date\space  Commercial Invoice \invc@version]
\LoadClass[11pt]{article}
\RequirePackage[margin=1in]{geometry}
\RequirePackage{datatool}
\RequirePackage{multicol}
\RequirePackage{array}
\RequirePackage{tabularx}
\RequirePackage{dcolumn}
\RequirePackage{fancyhdr}
\renewcommand{\rmdefault}{\sfdefault}
\newcommand*{\invc@BL}[1]{\rule{#1}{.5pt}}
\newcommand*\invc@NL{\tabularnewline}
\newcolumntype{d}{D{.}{.}{6.2}}
\newcommand*{\invc@mc}{\multicolumn{1}{c|}}
\newcommand*{\invc@waybill}{
\fbox{\textbf{Waybill Number:} \invc@waybillnum}}
\newcommand*{\waybill}[1]{\gdef\invc@waybillnum{#1}}
\newcommand{\toaddress}[1]{\gdef\invc@toaddress{#1}}
\newcommand*{\destination}[1]{\gdef\invc@destination{#1}}
\newcommand*{\carrier}[1]{\gdef\invc@carrier{#1}}
\newcommand*{\InputFile}[1]{\gdef\invc@inputfile{#1}}
\newcommand*{\weight}[2]{\gdef\invc@pounds{#1}\gdef\invc@oz{#2}}
\newcommand*{\packages}[1]{\gdef\invc@packages{#1}}
\let\invc@shippingdate\today
% These could be made into user commands but if they are fixed, they can simply be
% hard coded as is done here
\newcommand{\invc@fromaddress}{%
The Duck Company\\
Some Avenue\\
Somewhere MI 48823\\
USA\\
Tel. 555-555-5555\\
}
\newcommand*{\invc@shipper}{Prof. van Duck}
\newcommand*{\invc@location}{Somewhere, MI}
%
\pagestyle{fancy}
\parindent=0pt
\lhead{}
\chead{\Large \sffamily \bfseries Commercial Invoice }
\rhead{}
\lfoot{}
\cfoot{\sffamily\thepage}
\rfoot{}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0pt}
\thispagestyle{fancy}
\sffamily
\newcommand{\printinvoice}{%
\invc@waybill
\begin{multicols}{2}

{\Large\bfseries From:}

\invc@fromaddress

\columnbreak

{\Large\bfseries To:}

\invc@toaddress
\end{multicols}

\setlength{\extrarowheight}{9pt}
\begin{tabularx}{\linewidth}{|*{4}{>{\centering}X|}}
\hline
\textbf{\scriptsize Country of ultimate destination:} & \textbf{\scriptsize Exporting Carrier} & \textbf{\scriptsize Total number of packages} & \textbf{\scriptsize Gross Weight} \invc@NL
\invc@destination & \invc@carrier &
\invc@packages & \invc@pounds~lb \invc@oz~oz \invc@NL
\hline
\end{tabularx}
%
\DTLloaddb{invoice}{\invc@inputfile}
\DTLsumcolumn{invoice}{Amount}{\invc@total}
\setlength{\extrarowheight}{3pt}
\begin{tabularx}{\linewidth}{|X|p{1in}|p{.75in}|d|d|}
\hline
\centering\bfseries Description & \centering\bfseries Country of Origin & \centering \bfseries Quantity &\invc@mc{\bfseries Unit Value\$} & \invc@mc{\bfseries Amount (USD)}\invc@NL
\hline
\DTLforeach{invoice}{%
\description=Description,\country=Country,\quantity=Quantity,\unitvalue=UnitValue,\amount=Amount}{%
\description & \country & \quantity & \unitvalue & \amount\\} & & & & \\\hline
\multicolumn{4}{|r|}{\bfseries Currency type and amount}& \DTLdecimaltocurrency{\invc@total}{\invc@subtotal}\invc@subtotal   \invc@NL
\multicolumn{4}{|r|}{\bfseries Packing cost} & \invc@NL
\multicolumn{4}{|r|}{\bfseries Shipping cost} & \invc@NL
\multicolumn{4}{|r|}{\bfseries Insurance cost} & \invc@NL
\hline\hline
\multicolumn{4}{|r|}{\bfseries Total Invoice Value} & \DTLdecimaltocurrency{\invc@total}{\invc@grandtotal}\invc@grandtotal \invc@NL
\hline
\end{tabularx}
\vskip 5ex
{\Large\bfseries Notes:}

{\footnotesize These commodities, technologies, or software were exported from the United States of
America in accordance with the Export Administration regulations. Diversion contrary to
U.S. law is prohibited.

It is hereby certified that this invoice shows: (1) the actual price of the goods described,
(2) that no other invoice has been or will be issued, and (3) that all particulars are true
and correct.}

\setlength{\extrarowheight}{18pt}
\begin{tabular}{|p{3in}|p{1.75in}|}
\hline
\textbf{\scriptsize Name:} \hskip 2em \invc@shipper & \textbf{\scriptsize Date:} \invc@shippingdate \invc@NL

\hline
\multicolumn{2}{|l|}{\textbf{\scriptsize Location:} \hskip 1em \invc@location}\invc@NL
\hline
\multicolumn{2}{|l|}{ \textbf{\scriptsize Signature:}}\invc@NL
\hline
\end{tabular}
}
\endinput

Sample user document

This is a sample user document. I've included the CSV file using filecontents but it would normally be an external file.

\documentclass{invoice-class}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.csv}
Description, Country, Quantity, UnitValue, Amount
Yellow Ducks, USA, 5, 2.00, 10.00
Pink Ducks, USA, 4, 15.00, 60.00
Blue Ducks, USA, 6, 5.00, 30.00
Orange Ducks, USA, 1, 4.00, 4.00
Red Ducks, USA, 30, 2.00, 60.00
\end{filecontents*}
\InputFile{\jobname.csv}
\waybill{8273205776}
\carrier{FedEx}
\destination{Brazil}
\toaddress{Paulo Cereda\\Rua Bonita\\Cidade de Patos\\SP\\Brazil}
\weight{1}{1}
\packages{1}
\begin{document}
\printinvoice
\end{document}

Output

enter image description here

  • 3
    @samcarter I think they may be unicorn ducks. Very rare. – Alan Munn Aug 4 '17 at 20:55
  • 1
    Are the red ducks Republican ducks and as such much cheaper than the blue ones ? ;-) – user31729 Aug 4 '17 at 21:18
  • 1
    @ChristianHupfer The ducks are apolitical. It is rumoured that the red ducks as Man United ducks, but this is just a rumour. Given their origin they are much more likely to be Red Wings ducks. – Alan Munn Aug 4 '17 at 21:48
  • 3
    Oh man, I love this community. You're always extremely helpful, have great ideas, which you all explain very well and on top of all this awesomeness, you're funny too. It's exactly that, what makes this community what it is! Thank you all and especially @AlanMunn for your time, your help and your friendliness! – Sam Aug 4 '17 at 22:54
  • 3
    @Sam Thanks for the kind words. And I agree, there are plenty of smart, friendly, and helpful people here. We've also become a bit duck mad, due to one particular smart, friendly, and helpful person. – Alan Munn Aug 5 '17 at 3:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.