Using Ledger for Accounting in Org-mode with Babel
1. Introduction
Ledger is a double entry accounting system which uses simple text files for recording all transactions. As such, it is fundamentally compatible with org mode in Emacs. Using Babel, it is possible to record financial transactions conveniently in an org file and subsequently generate the financial reports required.
1.1. Getting Started
With a recent version of org (7.01+), Ledger support is provided. To use it, enable Ledger support. Check the Babel documentation on Worg for instructions on how to achieve this but I currently do this directly as follows:
(org-babel-do-load-languages 'org-babel-load-languages '((R . t) (ditaa . t) (dot . t) (emacs-lisp . t) (gnuplot . t) (haskell . nil) (latex . t) (ledger . t) ;this is the important one for this tutorial (ocaml . nil) (octave . t) (python . t) (ruby . t) (screen . nil) (sh . t) (sql . nil) (sqlite . t)))
Once Ledger support in Babel has been enabled, we can use proceed to include Ledger entries within an org file. There are three ways (at least) in which these can be included:
- place all Ledger entries within one source block and execute this block with different arguments to generate the appropriate reports;
- place Ledger entries in more than one source block and use the noweb literary programming approach, supported by babel, to combine these into one block elsewhere in the file for processing by Ledger; and,
- place Ledger entries in different source blocks and use tangling to generate a Ledger file which you can subsequently process using Ledger directly.
The first two are described in more detail in this short tutorial. This tutorial, however, only scratches the surface of what is possible in Ledger. For further information on Ledger, check out the project website.
2. Embedded Ledger example with single source block
The easiest, albeit possibly less useful, way in which to use Ledger within an org file is to use a single source block to record all Ledger entries. The following is an example source block:
#+name: allinone #+begin_src ledger 2010/01/01 * Starting balance assets:bank:savings £1300.00 income:starting balances 2010/07/22 * Got paid assets:bank:chequing £1000.00 income:salary 2010/07/23 Rent expenses:rent £500.00 assets:bank:chequing 2010/07/24 Food expenses:food £150.00 assets:bank:chequing 2010/07/31 * Interest on bank savings assets:bank:savings £3.53 income:interest 2010/07/31 * Transfer savings assets:bank:savings £250.00 assets:bank:chequing 2010/08/01 got paid again assets:bank:chequing £1000.00 income:salary #+end_src
In this example, we have combined both expenses and income into one
set of Ledger entries. We can now generate register and balance
reports (as well as many other types of reports) using babel to invoke
Ledger with specific arguments. The arguments are passed to Ledger
using the :cmdline
header argument. In the code block above, there is
no such argument so the system takes the default. For Ledger code
blocks, the default :cmdline
argument is bal
and the result of
evaluating this code block (C-c C-c
) would be:
#+results: allinone() : £2653.53 assets : £650.00 expenses : £-3303.53 income
If, instead, you wished to generate a register of all the
transactions, you would change the #+begin_src
line for the code block
to include the required command line option:
#+begin_src ledger :cmdline reg
Evaluating the code block again would generate a different report.
Having to change the actual directive on the code block and
re-evaluate makes it difficult to have more than one view of your
transactions and financial state. Eventually, babel will support
passing arguments to #+call
evaluations of code blocks but this
support is missing currently. Instead, we can use the concepts of
literary programming, as implemented by the noweb
features of babel,
to help us.
3. Multiple Ledger source blocks with noweb
The noweb
feature of babel allows us to expand references to other
code blocks within a code block. For Ledger, this can be used to
group transactions according to type, say, and then bring various
sets of transactions together to generate reports.
Using the same transactions used above, we could consider splitting these into expenses and income, as follows:
3.1. Income Entries
The first set of entries relates to income, either monthly pay or
interest, all typically going into one of my bank accounts. Here,
I have placed several entries, but we could have had each entry in
a separate src
block. Note that all code blocks you wish to refer
to later must have the :noweb yes
babel header argument specified.
#+name: income #+begin_src ledger :noweb yes 2010/01/01 * Starting balance assets:bank:savings £1300.00 income:starting balances 2010/07/22 * Got paid assets:bank:chequing £1000.00 income:salary 2010/07/31 * Interest on bank savings assets:bank:savings £3.53 income:interest 2010/07/31 * Transfer savings assets:bank:savings £250.00 assets:bank:chequing 2010/08/01 got paid again assets:bank:chequing £1000.00 income:salary #+end_src
3.2. Expenses
The following entries relate to personal expenses, such as rent
and food. Again, these have all been placed in a single src
block
but could have been done individually.
#+name: expenses #+begin_src ledger :noweb yes 2010/07/23 Rent expenses:rent £500.00 assets:bank:chequing 2010/07/24 Food expenses:food £150.00 assets:bank:chequing #+end_src
3.3. Financial Summaries
Given the ledger entries defined above in the income
and expenses
code blocks, we can now refer to these using the noweb
expansion
directives, <<name>>
. We can now define different code blocks to
generate specific reports for those transactions. Below are two
examples, one to generate a balance report and one to generate a
register report of all transactions.
3.3.1. An overall balance summary
The overall balance of your account and expenditure with a breakdown
according to category is specified by passing the :cmdline bal
argument
to Ledger. This code block can now be evaluated (C-c C-c
) and
the results generated by incorporating the transactions referred
to by the <<income>>
and <<expenses>>=
lines.
#+name: balance #+begin_src ledger :cmdline bal :noweb yes <<income>> <<expenses>> #+end_src #+results: balance : £2653.53 assets : £650.00 expenses : £-3303.53 income
If you want a more detailed breakdown of where your money is and where
it has been spent, you can specify the -s
flag (i.e. :cmdline -s bal
)
to tell Ledger to include sub-accounts in the report.
#+begin_src ledger :cmdline -s bal :noweb yes <<income>> <<expenses>> #+end_src #+results: : £2653.53 assets:bank : £1100.00 chequing : £1553.53 savings : £650.00 expenses : £150.00 food : £500.00 rent : £-3303.53 income : £-3.53 interest : £-2000.00 salary : £-1300.00 starting balances
3.3.2. Generating a monthly register
You can also generate a monthly register (the reg
command) by
executing the following src
block. This presents a summary of
transactions for each monthly period (the -M
argument) with a
running total in the final column (which should be 0 at the end
if all the entries are correct).
#+name: monthlyregister #+begin_src ledger :cmdline -M reg :noweb yes <<income>> <<expenses>> #+end_src #+results: monthlyregister :2010/01/01 - 2010/01/31 assets:bank:savings £1300.00 £1300.00 : in:starting balances £-1300.00 0 :2010/07/01 - 2010/07/31 assets:bank:chequing £100.00 £100.00 : assets:bank:savings £253.53 £353.53 : expenses:food £150.00 £503.53 : expenses:rent £500.00 £1003.53 : income:interest £-3.53 £1000.00 : income:salary £-1000.00 0 :2010/08/01 - 2010/08/01 assets:bank:chequing £1000.00 £1000.00 : income:salary £-1000.00 0
We could also generate a monthly report on our assets
showing how
these are increasing (or decreasing!). In this case, the final column
will be the running total of the assets
in our ledger.
#+name: monthlyassetsregister #+begin_src ledger :cmdline -M reg assets :noweb yes <<income>> <<expenses>> #+end_src #+results: monthlyassetsregister : 2010/01/01 - 2010/01/31 assets:bank:savings £1300.00 £1300.00 : 2010/07/01 - 2010/07/31 assets:bank:chequing £100.00 £1400.00 : assets:bank:savings £253.53 £1653.53 : 2010/08/01 - 2010/08/01 assets:bank:chequing £1000.00 £2653.53
4. Summary
This short tutorial shows how Ledger entries can be embedded in a org file and manipulated using Babel. However, only simple Ledger features have been illustrated; please refer to the Ledger documentation for examples of more complex integrations with a ledger.