Connexion

Forum

Logiciels » Bureautique [Réglé] export via fichier *.QIF besoin d'un petit script ?

bal1 Membre non connecté

Rang

Avatar

Inscrit le : 22/01/2013 à 20h26

Localisation : Besançon - France

Messages: 284

Le 29/04/2019 à 21h10

Reprise du message précédent

magnux77 :
"je m'amuse" signifie que je ne fais rien de sérieux avec Eiffel, juste se frotter à l'application rugueuse de principes de programmation modernes : peut être un brin de masochisme ?

J'ai raté l'attachement du fichier 'cahier des charges' annoncé : heureusement car il est inexact !
Avec mes premières tentatives, je m'aperçois que la structure est plus complexe avec l'apparition de temps en temps d'une valeur N supplémentaire entre C et P.
Je mets au point et je renvoie.



:merci:
Alain
Tour LDLC Frakass [CM :ASROCK H81M-HDS Celeron 2800 Ghz RAM 4 Go SSD 120 Go HDD 160 Go]
Mageïa 6 x86-64 bureau Xfce4 + VirtualBox Mageïa 6 x86-64 bureau LXQT
   
Jybz Membre non connecté

Rang

Avatar

Modérateur

Inscrit le : 10/10/2018 à 10h26

Messages: 1852

Le 30/04/2019 à 07h16
bal1 :
J'ai rédiger mon cahier des charges et je le joins pour ceux que ça peut intéresser.
J'arrive au traitement suivant façon Eiffel

from début du fichier
until fin du fichier
loop
- lire une ligne du fichier QIF (donc un champ)
- analyser le 1er caractère selon la valeur : ne rien faire ou traiter le contenu
end

traiter le contenu :
- si 1er caractère = ^ -> écrire une ligne de sortie
- sinon supprimer le 1er caractère et ranger le reste dans une variable choisie selon la valeur du 1er caractère

