Text file expense reports

I suppose most people use spreadsheets to make their expense reports, and that makes sense for those who normally have a spreadsheet open. But I seldom use spreadsheets—I got out of the habit in the late ’90s when I switched to Linux; there were no good spreadsheets for Linux back then—so opening AppleWorks just to enter a few expenses seems wrong to me.

One application I do have open all the time is a text editor, sot I wrote this little Perl program, pexpense, to make and print an expense report from plain text input.

#!/usr/bin/perl

use Getopt::Std;

$logo = "$ENV{'HOME'}/mylogo.eps";
$name = "Dr. Drang";

$helpstring = <<'HELP';
pexpense -- Print out a formatted expense report based
            on structured input. Takes stdin or a file
            and prints to default printer. No options.

The input must be structured as follows:

project|date|description|amount

Note:   project can be G/B
        amount should not have a leading $
HELP

getopts('h');
die $helpstring if ($opt_h);

@mon = qw[January February March April May June
          July August September October November Decem];
@now = localtime;
$today = sprintf "%s %s, %4d", $mon[$now[4]], $now[3], $now[5]+1900;

# work through the input, building up the body of the table and keeping
# track of the total
$sum = 0;
while (<>) {
  chomp;
  ($proj, $date, $desc, $amt) = split /\|/;
  $sum += $amt;
  $amt = sprintf "%.2f", $amt;
  $tablebody .= "$proj|$date|$desc|$amt\n";
}
chomp $tablebody;
$sum = sprintf "\$%.2f", $sum;

# print out troff code for the page, process it, and send it to the
# printer
open PRINTER, "| groff -t | ps2pdf -";
select PRINTER;

print <<TROFF;
.vs 0
.po .5i
.ll 7.5i
.sp |.5i
.PSPIC -L $logo 1.5i .5i
.sp |.75i
.na
.ps 18
.ft HB
.ce 1
Expense report
.ft H
.sp |44p
.ps 10
.rj 3
$name
.sp |1i
$today
.ps 10
.vs 12
.sp |1.5i
.TS
center allbox tab(|);
cfHB|cfHB|cfHB|cfHB
c|c|lw(2.5i)|n.
Project|Date|Description|Amount
$tablebody
_
.T&
rfHB s s n.
Total|$sum
.TE
TROFF

The program takes the expense input, creates troff input, processes that with groff, and pipes the resulting PostScript to my printer. The results (with some generic changes) looks like this

The name and the (EPS) logo file can be easily changed in the lines near the top of the program. If you need to output, say, a PDF file change the line that looks like

open PRINTER, "| groff -t | lpr";

to

open PRINTER, "| groff -t | ps2pdf -";

which (assuming you have ps2pdf installed) will shoot the PDF onto standard output, where you can redirect it to a file or a printer.

As explained in the help message in the program, the format for each line of input is

project|date|description|amount

I use vertical bars to separate the fields because:

Until recently, I had trouble remembering the order of the fields. That’s why the help message is written so explicitly. But a week or so ago, I realized that Textmate’s snippets are the perfect solution to my faulty memory. I made this snippet

${1:G/B}|${2:`date +"%m"`}/${3:`date +"%d"`}`date +"/%y"`|
${4:description}|${5:0.00}
$0

(Don’t just cut and paste this. The first two lines are really one long line that I had to split to fit. The only real line break in the snippet is just before the $0.)

I gave this a Tab Trigger of exp. Now I don’t have to use the help message, the prompts are there for me as soon as I invoke the snippet. The defaults of “G/B” (general business) for the project and the current date for the date work well; they often don’t need to be changed. There are no good defaults (for me, at least) for the description and the amount, so I just set them to obvious prompts.

One more thing. TextMate has the Filter Through Command… item in the Text menu, so when I’m done entering expenses into a file, I select that item and, when the dialog box comes up, set the parameters like this

No need for the Terminal! By the time I walk over to the printer, the report is sitting in the output tray, waiting to be signed and stapled to my receipts. Although this took a bit of time to set up, I can’t imagine how a spreadsheet would be faster to use.

Tags: