.. -*- mode: rst -*- .. -*- coding: utf-8 -*- .. role:: toml(code) :language: toml .. default-role:: toml ============================================ Outil de construction des fichiers d’imports ============================================ .. raw:: html .. contents:: :depth: 2 L’application permet de construire un fichier d’import à partir d’une série de règles indiquant comment assembler les données. L’outil est capable d’aller chercher les données dans plusieurs fichiers différents et appliquer des règles simples pour mettre en forme le résultat. Invocation ========== --conf Le chemin vers le fichier de configuration. Cet argument est obligatoire. --print-conf Écrit la configuration chargée sur la sortie courante et selon la dernière syntaxe de l’application. .. --no-bom .. .. Ne pas insérer un BOM_ dans le fichier CSV. Cet indicateur permet .. d’informer Excel que le fichier CSV est en UTF-8, ce qui devrait être le .. cas. Dans le cas où cette chaine de caractère pose problème, il est .. possible de désactiver ce mécanisme. .. .. .. _BOM: https://fr.wikipedia.org/wiki/Indicateur_d%27ordre_des_octets Sortie ====== L’exécution du programme va générer trois fichiers, qui sont tous basés sur le nom du fichier de configuration : sortie.csv Il s’agit du fichier produit par l’application, et dont les colonnes sont celles définies dans le fichier de configuration. sortie.sqlite Il s’agit d’une base de données reprenant toutes les données utilisées pour construire le résultat. sortie_error.csv Il s’agit d’un fichier CSV généré si l’application rencontre des erreurs. Celles-ci concernent les liaisons entre les différents fichiers qui n’ont pas pu être réalisées Fichier de configuration ======================== Les informations générales -------------------------- version Il s’agit de la version de la syntaxe du fichier de configuration. Valeur attendue : `1` source La clef `source` indique quel est le fichier source : pour chaque ligne présente dans ce fichier, une ligne sera générée en sortie. :file: le fichier à charger :tab: optionnellement l’onglet concerné :name: le nom sous lequel le fichier sera associé. Le chargement des dépendances ----------------------------- La recherche de valeurs dans d’autres fichiers Excel nécessite de déclarer les fichiers à charger. La liste `externals` décrit tous les fichiers qui doivent être chargés, et comment les données doivent être associée avec le fichier source. .. code:: toml [externals.target] intern_key = ":source.A" extern_key = ":A" file = "financial.xlsx" allow_missing = false Les clefs suivantes sont nécessaires pour lier les données venant d’un autre fichier : intern_key Il s’agit de la colonne servant à faire la liaison dans la source. file Le fichier à charger tab optionnellement l’onglet concerné extern_key Il s’agit de la colonne servant à faire la liaison dans le fichier devant être lié. La clef doit doit etre unique, l’application supprimera les doublons pour ne garder qu’une seule valeur par clef. Il n’est donc pas possible de faire un produit cartésien. allow_missing Cette clef optionnelle indique s’il faut autoriser les valeurs manquantes lors dans une liaison. Déclarer `allow_missing` va également autoriser les doublons sur les valeurs de clef. Une fois la dépendance vers un fichier externe déclaré, il est possible d’utiliser les colonnes de ce fichier en les référençant directement. Cela revient à faire un `RECHERCHEV` dans Excel à chaque fois. Il est possible d’utiliser une référence externe dans une autre source externe, afin de construire des chemins sur plusieurs niveaux : .. code:: toml [externals.acheteur_annuaire] intern_key = ":I" extern_key = ":A" file = "ANNUAIRE.xlsx" [externals.acheteur_societe] intern_key = ":acheteur_annuaire.BJ" extern_key = ":A" file = "SOCIETES.xlsx" Les valeurs présentes dans ces colonnes sont pré-traitées pour éviter les erreurs générales lors des imports : les espaces en fin de texte sont supprimés et le texte est passé en capitale. Définition des colonnes ----------------------- Une fois les différents fichiers chargés, il est possible de construire le schéma du fichier de sortie en listant toutes les colonnes à générer : .. code:: toml """function ( :A ^ '_' ^ :target.E , :E )""" ======================= ======================================= ====================== Type d’élément Interprétation Exemple ======================= ======================================= ====================== Texte Un texte libre. Celui-ci doit être `'_'` placé entre quote (`'` ou `"`). Un nombre La valeur correspondante `1234` Une référence Une colonne. Celle-ci peut être définie `:A` via un fichier externe ou directement par rapport au fichier source. `:target.E` Elle ne doit pas être placée entre quote. Le nom du fichier peut être omis (et est alors considéré comme étant le fichier source) Opérateur `^` Concaténation d’éléments `"contract_" ^ :A` Opérateur mathématique `+` `-` `/` `=` `<>` `:Q + 1` `:A = 2000` Fonction Applique la fonction sur les `nvl(:I, :N, "Defaut")` éléments donnés. La fonction ne doit pas être placée entre quote `trim(:N)` La fonction prend en paramètre les arguments sous forme de `trim("prefixe_" ^ :C)` liste, séparés par des virgules. ======================= ======================================= ====================== .. class:: collapse :Operator: `+` | `-` | `<` | `>` | `/` | `^` :Equality: `=` | `<>` :Reference: | `:`\ COLUMN | `:`\ TABLE\ `.`\ COLUMN :Expression: | LITERAL | NUMERIC | *Reference* | *Expression* *Operator* *Expression* | *Expression* *Equality* *Expression* | *Expression* *Equality* *Group* | IDENTIFIER `(` *Expression*\ + `)` | IDENTIFIER `(` *Expression*\ , *Group*, *Group* `)` | IDENTIFIER `(` *Group*, *Group* `)` :Group: | `[` Expression* `]` Tri des données --------------- .. code:: toml sort = [ ":mouvements.B", ":lib_titres.B", "date('%d/%m/%Y', :mouvements.C)", ":A", ] Les données peuvent être triées à l’aide de la section `sort`. Il est possible de définir plusieurs critères de tri qui seront traités par ordre de priorité. Des fonctions peuvent également être utilisées (dans l’exemple ci-dessus, nous avons un tri sur des dates au format dd/mm/yyyy, si la donnée n’était pas convertie en date, elle serait triée sur le jour avant d’être triée sur l’année). Filtrer les données ------------------- .. code:: toml filters = [ ":t_operation.B <> ['Cession', 'Restitution', 'Prêt de titres']", ":lib_titres.B <> 0", ":societe.A <> 0", ] Un filtre peut être mis en place pour ne conserver que les lignes souhaitées. Les conditions doivent être toutes validées pour que la ligne soit retenue. .. note:: Il est possible de mettre une fonction de groupe dans les filtres, pour n’extraire par exemple que la première ligne d’une série. Toutefois, cette fonctionnalité est encore expérimentale. L’application peut lever une erreur si la fonction est trop complexe pour etre interprétée. Si une fonction de groupe est présente, l’application ordonnera les évaluations selon l’ordre suivant : 1. En premier lieu tous les filtres *simples* pour ne conserver que les lignes correspondantes. 2. Ensuite seulement la fonction de groupe présente dans la section `filter` Exemple complet =============== Cet exemple (issu d’un cas réel), crée un fichier des personnes morales à partir de plusieurs tables. - Le fichier source donne des identifiants pour les formes juridiques (qu’il faut donc aller dans une table à part) et les devises - le numéro de TVA communautaire doit être chargé dans la table immatriculation, la colonne A doit correspondre au code de la société, et la colonne D doit avoir la valeur `4` - l’adresse est reconstituée en concaténant cinq colonnes depuis la table annuaire. - la ville et le code postal peuvent être présent sur deux tables : la table annuaire si l’adresse n’a pas été modifiée depuis la saisie initiale de la fiche, ou la source qui contient la dernière valeur, mais peut être nulle si celle-ci n’a pas été modifiée… .. code:: toml version = 1 [source] file = "20220222_SOCIETES.xlsx" name = "société" # Des commentaires peuvent etre ajoutés tout au long du fichier. # Ici la table actif permet de faire une correspondance entre les valeurs # du client et nos valeurs : # 1 -> Actif # 0 -> Inactif [externals.actifs] intern_key = ":E" file = "actifs.xlsx" extern_key = ":A" allow_missing = false [externals.legalform] intern_key = ":J" file = "mapping.xlsx" tab = 2 extern_key = ":A" allow_missing = false [externals.currency] intern_key = ":BF" file = "mapping.xlsx" tab = 6 extern_key = ":A" allow_missing = false # le fichier annuaire contient des informations supplémentaires [externals.annuaire] intern_key = ":A" file = "20220222_ANNUAIRE.xlsx" extern_key = ":BJ" allow_missing = false # La table des immatriculations. # Seules les lignes avec la colonne D = 4 nous intéressent [externals.immat] intern_key = ":A ^ '_4'" file = "20220222_SO_IMMATRICULATION.xlsx" extern_key = ":B ^ '_' ^ :D" allow_missing = true [sheet] columns = [ "'companyDirectory_' ^ :A", ":G", "'internalExternalList_Internal'", ":actifs.B", ":H", ":I", "", ":legalform.S", ":annuaire.I", ":T", ":BP", ":currency.D", "", ":annuaire.CC", ":CQ", ":CO", ":immat.C", # Utilise la fonction join pour assembler les éléments # De cette manière, si l’un des éléments est vide, il n’y aura pas de # double espace (' ') dans le résultat "join(' ', :annuaire.CP, :annuaire.CQ, :annuaire.CR, :annuaire.L, :annuaire.M)", "nvl(:CM, :annuaire.N)", "nvl(:CS, :annuaire.AB)", ":CR" ] filters = [] sort = [] uniq = [] Comparaison des valeurs ======================= Comparaison par groupe ---------------------- .. code:: toml ":t_operation.B <> ['Cession', 'Restitution', 'Prêt de titres']" Les opérateurs de comparaison `=` et `<>` peuvent accepter un groupe de valeur plutot qu’une valeur unique. Dans ce cas, la condition est vraie si l’une des valeurs est présente. Le cas des cellules vides ------------------------- .. code:: toml ":B > 0", "'prefix_' ^ :B", Les cellules vides peuvent apparaitres dans des colonnes où l’on s’attend à trouver des champs texte, ou des nombres. L’application va traiter ces valeurs vides en fonction du contexte et les considérer comme `0` si elles sont associées avec un numérique, ou `""` si elles sont associées à un texte. Fonctions disponibles ===================== Liste non exhaustive. `if` Choisi la valeur de la cellule en fonction d’une condition : .. code:: toml """if( :E = 1 , 'Vrai' , 'Faux' )""" `nvl` Sélectionne la première valeur non nulle de la liste .. code:: toml "nvl(:I, :N, 'Defaut')" Fonctions sur les nombres ------------------------- `abs` Renvoie la valeur absolue d’un nombre. `int` Transforme une valeur en nombre entier. Fonctions sur le texte ---------------------- `join` .. code:: toml "join('-', :A, :target.E, :B)" Concatène tous les champs en utilisant le premier paramètre comme séparateur. Les valeurs vides sont ignorées, et dans ce cas le séparateur n’est pas répété. `match` Extrait un motif sur la base d’une `expression régulière`_. .. code:: toml "match('hello ([A-Za-z]+)', ':B')" .. _expression régulière: https://fr.wikipedia.org/wiki/Expression_r%C3%A9guli%C3%A8re#Op%C3%A9rateurs `substring` Extrait une sous-chaine en indiquant la position et la longueur. .. code:: toml "substring(:H, 1, 5)" `trim` Supprime les espaces en début et fin de chaine .. code:: toml "trim(:C)" `upper` Passe le texte en capitale .. code:: toml "upper(:A)" Fonctions sur les dates ----------------------- Normalement, les dates sont représentées dans Excel comme un nombre. On peut donc utiliser les opérations standard (addition…) sans avoir à se poser de question sur leur résultat. Toutefois, il est parfois nécessaire de faire des opérations avancées. `date` Converti une date depuis le format texte. Le résultat de la fonction est le nombre de jours écoulés depuis le 31 décembre 1899 (`1` correspond au 1er janvier 1900). Cela correspond à la manière dont Excel enregistre une valeur de type date. .. code:: toml "date('%d/%m/%Y', :B)" `year` Extrait l’année (sur 4 chiffres) à partir d’une date. Si la date est donnée directement, il vaut mieux utiliser `substring` qui est plus simple d’accès. `year` devient utile s’il y a des calculs associés : .. code:: toml "year( date('%d/%m/%Y', :M) + date('%d/%m/%Y', '31/12/1999') )", Les fonctions de groupes ------------------------ Les fonctions suivantes permettent de grouper les données ou de les mettre en correspondance avec d’autres lignes du fichier. Elles prennent se basent sur deux paramètres supplémentaires : 1. le premier étant les colonnes à identifier pour faire le regroupement, 2. le second étant l’ordre dans lequel les lignes doivent être triées. `counter([regroupement, …],[tri, …])` Le tri est ignoré si le regroupement est omi. `counter` Crée un compteur qui s’incrémente tant que les lignes sont identiques. L’exemple suivant va remettre le compteur à `1` dès que la société ou le titre change, et utilisera la date pour ordonner les valeurs dans ce groupe. .. code:: toml """counter( [:societe.H, :lib_titres.B], [date('%d/%m/%Y', :mouvements.C), :A] )""" La fonction peut également être utilisée pour ne conserver que les lignes uniques au sein d’une plage donnée (via un post-traitement où l’on ne garde que les valeurs à `1`) .. code:: toml "counter([:C], [:A]) = 1" Il est possible de construire plusieurs compteurs sur des groupes et des tris différents au sein d’un même fichier. Si le critère de tri n’est pas donné, l’application va compter le nombre d’éléments pour chaque groupe: toutes les cellules auront le même résultat. `previous` La fonction `previous` permet d’aller chercher l’élément précédent dans les données. En fonction du critère de regroupement, la valeur renverra vide (si l’on est sur groupe différent), et la valeur précédente sera recherchée en fonction du critère de tri donné. `previous(expression, [regroupement, …], [tri, …])` .. code:: toml """previous( :ths.G, [:socs.EB, :socs.L, :ths.E], [:ths.H])""" `sum` La fonction `sum` permet de calculer la somme d’une colonne donnée sur un critère de regroupement. Si le critère de tri n’est pas donné, l’application va calculer la somme totale en fonction du critère de regroupement : toutes les cellules auront le même résultat. `sum(expression, [regroupement, …], [])` .. code:: toml """sum( :shares.K, [:shares.A, :shares:D], [])""" Au contraire, si un tri est donné, l’application va accumuler la somme tout au long des valeurs rencontrées, et selon l’ordre du tri. `min` La fonction `min` permet d’aller chercher le premier élément du groupe (c’est à dire le plus petit selon l’ordre de tri) `min(expression, [regroupement, …], [tri, …])` .. code:: toml """min( :mouvements.C, [:societe.A, :I], [:mouvements.C])""" exemple d’utilisation : rechercher la première date d’achat. `max` La fonction `max` permet d’aller chercher le dernier élément du groupe. `max(expression, [regroupement, …], [tri, …])`