-
Notifications
You must be signed in to change notification settings - Fork 2
/
ynab_danske_bank.py
executable file
·127 lines (106 loc) · 4.9 KB
/
ynab_danske_bank.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python3
# -*- coding: ISO-8859-1 -*-
import os
import argparse
from collections import OrderedDict
import codecs
from functools import reduce
from operator import concat
import re
# Author: Stefan McKinnon Edwards
# Date: April 2018
# Converts a CSV file from Danske Bank for import to YNAB4.
#
# Reads a CSV file from Danske Bank and outputs
# either a QIF (or quiz? or, I forget) file
# or a CSV file for YNAB.
# Output CSV header:
# Date,Payee,Category,Memo,Outflow,Inflow
# Input CSV header:
# "Dato";"Tekst";"Beløb";"Saldo";"Status";"Afstemt"
class Transaction_DK(object):
def __init__(self, Date, Payee, Category='', Memo='', amount_str=0.0, Cleared=True):
self.Date = Date.replace('.','/')
self.Payee = re.sub('[ ]+[)]+','', Payee)
self.Payee_raw = Payee
self.Category = Category
self.Memo = Memo
self.Cleared = Cleared
self.flow = float(amount_str.replace('.','', 1).replace(',','.', 1))
if (self.flow < 0.0):
self.Outflow = abs(self.flow)
self.Inflow = 0.0
else:
self.Outflow = 0.0
self.Inflow = self.flow
def csv(self):
o = '{}'.format(self.Outflow) if self.Outflow > 0.0 else ''
i = '{}'.format(self.Inflow) if self.Inflow > 0.0 else ''
s = '{!s},{!s},{!s},{!s},{},{}'.format(self.Date, self.Payee.replace(',',''), self.Category, self.Memo, o, i)
return s
def qif(self):
c = '*' if self.Cleared else ' '
s = 'D{}\nT{:+.2f}\nP{}\nC{}\n^\n'.format(self.Date, self.flow, self.Payee, c)
return s
def reader(line, filter=True, stats=('Udført',), cleared=('Udført',), notcleared=('Venter',), verbose=0, lineno=0):
line = [s.strip('"') for s in line.rstrip().split(';')]
if filter and not line[4] in stats:
return None
if not filter:
is_cleared = line[4] in cleared
if verbose > 0 and not is_cleared and line[4] not in notcleared:
print('Did not recognize cleared state ("{}") on line {}.'.format(line[4], lineno))
t = Transaction_DK(line[0], line[1], amount_str=line[2], Cleared=is_cleared)
return t
'''
'''
def main(inp, outp, as_qif=False, verbose=0, qifopt=None):
with codecs.open(inp, encoding='latin1') as fin:
l1 = fin.readline().rstrip()
fields = [s.strip('"') for s in l1.split(';')]
if fields != ['Dato', 'Tekst', 'Bel\xf8b', 'Saldo', 'Status', 'Afstemt']:
print(fields)
raise ValueError('Downloadet CSV fil har ikke den rigtige første linje')
with codecs.open(outp, 'w', encoding='latin1') as fout:
i = 0
j = 0
if not as_qif:
fout.write('Date,Payee,Category,Memo,Outflow,Inflow\n')
for line in fin:
j += 1
transaction = reader(line, verbose=verbose, lineno=j)
if transaction is not None:
print(transaction.csv(), file=fout)
i += 1
else:
if qifopt is None:
qifopt = {'header':'Bank'}
fout.write('!Type:{}\n'.format(qifopt['header']))
for line in fin:
transaction = reader(line, filter=False, verbose=verbose, lineno=j)
if transaction is not None:
print(transaction.qif(), file=fout)
i += 1
if verbose > 0:
print('Converted',i,'lines.')
print('Output written to',outp)
def make_output_name(input, qif=False, suffix='_ynab'):
output, ext = os.path.splitext(input)
if ext == '.csv' and qif == False or ext == '.qif' and qif == True:
return output + suffix + ext
ext = '.qif' if qif else '.csv'
return output + ext
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Converts Danske Bank CSV files to YNAB formats.')
parser.add_argument('input', help='Input filename, the CSV file from Danske Bank.')
parser.add_argument('output', nargs='?', help='Output filename')
parser.add_argument('-q','--qif', help='Output in QUICKEN format. Changes filtering', action='store_true')
parser.add_argument('-qt', help='Modify "!Type" header in output file (Default: "Bank").', default="Bank", metavar='header type')
parser.add_argument('--verbose', '-v', default=1, help='Verbose, adds logging output for your convenience.', action='count')
parser.add_argument('--suffix', default='_ynab', help='Suffix to filename when input and output files are both CSV.')
args = parser.parse_args()
if args.output is None:
args.output = make_output_name(args.input, qif=args.qif, suffix=args.suffix)
if args.qif:
qifopt = {'header':args.qt}
main(args.input, args.output, as_qif=args.qif, verbose=args.verbose, qifopt=qifopt)