GnuCash  5.6-150-g038405b370+
export_account_totals.py
1 #!/usr/bin/env python3
2 
3 # export_account_totals -- export the account totals of all accounts.
4 
5 # Copyright (C) 2020 Hong Xu <hong@topbug.net>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; either version 2 of
9 # the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # @author Hong Xu <hong@topbug.net>
17 
18 # Usage:
19 #
20 # python3 export_account_totals.py /path/to/gnucash_book_file > output.csv
21 
22 import copy
23 import sys
24 
25 from gnucash import GncNumeric, Session, SessionOpenMode
26 
27 
28 def get_all_sub_accounts(account, names=[]):
29  "Iterate over all sub accounts of a given account."
30 
31  for child in account.get_children_sorted():
32  child_names = names.copy()
33  child_names.append(child.GetName())
34  yield child, '::'.join(child_names)
35  yield from get_all_sub_accounts(child, child_names)
36 
37 
38 def to_string_with_decimal_point_placed(number: GncNumeric):
39  """Convert a GncNumeric to a string with decimal point placed if permissible.
40  Otherwise returns its fractional representation.
41  """
42 
43  number = copy.copy(number)
44  if not number.to_decimal(None):
45  return str(number)
46 
47  nominator = str(number.num())
48  point_place = str(number.denom()).count('0') # How many zeros in the denominator?
49  if point_place == 0:
50  return nominator
51 
52  if len(nominator) <= point_place: # prepending zeros if the nominator is too short
53  nominator = '0' * (point_place - len(nominator)) + nominator
54 
55  return '.'.join([nominator[:-point_place], nominator[-point_place:]])
56 
57 
58 if __name__ == '__main__':
59  print('Name,Commodity,Totals,Totals (USD)')
60  with Session(sys.argv[1], SessionOpenMode.SESSION_READ_ONLY) as session:
61  commodity_table = session.book.get_table()
62  USD = commodity_table.lookup("ISO4217", "USD")
63  root_account = session.book.get_root_account()
64  for account, account_name in get_all_sub_accounts(root_account):
65  print(','.join([account_name,
66  account.GetCommodity().get_mnemonic(),
67  to_string_with_decimal_point_placed(account.GetBalance()),
68  to_string_with_decimal_point_placed(account.GetBalanceInCurrency(USD, True))
69  ]))