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!

Sam
  • 2,958
  • 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 04 '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 04 '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 04 '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 04 '17 at 18:15
  • Okay, that's pretty nice, so this could be a step in the future, but I still need a way do define the complete design of the invoice. If the data is collected by an Excel sheet or by these lists shouldn't be relevant for this, or is it? – Sam Aug 04 '17 at 18:21
  • @Sam: Basically this comes down to provide something like \TagLineFormat etc. for each of your invoice data fields. This can be 'looped', but you would still have to provide some default formats –  Aug 04 '17 at 19:01
  • 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 04 '17 at 19:15
  • @AlanMunn I think I actually understood what you mean, but I don't see how to format the output. A .csv file only includes data, so it replaces the list of key/value pairs. As I said in my question, I don't know how to format the output without beginning the document. All I know is how to format things when defining a new environment or a newcommand which is then called in the main.tex But you don't use any of these methods, and I also don't want to use any of these, so how can I format the output in the class file? – Sam Aug 04 '17 at 19:46
  • Or is \printinvoice meant to be such a \newcommand which sets everything up? – Sam Aug 04 '17 at 19:53
  • Something like textmerg can be used in the same way. I use a spreadsheet to hold student data and calculate marks. At the end of the module, I save one sheet of this as a .csv file, feed that into a simple wrapper and a custom class produces a module assessment form for each student. All the formatting is done by the class. All the calculating is done by Calc. And it is much easier to see and assess the data during the semester in spreadsheet format. (Actually, I also pre-process the .csv into a .dat using a bash script, but this is not really important.) – cfr Aug 04 '17 at 22:08

1 Answers1

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

Alan Munn
  • 218,180