Text file expense reports
July 5, 2006 at 10:37 PM by Dr. Drang
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:
- Tabs, which may seem the obvious choice for separating fields, don’t come naturally to me because I always set my editors to use spaces rather than tabs.
- Vertical bars are visible, so I can see at a glance whether I’ve put them in.
- Vertical bars aren’t a “normal” character; I have good reason to believe they’ll never be needed in any of the fields.
- Vertical bars are natural to me because I use them as separators in other programs. If you speak
tbl
, you’ll see that I use them to separate columns in the troff source code, too.
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.