;examples: csv: add an example python converter script
This commit is contained in:
parent
a6542e67db
commit
7a88130922
87
examples/csv/csv-hledger-1.py
Normal file
87
examples/csv/csv-hledger-1.py
Normal file
@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python3
|
||||
# An example of using Python to convert a certain CSV to hledger journal entries.
|
||||
# This won't work as-is (unless you have this particular kind of CSV);
|
||||
# use it for inspiration. hledger's own CSV rules are not used at all here.
|
||||
|
||||
|
||||
__version__ = "1.0"
|
||||
__author__ = "Simon Michael"
|
||||
|
||||
VERSION = "%prog " + __version__
|
||||
USAGE = """%prog [options] [CSVFILE [JOURNALFILE]]
|
||||
Reads a [certain kind of] CSV, writes a hledger journal.
|
||||
Journal entries will be in the same order as the CSV records.
|
||||
|
||||
Requirements: python 3.
|
||||
"""
|
||||
|
||||
# from pprint import pprint as pp
|
||||
import csv
|
||||
import datetime
|
||||
import optparse
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
# import warnings
|
||||
|
||||
def parse_options():
|
||||
parser = optparse.OptionParser(usage=USAGE, version=VERSION)
|
||||
opts, args = parser.parse_args()
|
||||
if len(args) > 2:
|
||||
parser.print_help()
|
||||
sys.exit()
|
||||
return opts, args
|
||||
|
||||
def single_space(ms):
|
||||
if ms is not None: ms = re.sub(r' +',' ',ms)
|
||||
return ms
|
||||
|
||||
# Join two strings with the give separator, but omit the separator
|
||||
# if either string is empty.
|
||||
def intercalate2(sep,astr,bstr):
|
||||
if astr and bstr:
|
||||
return astr + sep + bstr
|
||||
else:
|
||||
return astr + bstr
|
||||
|
||||
def main():
|
||||
opts, args = parse_options()
|
||||
out = open(args[1],'w') if len(args) > 1 else sys.stdout
|
||||
with open(args[0],'r') if len(args) > 0 else sys.stdin as csvfile:
|
||||
|
||||
# Process CSV records, and generate a hledger journal entry for each transaction.
|
||||
|
||||
for r in csv.reader(csvfile):
|
||||
|
||||
# skip headings (record containing no numbers)
|
||||
if all(map(lambda v: not any(c.isdigit() for c in v), r)): continue
|
||||
|
||||
# hledger doesn't like records with only one field
|
||||
if len(r) < 2: continue
|
||||
|
||||
# skip non-transaction records
|
||||
if re.match(r'^(Starting Balance|Net Change|Total|)$',r[0]): continue
|
||||
|
||||
# write a hledger journal entry
|
||||
property_,date_,payee_payer_,type_,reference_,debit_,credit_,balance_,description_,gl_account_ = r
|
||||
date = datetime.datetime.strptime(date_,"%m/%d/%Y").date().isoformat()
|
||||
code = f" ({reference_})" if reference_ else ""
|
||||
description = intercalate2(' | ', payee_payer_, intercalate2(' ', description_, type_))
|
||||
amount1 = f"${debit_}" if debit_ else ""
|
||||
amount2 = f"${credit_}" if credit_ else ""
|
||||
balance1 = balance_
|
||||
account1 = f"Properties:{property_}"
|
||||
if gl_account_[0].isdigit():
|
||||
account2 = f"{gl_account_[0]}xxx:{gl_account_}"
|
||||
else:
|
||||
account2 = f"{gl_account_}"
|
||||
account1, account2 = single_space(account1), single_space(account2)
|
||||
out.write(f"""\
|
||||
{date}{code} {description}
|
||||
{account1} {amount1} ; = {balance1}
|
||||
{account2} {amount2}
|
||||
|
||||
""")
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
Loading…
Reference in New Issue
Block a user