-
Notifications
You must be signed in to change notification settings - Fork 2
/
convertBNP.py
243 lines (215 loc) · 8.96 KB
/
convertBNP.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# nom convertBNP.py
# description Lit les relevés bancaires de la BNP en PDF dans le répertoire courant pour en générer des CSV
# Nécessite le fichier pdftotext.exe en version 3.03 issu de l'archive xpdf (gratuit, GPL2)
# ------------------
# 10-nov-2013 v1 pour python3
# 26-nov-2014 v1.1 ajout de la version "_4col" qui sépare crédit et débits en 2 colonnes distinctes
# 28-jan-2015 v1.2 correction du bug "Mixing iteration and read methods would lose data"
# ------------------
# chaque opération bancaire contient 3 éléments :
#
# - date : string de type 'JJ/MM/AAAA'
# - description de l'opération : string
# - valeur : string (négatif si débit, positif si crédit)
#
# fichiers PDF de la forme RCHQ_101_300040012300001234567_20131026_2153.PDF
PREFIXE_COMPTE = "RCHQ_101_300040012300001234567_"
PREFIXE_CSV = "Relevé BNP "
CSV_SEP = ";"
import os, subprocess
class uneOperation:
"""Une opération bancaire = une date, un descriptif,
une valeur (négative=débit, positive=crédit) et un interrupteur de validité"""
def __init__(self, date="", desc="", valeur=""):
self.date = date
self.desc = desc
self.valeur = valeur
self.valide = True
if not len(self.date) == 10 or int(self.date[:2]) > 31 or int(self.date[3:4]) > 12 or valeur == 0:
self.valide = False
class UnReleve:
"""Un relevé de compte est une liste d'opérations bancaires
sur une durée définie"""
def __init__(self, nom="inconnu"):
self.nom = nom
self.liste = []
def ajoute(self, Ope):
"""Ajoute une opération à la fin de la liste du relevé bancaire"""
self.liste.append(Ope)
def ajoute_from_TXT(self, fichier_txt, annee, mois):
"""Parse un fichier TXT pour en extraire les
opérations bancaires et les mettre dans le relevé"""
print('[txt-> ] Lecture : '+fichier_txt)
with open(fichier_txt) as file:
date = ""
for ligne in file:
date_ou_pas = ligne[:12].split() # premier caractères de la ligne (date?)
dernier = ligne[-14::].split() # derniers caractètres (valeur?)
if estDate(date_ou_pas): # est-ce une date
date = date_ou_pas
operation = []
if date : # si on a deja trouvé une date
if not estArgent(dernier) : # nom d'opération en plusieurs lignes, ceci n'est pas la dernière
operation.extend(ligne[12:64].split())
else: # dernière ligne, avec une valeur
operation.extend(ligne[12:64].split())
la_date = list2date(date, annee, mois)
l_operation = ' '.join(operation)
la_valeur = list2valeur(dernier)
date = "" # on repart à la recherche d'une date
if len(ligne) < 180:
la_valeur = "-" + la_valeur
Ope = uneOperation(la_date, l_operation, la_valeur) # on crée l'opération bancaire
if Ope.valide:
self.ajoute(Ope) # et on l'ajoute au relevé
def genere_CSV(self, filename=""):
"""crée un fichier CSV qui contiendra les opérations du relevé
si ce CSV n'existe pas deja"""
if filename == "":
filename = self.nom
filename = filename + ".csv"
if not filename in deja_en_csv:
print('[ ->csv] Export : '+filename)
with open(filename, "w") as file:
file.write("Date"+CSV_SEP+"Opération"+CSV_SEP+"Valeur\n")
for Ope in self.liste:
file.write(Ope.date+CSV_SEP+Ope.desc+CSV_SEP+Ope.valeur+"\n")
file.close()
def extraction_PDF(pdf_file, deja_en_txt, temp):
"""Lit un relevé PDF et le convertit en fichier TXT du même nom
s'il n'existe pas deja"""
txt_file = pdf_file[:-3]+"txt"
if not txt_file in deja_en_txt:
print('[pdf->txt] Conversion : '+pdf_file)
subprocess.call(['pdftotext.exe', '-layout', pdf_file, txt_file])
temp.append(txt_file)
def estDate(liste):
if len(liste) != 3:
return False
if len(liste[0]) == 2 and len(liste[1]) == 1 and len(liste[2]) == 2:
return True
else:
return False
def estArgent(liste):
if len(liste) < 3:
return False
if liste[-2] == ',':
return True
else:
return False
def list2date(liste, annee, mois):
"""renvoie un string"""
if mois == '01' and liste[2] == '12':
return liste[0]+'/'+liste[2]+'/'+str(int(annee)-1)
else:
return liste[0]+'/'+liste[2]+'/'+annee
def list2valeur(liste):
"""renvoie un string"""
liste_ok = [x for x in liste if x != '.']
return "".join(liste_ok)
def filtrer(liste, filetype):
"""Renvoie les fichiers qui correspondent à l'estension donnée en paramètre"""
files = [fich for fich in liste if str.lower(fich[-3::])==filetype]
return files
def mois_dispos(liste):
"""Renvoie une liste des relevés disponibles de la forme
[['2012', '10', '11', '12']['2013', '01', '02', '03', '04']]"""
liste_tout = []
les_annees = []
for releve in liste:
if releve[:len(PREFIXE_COMPTE)] == PREFIXE_COMPTE:
annee = releve[len(PREFIXE_COMPTE):len(PREFIXE_COMPTE)+4]
mois = releve[len(PREFIXE_COMPTE)+4:len(PREFIXE_COMPTE)+6]
if not annee in les_annees:
les_annees.append(annee)
liste_annee = [annee, mois]
liste_tout.append(liste_annee)
else:
liste_tout[les_annees.index(annee)].append(mois)
return liste_tout
# fonction inutilisée
def est_dispo(annee, mois, liste):
"""Verifie si le relevé de ce mois/année est disponible
dans la liste donnée"""
for annee_de_liste in liste:
if annee == annee_de_liste[0]:
if mois in annee_de_liste:
return True
return False
def affiche(liste):
"""Affiche à l'écran les mois dont les relevés sont disponibles"""
print("Relevés disponibles:")
for annee in liste:
ligne_12 = [' ']*12
for i in annee:
if len(i) == 2:
ligne_12[int(i)-1] = i
ligne = annee[0]+': '+' '.join(ligne_12)
print(ligne)
print("")
# On demarre ici
print('\n******************************************************')
print('* Convertisseur de relevés bancaires BNP Paribas *')
print('******************** PDF -> CSV ********************\n')
chemin=os.getcwd()
fichiers = os.listdir(chemin)
if not "pdftotext.exe" in fichiers:
print("Fichier pdftotext.exe absent !")
input("Bye bye :(")
exit()
mes_pdfs = filtrer(fichiers, 'pdf')
deja_en_txt = filtrer(fichiers, 'txt')
deja_en_csv = filtrer(fichiers, 'csv')
mes_mois_disponibles = mois_dispos(mes_pdfs)
mes_mois_deja_en_txt = mois_dispos(deja_en_txt)
if len(mes_mois_disponibles) == 0:
print("Il n'y a pas de relevés de compte en PDF dans ce répertoire")
print("correspondant au préfixe "+PREFIXE_COMPTE)
print("\nIl faut placer les fichiers convertBNP.py et pdftotext.exe")
print("à côté des fichiers de relevé de compte en PDF et adapter")
print("la ligne 18 (PREFIXE_COMPTE = XXXXX) du fichier convertBNP.py")
print("pour la faire correspondre à votre numéro de compte.\n")
input("Bye bye :(")
exit()
affiche(mes_mois_disponibles)
touch = 0
temp_list = []
# on convertit tous les nouveaux relevés PDF en TXT sauf si CSV deja dispo
for releve in mes_pdfs:
if releve[:len(PREFIXE_COMPTE)] == PREFIXE_COMPTE:
annee = releve[len(PREFIXE_COMPTE):len(PREFIXE_COMPTE)+4]
mois = releve[len(PREFIXE_COMPTE)+4:len(PREFIXE_COMPTE)+6]
csv = PREFIXE_CSV+annee+'-'+mois+".csv"
if not csv in deja_en_csv:
touch = touch + 1
extraction_PDF(releve, deja_en_txt, temp_list)
if touch != 0:
print("")
# on remet à jour la liste de TXT
fichiers = os.listdir(chemin)
deja_en_txt = filtrer(fichiers, 'txt')
mes_mois_deja_en_txt = mois_dispos(deja_en_txt)
# on convertit tous les nouveaux TXT en CSV
for txt in deja_en_txt:
if txt[:len(PREFIXE_COMPTE)] == PREFIXE_COMPTE:
annee = txt[len(PREFIXE_COMPTE):len(PREFIXE_COMPTE)+4]
mois = txt[len(PREFIXE_COMPTE)+4:len(PREFIXE_COMPTE)+6]
csv = PREFIXE_CSV+annee+'-'+mois+".csv"
if not csv in deja_en_csv:
releve = UnReleve()
releve.ajoute_from_TXT(txt, annee, mois)
releve.genere_CSV(PREFIXE_CSV+annee+'-'+mois)
# on efface les fichiers TXT
if len(temp_list) :
print("[txt-> x ] Nettoyage\n")
for txt in temp_list:
os.remove(txt)
if touch == 0:
input("Pas de nouveau relevé. Bye bye.")
else:
print(str(touch)+" relevés de comptes convertis.")
input("Terminé. Bye bye.")
# EOF