Many of the Moneydance classes and methods can be accessed with just a few commands on the Python console, and you can cut and paste many of the examples below to check out the methods in your environment. The methods below were choosen for their utility in writing report generators. They will be useful in most other programming too, such as those that modify Moneydance data. Once you understand the methods here, many others will be simple to learn.
When Moneydance reads a Jython program it feeds it through code that handles interactive input and that doesn't quite support normal Python syntax. For example, this program fails, first by complaining about a syntax error caused by a comment, and later by the last line having a syntax error:
def sq(i): # Comment that will cause a syntax error return i*i for i in range(3): print i, sq(i) print 'done'
The comment may be replaced by a blank line and that terminates the definition. Interactive mode needs a blank line to end the for statement, and that unindented print statement causes another syntax error. If you're loading a longish program, you can get a bizarre mix of errors and code execution that simply shouldn't execute. Don't use comment lines in indented code and terminate outermost multi-line statements with a blank line, e.g.:
def sq(i): pass # Comment that will pass Moneydance's Jython return i*i for i in range(3): print i, sq(i) print 'done'
ra = moneydance.getRootAccount()
The methods special to rootAccount are not very useful for writing reports, the methods for the generic account class are the useful ones. However, there are a couple:
>>> ra = moneydance.getRootAccount() >>> ra.getHighestAccountNum() 112 >>> acct = ra.getAccountById(112) >>> acct Elemental Holdings:Radium Arc Lamps >>> acct = ra.getAccountByName('elemental holdings')
>>> ra = moneydance.getRootAccount() >>> acct = ra.getAccountByName('checking') >>> print repr(acct) Checking >>> acct Checking
Useful methods:
>>> acct.getAccountName() 'Checking'
>>> pg = ra.getAccountByName('personal:groceries') >>> pg.getFullAccountName() 'Personal:Groceries' >>> pg.getAllAccountNames() array(['Personal', 'Groceries'], java.lang.String) >>> pg.getAllAccountNames()[0] 'Personal' >>> pg.getAllAccountNames()[1] 'Groceries' >>> pg.getDepth() 2 >>> acct.getDepth() 1 >>> ra.getDepth() 0
>>> acct.getAccountNum() 1
>>> acct.getBalance() 3541L >>> acct.getStartBalance() 0L
To get all the transactions associated with an account, you need to have the rootAccount search for them. Consider this checking account with a short register:
Date Chk Desc Account Payment Deposit Balance 1/01/2005 Dep Bossco Bonus 1,000.00 1,000.00 1/03/2005 Banke Savings 100.00 900.00 1/07/2005 1 CG Groceries 20.00 880.00 1/15/2005 2 Sitgo - 2 splits - 30.00 850.00 Split 1: Lunch Personal:Dining 10.00 Split 2: Gas Automotive:Fuel 20.00 1/31/2005 ATM Cash ATM Withdrawal 100.00 750.00
>>> txns = ra.getTransactionSet().getTransactionsForAccount(acct).getAllTxns() >>> txns com.moneydance.apps.md.model.TxnSet$TransactionEnumerator@1c9f8fb >>> for txn in txns: ... print repr(txn) ... [ParentTxn(12) desc=Cash; val=-10000; stat= ; #splits=1; chk=ATM; ... [ParentTxn(10) desc=Bank; val=-10000; stat= ; #splits=1; chk=; ... [ParentTxn(8) desc=CG; val=-2000; stat= ; #splits=1; chk=1; ... [ParentTxn(6) desc=Sitgo; val=-3000; stat= ; #splits=2; chk=2; ... [ParentTxn(3) desc=Bossco; val=100000; stat= ; #splits=1; chk=Dep; ...
The list of attributes displayed isn't complete and Moneydance doesn't let you access them directly, e.g. txn.val won't work. The attributes are accessed by various methods. Here are all the fields displayed above for the transactions with 2 splits with the method a program can use to get the values or a close relative:
Other useful methods include the following. Methods prefixed with txn. apply to the parent transaction (class ParentTxn) and sxn. apply to the first split transaction (class SplitTxn).
>>> txn.getMemo() 'Eat here and get gas.'
>>> txn.getOtherTxnCount() 2 >>> sxn.getOtherTxnCount() 1
>>> txn.getParentTxn() [ParentTxn(6) desc=Sitgo; val=-3000; ... >>> sxn.getParentTxn() [ParentTxn(6) desc=Sitgo; val=-3000; ...
>>> txn.getTransferType() 'xfrtp_bank' >>> sxn.getTransferType() 'xfrtp_bank' >>> txn.TRANSFER_TYPE_BANK 'xfrtp_bank'
Suppose we have an investment account called Elemental Holdings, which has two stocks from these transactions:
If we look at these via Mondydance:Security: Itanium Mining Date Dir Shares $/sh Value Balance 2005/04/01 Buy 10.0000 40.00 $400.00 10.0000 Security: Radium Arc Lamps Date Dir Shares $/sh Value Balance 2005/03/14 Buy 100.0000 3.14 $314.00 100.0000 Commission: $0.15
The last transaction has two splits, let's take a closer look at it as we look at some important methods.>>> acct = ra.getAccountByName('elemental holdings') >>> acct.getBalance() 0L >>> txns = ra.getTransactionSet().getTransactionsForAccount(acct).getAllTxns() >>> for txn in txns: ... print repr(txn) ... [ParentTxn(21) desc=Buy Shares; val=-40000; #splits=1; chk=; date=20050401; ... [SplitTxn(18) desc=Elemental Holdings; val=40000; rate=1.0; amt=-40000; val=40000; ] [SplitTxn(16) desc=Elemental Holdings; val=31415; rate=1.0; amt=-31415; val=31415; ] [ParentTxn(15) desc=Buy Shares; val=-31415; #splits=2; chk=; date=20050314; ...
>>> ts = ra.getTransactionSet() >>> txn =ts.getTxnByID(15) >>> txn.getSplitCount() 2 >>> sxn0 = txn.getSplit(0) >>> sxn1 = txn.getSplit(1)
>>> txn.getAccount() Elemental Holdings >>> sxn0.getAccount() Elemental Holdings:Radium Arc Lamps >>> sxn1.getAccount() Investment:Trading Commission
>>> txn.getValue() -31415L >>> sxn0.getValue() 1000000L >>> sxn1.getValue() 15L
>>> txn.getAmount() Traceback (innermost last): File "", line 1, in ? AttributeError: getAmount >>> sxn0.getAmount() -31400L >>> sxn1.getAmount() -15L
>>> sxn0.getRate() 31.84713375796178 >>> float(sxn0.getValue()) / sxn0.getAmount() -31.84713375796178 >>> sxn1.getRate() 1.0
You can get to an account's currency type from the Python console:
>>> acct = ra.getAccountByName('elemental holdings:itanium mining') >>> ct = acct.getCurrencyType() >>> chk = ra.getAccountByName('checking') >>> cct = chk.getCurrencyType()
>>> ct.getName() 'Itanium Mining' >>> ct.getIDString() '^itm' >>> cct.get() 'US Dollar' >>> cct.getIDString() 'USD'
>>> ct.getDecimalPlaces() 4 >>> cct.getDecimalPlaces() 2
>>> ct.format(123456789L, '.') '12345.6789' >>> ct.formatSemiFancy(123456789L, '.') '12,345.6789' >>> ct.formatFancy(123456789L, ',') 12.345,6789 itm Shares' >>> cct.formatFancy(123456789L, '.') '$ 1,234,567.89'
>>> ct.getRawRate() 4.0 >>> cct.getRawRate() 1.0
Moneydance date/time values are tracked as longs in 1,000ths of a day. Day zero follows Unix/Linux/Posix practice, so it's easy to work with date/time values with Python's time module.04/01/2005 $40.00 09/01/2005 $30.00 10/01/2005 $25.00
>>> import time >>> dt = (2005, 10, 1, 0, 0, 0, 0, 0, 0) >>> ct.getRawRateByDate(long(time.mktime(dt)) * 1000L) 3.333333333333333 >>> dt = (2005, 10, 2, 0, 0, 0, 0, 0, 0) >>> ct.getRawRateByDate(long(time.mktime(dt)) * 1000L) 4.0
Contact Ric Werme or visit his home page.
Last updated 2005 November 1.