Fin du QIF à la Société Générale
J'utilise GnuCash depuis une dizaine d'années pour tenir mes comptes. J'ai l'habitude d'importer le relevé des opérations au format QIF dans GnuCash. Or depuis la refonte du site Internet destiné aux particuliers, la Société Générale ne propose plus l'export du relevé des opération au format QIF. À la place, la banque au carré rouge et noir propose un fichier CSV contenant les opérations réalisées au cours des six derniers mois.
Contactée, la Société Générale m'a informé « ne pas pouvoir changer le format proposé par le site ».
Je constate qu'à l'image des GAFAM, la Société Générale cherche à capter les données de ses clients pour les exploiter et néglige leur partage avec ces mêmes clients qui en sont pourtant les propriétaires. Ainsi, le site Internet de la Société Générale propose d'importer des comptes externes, c'est-à-dire tenus dans d'autres établissements bancaires. Mais quiconque veut rapatrier ses données doit se contenter d'un fichier CSV réduit à la portion congrue.
Nous allons étudier les problèmes liés au fichier CSV fourni par la
Société Générale et développer ensemble l'esprit d'équipe une
solution pour faciliter son import dans GnuCash.
Du CSV à la française
Après avoir téléchargé le fichier CSV, observons ses propriétés :
$ file Export_17052019_16112019.csv Export_17052019_16112019.csv: ISO-8859 text, with CRLF line terminators
Le fichier est encodé en ISO 8859 et les retours à la ligne sont matérialisés par deux octets CR+LF comme il est d'usage sous Windows.
Que contiennent donc nos données ?
$ head Export_17052019_16112019.csv ="0201900016400270";17/05/2019;16/11/2019; date_comptabilisation;libellé_complet_operation;montant_operation;devise; 15/11/2019;CARTE X7527 15/11 METRO ;-14,90;EUR; 13/11/2019;VIR RECU 8527975563S DE: Boulot SAS MOTIF: BOULOT OCTOBRE 2019 33 REF: BOULOT OCTOBRE 2019 33;2188,28;EUR; 11/11/2019;PRELEVEMENT EUROPEEN 7997325297 DE: DODO GESTION ID: FR65ZZZ233162 MOTIF: 081 LOYER DODO;-614,50;EUR; 10/11/2019;CARTE X7527 10/11 RESTO ;-11,00;EUR; 09/11/2019;CARTE X7527 09/11 BRICO ;-14,50;EUR;
Nous avons affaire à la variante française du CSV qui utilise le point-virgule pour délimiter les colonnes et la virgule pour partager la partie entière et la partie décimale d'un nombre.
La première ligne débute par le numéro de compte. La notation
="0123"
est une astuce pour indiquer à Microsoft Excel de
préserver le zéro
au début d'un nombre. Suivent les dates de début et de fin des
données exportées. Les dates sont exprimées au format français
JJ/MM/AAAA.
La deuxième ligne contient les intitulés de colonnes qui sont donc la date de comptabilisation, le libellé de l'opération, son montant et la devise. Nous remarquons que la ligne se termine par un séparateur point-virgule inutile.
Nettoyer le fichier CSV avec Pandas
Après avoir observé les données, nous ouvrons notre boîte à outils d'apprenti Data Scientist. Nous choisissons Python et Pandas. Python est un langage de programmation qu'on ne présente plus : il est même enseigné au Lycée. Pandas est une bibliothèque Python destinée à la fouille de données. Python et Pandas, voilà une excellente compagnie pour le paresseux que je suis.
Charger
La bibliothèque Pandas fournit la fonction
read_csv()
avec de nombreux paramètres permettant de nettoyer le fichier CSV.
import pandas as pd df = pd.read_csv('Export_17052019_16112019.csv', sep=';', decimal=',', header=1, parse_dates=True, dayfirst=True, usecols=range(4), index_col=0, names=['date', 'description', 'amount', 'currency'], encoding='ISO-8859-1')
Parmi les paramètres :
-
sep
etdecimal
adaptent le comportement deread_csv()
pour la variante française du CSV. -
header
indique que la ligne des entêtes est la deuxième ligne (la première ligne ayant pour indice zéro). -
dayfirst
sélectionne le format de date européen où le jour apparaît avant le mois (les États-Unis fêtent Noël le 12/25). -
index_col
précise que la première colonne – la date – sert d'index.
La fonction read_csv()
retourne un objet de type
DataFrame
.
Voici son contenu affiché par Python :
>>> df description amount currency date 2019-11-15 CARTE X7527 15/11 METRO -14.90 EUR 2019-11-13 VIR RECU 8527975563S DE: Boulot SAS MOTIF: ... 2188.28 EUR 2019-11-11 PRELEVEMENT EUROPEEN 7997325297 DE: DODO GESTI... -614.50 EUR 2019-11-10 CARTE X7527 10/11 RESTO -11.00 EUR 2019-11-09 CARTE X7527 09/11 BRICO -14.50 EUR
Filtrer
La version précédente du site Internet de la Société Générale proposait d'exporter les transactions au format QIF depuis le dernier téléchargement. La nouvelle mouture propose un export au format CSV des transactions des six derniers mois.
Par conséquent, nous sommes désormais contraint de relever dans GnuCash la date de la dernière transaction déjà importée afin de filtrer les données CSV à importer et limiter les doublons.
La première colonne – la date – ayant été choisie comme index, l'opération se fait simplement avec un slice :
>>> df = df['2019-11-15':'2019-11-13'] >>> df description amount currency date 2019-11-15 CARTE X7527 15/11 METRO -14.90 EUR 2019-11-13 VIR RECU 8527975563S DE: Boulot SAS MOTIF: ... 2188.28 EUR
Distinguer les dépôts et les retraits
Le CSV exporté depuis le site Internet de la Société Générale comprend une seule colonne montant. Or GnuCash exige de distinguer dépôt et retrait.
Nous devons donc ajouter deux colonnes au tableau et les remplir à partir du montant.
Pour une transaction donnée :
- Si le montant est positif, il s'agit d'un dépôt. Nous copions la valeur du montant dans la colonne dépôt et nous écrivons zéro dans la colonne débit.
- Si le montant est négatif, il s'agit d'un retrait. Nous copions la valeur absolue du montant dans la colonne retrait et nous écrivons zéro dans la colonne dépôt.
Avec Pandas, les colonnes dépôt et retrait peuvent être calculées à partir du montant de la manière suivante :
df['deposit'] = df['amount'].apply(lambda x: x if x > 0 else 0) df['withdraw'] = df['amount'].apply(lambda x: abs(x) if x < 0 else 0)
En Python, le mot clé lambda définit une fonction anonyme. Dans la première instruction, la colonne dépôt est remplie en appliquant au montant la fonction qui pour x retourne x s'il est positif et 0 dans le cas contraire.
Voici à quoi ressemble notre tableau suite à l'ajout des colonnes dépôt et retrait :
description amount currency deposit withdraw date 2019-11-15 CARTE X7527 15/11 METRO -14.90 EUR 0.00 14.9 2019-11-13 VIR RECU 8527975563S DE: Boulot SAS MOTIF: ... 2188.28 EUR 2188.28 0.0
Exporter à destination de Gnucash
La méthode
to_csv()
permet de sauvegarder un DataFrame
dans un
fichier au format CSV.
df.to_csv('gnucash.csv', sep=';', decimal=',', columns=['description', 'deposit', 'withdraw'])
Seules sont exportées les colonnes utiles à GnuCash : date (implicite car il s'agit de l'index), description, dépôt, et retrait.
Notre fichier CSV « nettoyé » est prêt à être importé dans GnuCash.
Importer le fichier CSV final dans GnuCash
Dans l'interface graphique de GnuCash, nous cliquons sur : fichier → importer → importer des transactions depuis un CSV.
Après avoir sélectionné notre fichier CSV, GnuCash nous présente la fenêtre d'aperçu de l'import.
Nous appliquons les réglages suivants :
- Le point-virgule est défini comme séparateur de colonnes.
- La première ligne qui correspond à l'entête est ignorée.
- Le type des données de chaque colonne est précisé.
- Un compte cible est renseigné pour l'ensemble des transactions (champ account).
Le wiki de GnuCash décrit plus en détail comment importer des transactions au format CSV.
Pour aller plus loin
Le script csv-socgen.py reprend l'ensemble du code présenté ici. Il ne s'agit que d'un premier jet.
Le script mérite d'être amélioré pour remplir automatiquement le compte destinataire et modifier la description si elle correspond à un motif donné. Ainsi, le compte destinataire de la transaction ayant pour description METRO serait automatiquement renseigné en Dépenses:Transports publics:Métro. Remarquons que la banque affiche une catégorie pour chaque transaction sur son site Internet mais que cette information ne figure pas dans le fichier CSV. À nous de ruser.
Un ancien slogan de la Société Générale clamait « On est là pour vous aider ». Cette ambition a disparu en 2019 avec un slogan devenu « C'est vous l'avenir ». Alors, ne comptez que sur vous-même pour tenir vos comptes !