écrire la ligne de sortie : (avec les variables dans l'ordre correcte donné par list_var)
from list_var.start
until list_var.exhausted
loop
écrire l'item de list_var le fichier CSV
if dernier item
écrire 'fin de ligne'
else
écrire ';'
end
list_var.forth
end


Pour moi, ce n'est pas un cahier des charges, mais un protocole.
Si je devais donner un "cahier des charges" (toujours mon avis) ça serait :

Le script doit transformer un QIF en CSV,
il doit reconnaitre toutes les colonnes susceptibles d'être contenu dans un fichier QIF.
Le fichier CSV résultat ne doit pas obligatoirement prendre en compte une ligne d'entête.
Le séparateur peut être un caractère choisit en paramètre, mais par défaut prendra le caractère ','.
De préférence, le script est écrit en Eiffel (par ailleurs, je n'ai jamais entendu parlé de ce langage. Suis-je trop jeune ?).

bal1 :
[...]J'ai raté l'attachement du fichier 'cahier des charges' annoncé : heureusement car il est inexact !
[...]

Ah j'ai loupé cette ligne, je viens de la voir qu'après avoir écrit tout ça :D Bon, tant pis !

Papoteur :
Voici un exemple plus précis, et vérifié :
Code PYTHON :
with open("fichier_qif.txt", 'r') as f:
    debut = True
    nouvelle_ligne = True
    for l in f.readlines():
        if nouvelle_ligne:
            #on initialise la variable contenant une ligne de sortie à chaque début de ligne
            nouvelle_ligne = False
            sortie = {'D':'','T':'', 'C':'', 'P':'', 'M':'', 'L':''}
        if l[:1] == "^":
            # On a atteint la fin de la (première) ligne
            # Fin de la ligne, on la sort
            if debut:
                debut = False
            else:
                print("{D};{T};{C};{P};{M};{L}".format(D=sortie['D'],T=sortie['T'],C=sortie['C'],P=sortie['P'],M=sortie['M'],L=sortie['L'],))
                nouvelle_ligne = True
 
        else:
            sortie[l[:1]] = l[1:-1]
 
 


Pas mal ! Il m'a fallut un certain temps pour comprendre (je n'avais pas suivit le "else" du premier "if", donc au début je croyais que les variables se définissait par magie :D mais je suis bluffé par cette utilisation de tableau à deux dimension, ça m'a l'air assez simple ! (ne réécrases tu pas le caractère d'indice 1 ?)

bal1 :
[...]Avec mes premières tentatives, je m'aperçois que la structure est plus complexe avec l'apparition de temps en temps d'une valeur N supplémentaire entre C et P.[...]

Tu as de la chance qu'avec le script python de Papoteur, il ne suffit que de rajouter "le champs N entre C et P"; soit un changement dans ces lignes :
Code PYTHON :
[...]
            sortie = {'D':'','T':'', 'C':'', 'P':'', 'M':'', 'L':''}
[...]
                print("{D};{T};{C};{P};{M};{L}".format(D=sortie['D'],T=sortie['T'],C=sortie['C'],P=sortie['P'],M=sortie['M'],L=sortie['L'],))
[...]

en
Code PYTHON :
[...]
            sortie = {'D':'','T':'', 'C':'', 'N':'', 'P':'', 'M':'', 'L':''}
[...]
                print("{D};{T};{C};{N};{P};{M};{L}".format(D=sortie['D'],T=sortie['T'],C=sortie['C'],N=sortie['N'],P=sortie['P'],M=sortie['M'],L=sortie['L'],))
[...]


EDIT : J'ai oublié un morceau de code dans la seconde ligne a modifié :D Edité par Jybz Le 30/04/2019 à 10h01
   
bal1 Membre non connecté

Rang

Avatar

Inscrit le : 22/01/2013 à 20h26

Localisation : Besançon - France

Messages: 284

Le 30/04/2019 à 09h49
Bravo, quelle compacité !
Je suppose que l'on peut mettre les champs en sortie dans l'ordre que l'on veut ? exemple ci-dessous
print("{D};{C};{P};{N};{M};{T};{L}".format(D=sortie['D'],C=sortie['C'],P=sortie['P'],T=sortie['N'],M=sortie['M'],T=sortie['T'],L=sortie['L'],))

Un bémol sur la lisibilité du code pour les nuls en Python, un code Eiffel c'est du BASIC en comparaison :
If booléen then from initialisation
mon code until stop
else loop
autre code mon code
end end

Comme je suis tenace, je termine le programme Eiffel et je le poste.

Non, Jybz tu n'es pas trop jeune, peut être trop formaté : Eiffel est un langage totalement typé, fonctionnel, ,orienté objet, à héritage multiple.
Il existe un IDE très puissant StudioEiffel gratuit : le développement est fait en interpréteur et bytecode pour la rapidité des mises à jour, et les applications finales sont compilés en exécutable (pas besoin de la bonne version du bytecode sur la machine d'éxécution).




:merci:
Alain
Tour LDLC Frakass [CM :ASROCK H81M-HDS Celeron 2800 Ghz RAM 4 Go SSD 120 Go HDD 160 Go]
Mageïa 6 x86-64 bureau Xfce4 + VirtualBox Mageïa 6 x86-64 bureau LXQT
   
Jybz Membre non connecté

Rang

Avatar

Modérateur

Inscrit le : 10/10/2018 à 10h26

Messages: 1852

Le 30/04/2019 à 10h04
bal1 :

Je suppose que l'on peut mettre les champs en sortie dans l'ordre que l'on veut ? exemple ci-dessous
print("{D};{C};{P};{N};{M};{T};{L}".format(D=sortie['D'],C=sortie['C'],P=sortie['P'],T=sortie['N'],M=sortie['M'],T=sortie['T'],L=sortie['L'],))

Oui exactement ! (enfin, je n'ai pas vérifier.)

bal1 :

Comme je suis tenace, je termine le programme Eiffel et je le poste.

Avec plaisir !

bal1 :

Non, Jybz tu n'es pas trop jeune, peut être trop formaté : Eiffel est un langage totalement typé, fonctionnel, ,orienté objet, à héritage multiple.

Oh, ma spécialité c'est le C, donc je n'aurais pas dit que Eiffel soit trop formaté ^^

   
Papoteur Membre non connecté

Rang

Avatar

Modérateur Équipe Mageia

Inscrit le : 03/10/2011 à 22h16

Localisation : Metz

Messages: 6715

Le 30/04/2019 à 11h03
bal1 :
Bravo, quelle compacité !
Je suppose que l'on peut mettre les champs en sortie dans l'ordre que l'on veut ? exemple ci-dessous
print("{D};{C};{P};{N};{M};{T};{L}".format(D=sortie['D'],C=sortie['C'],P=sortie['P'],T=sortie['N'],M=sortie['M'],T=sortie['T'],L=sortie['L'],))


Oui, mais attention, la ligne ci-dessus générera une erreur ou une mauvaise sortie. Tu définis deux fois T=... mais tu utilises {N} que tu n'as pas défini dans le format().
Si tu veux changer l'ordre des colonnes, il suffit de le faire dans la chaîne avec les accolades.
Une autre option est de paramétrer l'indice des colonnes:
Code PYTHON :
debut_sortie = True
for indice in ('D','C','P', 'N', 'M','T','L'):
   if debut_sortie:
      # pas de séparateur pour le premier. On initialise une chaîne s
      s = '{}'.format(sortie[indice])
      debut_sortie = False
   else:
      # avec un séparateur. On complète la chaîne s
      s += ';{}'.format(sortie[indice])
print(s)

Edité par Papoteur Le 30/04/2019 à 11h04


Yves
   
Papoteur Membre non connecté

Rang

Avatar

Modérateur Équipe Mageia

Inscrit le : 03/10/2011 à 22h16

Localisation : Metz

Messages: 6715

Le 30/04/2019 à 11h16
Jybz :
mais je suis bluffé par cette utilisation de tableau à deux dimension, ça m'a l'air assez simple ! (ne réécrases tu pas le caractère d'indice 1 ?)

Je ne comprends pas ce que tu appelles un tableau à deux dimensions.
Non, je n'écrase rien. Je ne fais que lire le premier caractère avec l[:1] (jusqu'à l'indice 1 exclus) ou lire à partir du deuxième (1: ) sauf le dernier ( :-1 )


Yves
   
Jybz Membre non connecté

Rang

Avatar

Modérateur

Inscrit le : 10/10/2018 à 10h26

Messages: 1852

Le 30/04/2019 à 11h26
Papoteur :
Jybz :
mais je suis bluffé par cette utilisation de tableau à deux dimension, ça m'a l'air assez simple ! (ne réécrases tu pas le caractère d'indice 1 ?)

Je ne comprends pas ce que tu appelles un tableau à deux dimensions.
Non, je n'écrase rien. Je ne fais que lire le premier caractère avec l[:1] (jusqu'à l'indice 1 exclus) ou lire à partir du deuxième (1: ) sauf le dernier ( :-1 )


Code PYTHON :
sortie[l[:1]]

sortie est un tableau, l est un tableau, donc sortie à deux dimensions. Non ?
Au temps pour moi ! J'ai cru que les lignes commençait comme "D:ResteDesValeurs" mais je me suis fait avoir par les ":" vu lors de l'étape d'initialisation.
Et j'ai cru que tu réécrivait ":" sur ces ":".
   
bal1 Membre non connecté

Rang

Avatar

Inscrit le : 22/01/2013 à 20h26

Localisation : Besançon - France

Messages: 284

Le 30/04/2019 à 11h49
Papoteur : j'ai bien fait de te soumettre ma modification!
L'utilisation d'un indice est l'option pour ma solution Eiffel ci-dessous
L'exécutable pèse 2.2 MO !

en console : test_qif_to_csv file1.qif file2.csv
le programme test_qif_to_csv.e
Caché :

note
description: "passe un fichier QIF en format CSV : quif_to_csv file1.qif file2.csv"
date: "$Date$"
revision: "$Revision$"

class
APPLICATION

inherit
ARGUMENTS_32

create
make

feature {NONE} -- Initialization

make
-- Run application.
do
create champ.make_empty
create list_var.make_filled ("",1,7)
create input_file.make_open_read (argument (1))
create output_file.make_open_write (argument (2))
if is_input_qif then
if cut_head then
traite_file_input
end
else
print ("%NErreur : Le fichier " + argument (1).out + " n'est pas compatible%N")
end
end

is_input_qif : BOOLEAN
-- analyse les premières lignes pour vérifier que le fichier est valide :
-- c'est un QIF et c'est mon compte
do
input_file.start
input_file.read_line
champ := input_file.last_string
if champ.is_equal ("!Account") then
input_file.read_line
champ := input_file.last_string
Result := champ.is_equal ("NBank account 0430527C025")
end
end

cut_head : BOOLEAN
-- input_file lit le début du fichier (quelques lignes descriptives du compte)
-- jusqu'à la fin d'en-tete = !Type:Bank
-- le traitement débutera par la ligne suivante
do
from input_file.start
until Result or else input_file.exhausted
loop
input_file.read_line
champ := input_file.last_string
Result := champ.is_equal ("!Type:Bank")
end
if not Result then
print ("%NErreur : en-tete fichier anormal%N")
end
end

traite_file_input
-- lit chaque ligne et la traite selon son contenu :
-- afficher l'anomalie
-- demander le placement ad'hoc pour la sortie
-- construire et ecrire l'enregistrement de sortie (placer ';' et fin de ligne)
local i : INTEGER -- index de list_var (champ de sortie dans l'ordre de sortie
do
from -- le fichier a été positionné par 'cut_head' au bon endroit
until input_file.exhausted
loop
input_file.read_line
create champ.make_from_string (input_file.last_string)
if champ.count > 0 and then attached champ.item (1) as l_c then
-- l'item (1) existe
inspect l_c
when '^' then
print ("%N " + champ)
write_output_file
when 'D' then
maj_output (1)
when 'C' then
maj_output (2)
when 'N' then
maj_output (3)
when 'P' then
maj_output (4)
when 'M' then
maj_output (5)
when 'T' then
maj_output (6)
when 'L' then
maj_output (7)
else
print ("%NErreur : type de champ inconnu " + champ.out + "%N")
end
else
do_nothing
end
end
end

maj_output (i : INTEGER)
-- ampute 'champ' de son 1er caractère
-- range le rest dans list_var à la ième place
do
champ.remove_head (1)
list_var.put (champ, i)
end

write_output_file
-- concatene les items de list_var en les séparant avec ';'
-- ajoute la chaine dans output_file
-- ajoute 'fin de ligne' dans output_file
local i : INTEGER
ligne : STRING
do
from i := 1
create ligne.make_empty
until i > 7
loop
ligne := ligne + list_var.item (i)
if i < 7 then
ligne := ligne + ";"
end
i := i + 1
end
print ("%N " + ligne)
output_file.put_string (ligne)
output_file.new_line
create list_var.make_filled ("",1,7) -- reinit list_var
end

feature -- Access

list_var : ARRAY [STRING]
champ : STRING
input_file: PLAIN_TEXT_FILE
output_file: PLAIN_TEXT_FILE

end


Je pense que l'usage d'un script awk ou sed serait difficile dans ce cas Edité par bal1 Le 30/04/2019 à 11h53


:merci:
Alain
Tour LDLC Frakass [CM :ASROCK H81M-HDS Celeron 2800 Ghz RAM 4 Go SSD 120 Go HDD 160 Go]
Mageïa 6 x86-64 bureau Xfce4 + VirtualBox Mageïa 6 x86-64 bureau LXQT
   
Jybz Membre non connecté

Rang

Avatar

Modérateur

Inscrit le : 10/10/2018 à 10h26

Messages: 1852

Le 30/04/2019 à 12h13
bal1 :
L'exécutable pèse 2.2 MO !

Pouah c'est du lourd !
bal1 :
Je pense que l'usage d'un script awk ou sed serait difficile dans ce cas

Je ne sais pas... On fait de grandes choses assez rapidement avec sed et awk
   
magnux77 Membre non connecté

Rang

Avatar

Inscrit le : 21/09/2009 à 11h49

Localisation : Champs-sur-Marne France

Messages: 5037

Le 30/04/2019 à 21h16
bal1 :
Je pense que l'usage d'un script awk ou sed serait difficile dans ce cas
Certainement pas. Et ça n'aurait pas pesé 2,2Mo. Mais j'en ai trop fait et là je suis en vacances...


...depuis Mandrake 7
Membre de l'April - « promouvoir et défendre le Logiciel Libre»
Soutien Framasoft - « Changer le monde, un octet à la fois»
Config n°1 : cpu=AMD64x6 mem=16G SSD=64G HDD=1T OS=Mageia7-64 DE=Xfce, Config n°2 : Dell Latitude E6410 SSD=120G OS=Mageia7 DE=Xfce, Config n°3 : ThinkpadR40 SSD=32G OS=[Manjaro, Parabola, Mageia6] DE=Xfce, Config n°4 : EeePC901 SSD=20Gb, OS=[SliTaz5/Lxde, Mageia6/Xfce]
   
marc-andré Membre non connecté

Rang

Avatar

Inscrit le : 29/09/2015 à 00h10

Localisation : cavaillon

Messages: 675

Le 30/04/2019 à 22h35
salut
oui, le langage Eiffel, ça donne pas trop envie;

concernant le python, c'est beaucoup plus clair et concis;
mais je me demande si avec la librairie "pandas", en chargeant le fichier dans une "dataframe", on pourrait pas le faire encore plus simplement;
je n'ai vu que des vidéos sur "pandas" sans le pratiquer;


ACER Aspire 64 bits 4 coeurs , 4 Go RAM , 1 To SATA, 1ssd 240 Gio NVIDIA GeForce;
Mageia7 , gnome + fedora29 gnome, + mageia6 multi-bureau, + opensuse leap 15.0 plasma
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
   
Papoteur Membre non connecté

Rang

Avatar

Modérateur Équipe Mageia

Inscrit le : 03/10/2011 à 22h16

Localisation : Metz

Messages: 6715

Le 01/05/2019 à 06h55
Bonjour,
La bibliothèque pandas propose la lecture et l'écriture de fichiers en particulier au format csv.
Ok pour une sortie.
Par contre, la lecture à ce format ne me semble pas adaptée.


Yves
   
bal1 Membre non connecté

Rang

Avatar

Inscrit le : 22/01/2013 à 20h26

Localisation : Besançon - France

Messages: 284

Le 01/05/2019 à 10h50
Eiffel impose un typage rigoureux notamment à travers les classes qu'il fournit et la conception de programme nécessite d'intégrer ce qui est proposé.
Je vais voir ce que ça donne avec Racket (fils de Schême, petit-fils de Lisp) : Tout est liste !
Ce qui est dommage avec Racket c'est que l'aspect objet est basé sur java ; mais dans ce cas, on s'en passe.

Bonnes vacances à Magnux77, pensez aux retraités : jamais de congés !


:merci:
Alain
Tour LDLC Frakass [CM :ASROCK H81M-HDS Celeron 2800 Ghz RAM 4 Go SSD 120 Go HDD 160 Go]
Mageïa 6 x86-64 bureau Xfce4 + VirtualBox Mageïa 6 x86-64 bureau LXQT
   
Jybz Membre non connecté

Rang

Avatar

Modérateur

Inscrit le : 10/10/2018 à 10h26

Messages: 1852

Le 01/05/2019 à 11h32
bal1 :
Bonnes vacances à Magnux77, pensez aux retraités : jamais de congés !

:mdr2:
   
marc-andré Membre non connecté

Rang

Avatar

Inscrit le : 29/09/2015 à 00h10

Localisation : cavaillon

Messages: 675

Le 01/05/2019 à 11h57
Papoteur :
Bonjour,
La bibliothèque pandas propose la lecture et l'écriture de fichiers en particulier au format csv.
Ok pour une sortie.
Par contre, la lecture à ce format ne me semble pas adaptée.


merci pour l'info;
en fait, si je voulais tester, où trouverai je un exemple de fichier à ce format qif ?

par ailleurs, en ce moment j'essaie de faire des progrès avec vim;
s'il est possible d'ouvrir ce genre de fichier avec vim, il doit bien y avoir un moyen de faire une ou plusieurs macros, pour remettre ce fichier en csv;
mais, on va retomber sur une solution à base d'expression régulières, comme avec "awk" et "sed", avec toutefois en plus, toutes les fonctionnalités de vim;
remarque : la difficulté de faire de l'informatique aujourd'hui, pour moi, vient de la multitude de solutions possibles à chaque problème : on finit par ne plus savoir laquelle utiliser.

bonnes vacances et bonne retraite ( c'est pas pareil ) à tous.




ACER Aspire 64 bits 4 coeurs , 4 Go RAM , 1 To SATA, 1ssd 240 Gio NVIDIA GeForce;
Mageia7 , gnome + fedora29 gnome, + mageia6 multi-bureau, + opensuse leap 15.0 plasma
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
   
Papoteur Membre non connecté

Rang

Avatar

Modérateur Équipe Mageia

Inscrit le : 03/10/2011 à 22h16

Localisation : Metz

Messages: 6715

Le 01/05/2019 à 12h56
marc-andré :
[quote=Papoteur]remarque : la difficulté de faire de l'informatique aujourd'hui, pour moi, vient de la multitude de solutions possibles à chaque problème : on finit par ne plus savoir laquelle utiliser.

En effet.
C'est pourquoi j'ai choisi de me limiter à certaines solutions (une seule ne suffit pas).
D'où le Python, avec toutefois des variantes dans les bibliothèques graphiques : libyui et Qt. Je n'utilise pas le shell, en général Python s'en sort aussi bien.
Php pour ce qui est techno web, avec javascript (obligé).
J'évite toutefois de tomber dans le travers "Pour celui qui a un marteau, tout problème est un clou." Je connais certains qui maîtrise bien la programmation avec Excel et qui font tout avec. Je trouve ça bof.


Yves
   
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie