Gnucash: Some gnucash-parsing utilities
The following is an unconverted doc.txt file.
1 How To Use It
The very simplest way to see how it works is to take a look at the examples directory: it contains a simple example gnucash file, and a simple racket file with plenty of comments that opens the gnucash file and pulls out a few of the transactions in the file. If you still have questions, come back and read this file.
2 How to Use It (part II):
The library consists of two files. One reads in the data (parse.rkt), and one has some utility functions for handling it.
(require (planet clements/gnucash:1:3/parse)) |
(gnucash-read gnucash-file gnucash-zo-file) → true gnucash-file : path-string? gnucash-zo-file : path-string?
If the source file is newer than the zo file, it goes and recompiles the darn thing.
You probably won’t need to call any other functions in parse.rkt.
A Note On Representations:
Darn near everything in this library is represented using plain-old racket lists, and more specifically SXML representations. The up side of this is that you can "display" nearly everything transparently. The down side of this is that you will curse and scream at a bunch of errors that would be caught by any kind of type system or use of structures, e.g. using an account instead of an account id, etc.
I’m not even going to try to document a significant subset of the functions in lib.rkt; they’re mostly like this one:
> (transaction-splits t)
Returns the splits associated with the transaction
> (transaction-date t)
Returns the date associated with the transaction
Here’s one worth mentioning:
> (crossers transactions account-ids)
For most kinds of graphing/reporting/munging/etc., you will want to choose a set of accounts and look for all transactions that "cross the line", in the sense that they transfer money from that set of accounts to something else. More accurately, you want transactions where at least one split is inside the set of accounts, and where at least one split is outside the set of accounts.
Why is this? Well, imagine you have a checking account and a credit card. You want to take a look at what you’re spending your money on. You’d like to lump together the checking account and the credit card account and take a look at the money coming into or out of these two accounts, while ignoring transfers between these two. This is what "crossers" is for.
Please do note that the "account-ids" is a list of ids (that is, strings), and not accounts. The example file shows this happening.
Example.rkt:
Just to save you time bouncing around, I’ll include the content of the "example.rkt" file here. Naturally, the danger here is that this might get out of sync; nevertheless, I’ll leave it here to save navigating your planet cache:
#lang racket ;; replace these with PLaneT requires if you use this as a template somewhere else: (require "../libs.rkt" "../parse.rkt") ;; I don't know how to find the current path effectively... so I'll just assume that you started Racket in the ;; examples path. (define here-path ".") ;; Let's just check to make sure this is okay... (unless (file-exists? (build-path here-path "sample-gnucash-file")) (error 'gnucash-example "Due to hurried programming, this example can only be run when the current directory is the one containing the sample file.")) ;; ordinarily, the source file would be in some other directory... (define gnucash-file-source (build-path here-path "sample-gnucash-file")) (define gnucash-zo-file (build-path here-path "sample-gnucash.zo")) ;; this will take a very long time the first time you call it on a sizeable gnucash file. ;; my gnucash file is about 19 Meg after unzipping, and the translation to a .zo file takes ;; almost 3 minutes on my intel laptop. (init-libs (time (gnucash-read gnucash-file-source gnucash-zo-file))) ;; show all the account names (printf "Account names: ~v\n" (map account-name-path accounts)) ;; locate the id for the checking account (define checking-account-id (account-id (find-account `("Assets" "Current Assets" "Checking Account")))) ;; find all the transactions into or out of "Assets:Current Assets:Checking Account" (define my-transactions (crossers transactions (list checking-account-id))) ;; display their dates and the net flow into or out of the checking account (printf "Net Flows: ~v\n" (map (lambda (t) (list (transaction-date t) (net t (list checking-account-id) dollars))) my-transactions))
Well, that’s about all I have to say for now. Let me know if you find it useful or if it makes you grind your teeth.
John Clements, 2007-08