oguruma
XLDnaute Impliqué
Le but de ce post est de démontrer qu'il est possible de lire un fichier texte et de le transformer. Nous connaissons déjà la lecture de fichiers .csv. La technique utilisée repose quelque part sur cette méthode. 
La cible est d'obtenir
soit
		 
	
soit
		 
	
5 méthodes sont présentées. D'autres doivent exister certainement.
Méthode 1
Le fichier texte est sous ce format :
valeur du Param1;valeur du Param2;valeur du Param3
Les paramètres sont sur une seule ligne séparés par des ";".
On peut soit produire une table à une colonne soit une table à deux colonnes.
Production d'une table à une colonne
	
	
	
	
	
		
Pour accéder aux paramètres c'est un peu particulier et pour simplifier les choses une fonction
	
	
	
	
	
		
Utilisation de la fonction fnGetParamTbParamFromFileList
	
	
	
	
	
		
		 
	
Production d'une table à deux colonnes
Cependant à partir de cette série de paramètres sur une ligne il est possible de produire une table à deux colonnes comme présentée en introduction.
Voici le code. Pour les débutants qui ne sont pas à l'aise avec la manipulation des listes, ce code est un bon cas d'école 😉 à étudier sans modération 🙂
Pour sa bonne compréhension je vous invite à l'exécuter étape par étape afin de bien comprendre les fonctions List.* utilisées.
	
	
	
	
	
		
Le fichier contient un paramètre par ligne comme ceci
valeur du Param1
valeur du Param2
valeur du Param3
valeur du Param4
Nous obtenons une table à une colonne
	
	
	
	
	
		
On obtient
		 
	
On peut transformer la requête précédente pour obtenir une table à deux colonnes comme ceci
	
	
	
	
	
		
On obtient
		 
	
Méthode 2 - avec un délimiteur
PARAM1=valeur du Param1
PARAM2=valeur du Param2
PARAM3=valeur du Param3
PARAM4=valeur du Param4
PARAM5=valeur du Param5
	
	
	
	
	
		
		 
	
ça fonctionne aussi avec ce format à condition de changer la valeur du séparateur ";" en "="
"PARAM1"="valeur du Param1"
"PARAM2=valeur du Param2"
PARAM3=valeur du Param3
PARAM4=valeur du Param4
PARAM5=valeur du Param5
pDelimiter = "=",
Accéder aux paramètres de la table - exemple
	
	
	
	
	
		
Pour mémoire source de la fonction fnGetParameter
	
	
	
	
	
		
Méthode 3 - sous forme de liste
Le fichier paramètres peut être sous ce format
{"PARAMETRE", "VALEUR"},
{
{"PARAM1","STRING 1"},
{"PARAM2",";"},
{"PARAM3",25},
{"PARAM4","16/10/2023"}
}
A partir de ce formation on va construire la table avec le constructeur #table() comme ceci
Source1 = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))), --> on récupère le texte
Source2 = "#table ( " & Source1 & " )", --> on applique le constructeur
ToTable = Expression.Evaluate(Source2, #shared) --> on traduit tout ceci en table
	
	
	
	
	
		
Le fichier peut aussi avoir ce format au travers duquel on précise le type des colonnes :
type table[ PARAMETRE = Text.Type, VALEUR = Any.Type ],
{
{"PARAM1", "STRING 1" },
{"PARAM2", ";" },
{"PARAM3", 25 },
{"PARAM4", "16/10/2023" }
}
En fait on applique la syntaxe PowerQuery dans ce fichier
Méthode 4 - FromRecord
{
[ PARAMETRE = "PARAM1", VALEUR = "STRING1" ] ,
[ PARAMETRE = "PARAM2", VALEUR = "STRING2" ] ,
[ PARAMETRE = "PARAM4", VALEUR = 25 ] ,
[ PARAMETRE = "PARAM5", VALEUR = "16/10/2023" ] ,
[ PARAMETRE = "PARAM6" ]
},
null,
MissingField.UseNull
//type table[PARAMETRE = Text.Type, VALEUR = Any.Type ]
	
	
	
	
	
		
Ou comme ceci - avec un paramètre non valorisé
{
[ PARAMETRE = "PARAM1", VALEUR = "STRING1" ] ,
[ PARAMETRE = "PARAM2", VALEUR = "STRING2" ] ,
[ PARAMETRE = "PARAM4", VALEUR = 25 ] ,
[ PARAMETRE = "PARAM5", VALEUR = "16/10/2023" ] ,
[ PARAMETRE = "PARAM6", VALEUR = null]
},
type table[PARAMETRE = Text.Type, VALEUR = Any.Type ]
Méthode 5 - au format Json
{
"PARAM1"
:"VAL1",
"PARAM2"
:"VAL2",
"PARAM3"
:25,
"PARAM4"
:"VAL4"
}
Il aurait été dommage de passer à côté de ce format que PowerQuery est capable de lire.
	
	
	
	
	
		
	
		
			
		
		
	
				
			La cible est d'obtenir
soit
soit
5 méthodes sont présentées. D'autres doivent exister certainement.
Méthode 1
Le fichier texte est sous ce format :
valeur du Param1;valeur du Param2;valeur du Param3
Les paramètres sont sur une seule ligne séparés par des ";".
On peut soit produire une table à une colonne soit une table à deux colonnes.
Production d'une table à une colonne
		PowerQuery:
	
	
	let
/* Exemple
valeur du Param1;valeur du Param2;valeur du Param3
*/
    pCodeName   = "Params",     
    pExtension  = ".ini",
    pFolder      = null,
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then
                    if ParamExtDefaut is null then
                       ".pq" else
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,   
  
    Source = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))),     
    ToTableParam = Table.RenameColumns(Table.FromList(Text.Split(Source,";")),{{"Column1", "PARAMETRE"}})
    /*
    Pour accéder au 2ème paramètre de la table soit indice 1
    ToTableParam{1}[PARAMETRE]
    ToTableParam{1} : Renvoie le record (1)
    [PARAMETRE] : Nom de la colonne créée automatiquement au moment de la conversion
    */
        
in
    ToTableParamPour accéder aux paramètres c'est un peu particulier et pour simplifier les choses une fonction
		PowerQuery:
	
	
	(pIndex as number) =>
let
    Param = TbParamFromFileList{pIndex}[PARAMETRE]
in
    ParamUtilisation de la fonction fnGetParamTbParamFromFileList
		PowerQuery:
	
	
	let
    Param = fnGetParamTbParamFromFileList(1)
in
    ParamProduction d'une table à deux colonnes
Cependant à partir de cette série de paramètres sur une ligne il est possible de produire une table à deux colonnes comme présentée en introduction.
Voici le code. Pour les débutants qui ne sont pas à l'aise avec la manipulation des listes, ce code est un bon cas d'école 😉 à étudier sans modération 🙂
Pour sa bonne compréhension je vous invite à l'exécuter étape par étape afin de bien comprendre les fonctions List.* utilisées.
		PowerQuery:
	
	
	let
/* Exemple
valeur du Param1;valeur du Param2;valeur du Param3
*/
    pCodeName   = "Params",      
    pExtension  = ".ini",
    pFolder      = null,
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,    
   
    Source = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))),     
    ListValeurs = Text.Split(Source,";"),
    NbParams   = List.Count(ListValeurs),
    ListNumbers = {1..NbParams},
    ListParametres=List.Transform(ListNumbers, each "PARAMETRE" & Number.ToText(_) ),    
    ToTableListParams=
            Table.FromColumns(
                {
                    ListParametres,
                    ListValeurs
                }, 
                { "PARAMETRE", "VALEUR" }  // specifies column names
            )
in
    ToTableListParamsLe fichier contient un paramètre par ligne comme ceci
valeur du Param1
valeur du Param2
valeur du Param3
valeur du Param4
Nous obtenons une table à une colonne
		PowerQuery:
	
	
	let
/* Exemple
valeur du Param1;valeur du Param2;valeur du Param3
*/
    pCodeName   = "Params11",      
    pExtension  = ".ini",
    pFolder     = null,
    Sep         = "#(cr)#(lf)",
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,    
   
    Source = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))),     
    ToTableParam = Table.RenameColumns(Table.FromList(Text.Split(Source,Sep)),{{"Column1", "PARAMETRE"}})
        
in
    ToTableParamOn obtient
On peut transformer la requête précédente pour obtenir une table à deux colonnes comme ceci
		PowerQuery:
	
	
	let
/* Exemple
valeur du Param1;valeur du Param2;valeur du Param3
*/
    pCodeName   = "Params11",      
    pExtension  = ".ini",
    pFolder      = null,
    Sep         = "#(cr)#(lf)",
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,    
   
    Source = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))),     
    ListValeurs = Text.Split(Source,Sep),
    NbParams   = List.Count(ListValeurs),
    ListNumbers = {1..NbParams},
    ListParametres=List.Transform(ListNumbers, each "PARAMETRE" & Number.ToText(_) ),    
    ToTableListParams=
            Table.FromColumns(
                {
                    ListParametres,
                    ListValeurs
                }, 
                { "PARAMETRE", "VALEUR" }  // specifies column names
            )
in
    ToTableListParamsOn obtient
Méthode 2 - avec un délimiteur
PARAM1=valeur du Param1
PARAM2=valeur du Param2
PARAM3=valeur du Param3
PARAM4=valeur du Param4
PARAM5=valeur du Param5
		PowerQuery:
	
	
	let
/* Exemple
PARAM1;valeur du Param1
PARAM2;valeur du Param2
PARAM3;valeur du Param3
PARAM4;valeur du Param4
PARAM5;valeur du Param5
*/
    pCodeName   = "Params2",      
    pExtension  = ".ini",
    pFolder      = null,
    pDelimiter   = ";",
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,   
    Source =  Csv.Document(File.Contents(FileParam),[Delimiter=pDelimiter]),
    ToTableParam = Table.RenameColumns(Source,{{"Column1", "PARAMETRE"}, {"Column2", "VALEUR"}})
            
        
in
   ToTableParamça fonctionne aussi avec ce format à condition de changer la valeur du séparateur ";" en "="
"PARAM1"="valeur du Param1"
"PARAM2=valeur du Param2"
PARAM3=valeur du Param3
PARAM4=valeur du Param4
PARAM5=valeur du Param5
pDelimiter = "=",
Accéder aux paramètres de la table - exemple
		PowerQuery:
	
	
	let
    Source = fnGetParameter(TbGetParamFromFileDelim_1,"PARAM1")
in
    SourcePour mémoire source de la fonction fnGetParameter
		PowerQuery:
	
	
	let fnGetParameter =
    (
        pTable  as any, 
        pName   as text
    ) =>
    let
        ParamSource = if pTable is text then 
                         Excel.CurrentWorkbook(){[Name=pTable]}[Content]
                         else pTable,
                         
        ParamRow = Table.SelectRows(ParamSource, each ([PARAMETRE] = pName)),
        Value= if Table.IsEmpty(ParamRow)=true
                  then null
                  else Record.Field(ParamRow{0},"VALEUR")
    in
        Value
in 
    fnGetParameterMéthode 3 - sous forme de liste
Le fichier paramètres peut être sous ce format
{"PARAMETRE", "VALEUR"},
{
{"PARAM1","STRING 1"},
{"PARAM2",";"},
{"PARAM3",25},
{"PARAM4","16/10/2023"}
}
A partir de ce formation on va construire la table avec le constructeur #table() comme ceci
Source1 = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))), --> on récupère le texte
Source2 = "#table ( " & Source1 & " )", --> on applique le constructeur
ToTable = Expression.Evaluate(Source2, #shared) --> on traduit tout ceci en table
		PowerQuery:
	
	
	let
/*
{"PARAMETRE", "VALEUR"},
{
   {"PARAM1","STRING 1"},
   {"PARAM2",";"},
   {"PARAM3",25},
   {"PARAM4","16/10/2023"}
}
*/
    pCodeName   = "Params7",      
    pExtension  = ".ini",
    pFolder      = null,
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,   
    Source1 = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))),
    Source2 =  "#table ( " & Source1 & " )",
    ToTable = Expression.Evaluate(Source2, #shared)
            
        
in
   ToTableLe fichier peut aussi avoir ce format au travers duquel on précise le type des colonnes :
type table[ PARAMETRE = Text.Type, VALEUR = Any.Type ],
{
{"PARAM1", "STRING 1" },
{"PARAM2", ";" },
{"PARAM3", 25 },
{"PARAM4", "16/10/2023" }
}
En fait on applique la syntaxe PowerQuery dans ce fichier
Méthode 4 - FromRecord
{
[ PARAMETRE = "PARAM1", VALEUR = "STRING1" ] ,
[ PARAMETRE = "PARAM2", VALEUR = "STRING2" ] ,
[ PARAMETRE = "PARAM4", VALEUR = 25 ] ,
[ PARAMETRE = "PARAM5", VALEUR = "16/10/2023" ] ,
[ PARAMETRE = "PARAM6" ]
},
null,
MissingField.UseNull
//type table[PARAMETRE = Text.Type, VALEUR = Any.Type ]
		PowerQuery:
	
	
	let
/* Exemple
{  
  [ PARAMETRE = "PARAM1", VALEUR = "STRING1"     ] ,
  [ PARAMETRE = "PARAM2", VALEUR = "STRING2"     ] ,
  [ PARAMETRE = "PARAM4", VALEUR = 25            ] ,
  [ PARAMETRE = "PARAM5", VALEUR = "16/10/2023"  ] ,
  [ PARAMETRE = "PARAM6"  ]   
}, 
null,
MissingField.UseNull
//type table[PARAMETRE = Text.Type, VALEUR = Any.Type ]
*/
    pCodeName   = "Params9",      
    pExtension  = ".ini",
    pFolder      = null,
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,
    
    Source1 = Text.FromBinary(Binary.Buffer(File.Contents(FileParam))),
    Source2 =  "Table.FromRecords ( " & Source1 & " )",
    ToTable = Expression.Evaluate(Source2, #shared)
            
        
in
   ToTableOu comme ceci - avec un paramètre non valorisé
{
[ PARAMETRE = "PARAM1", VALEUR = "STRING1" ] ,
[ PARAMETRE = "PARAM2", VALEUR = "STRING2" ] ,
[ PARAMETRE = "PARAM4", VALEUR = 25 ] ,
[ PARAMETRE = "PARAM5", VALEUR = "16/10/2023" ] ,
[ PARAMETRE = "PARAM6", VALEUR = null]
},
type table[PARAMETRE = Text.Type, VALEUR = Any.Type ]
Méthode 5 - au format Json
{
"PARAM1"
:"VAL1",
"PARAM2"
:"VAL2",
"PARAM3"
:25,
"PARAM4"
:"VAL4"
}
Il aurait été dommage de passer à côté de ce format que PowerQuery est capable de lire.
		PowerQuery:
	
	
	let
/* Exemple
valeur du Param1;valeur du Param2;valeur du Param3
*/
    pCodeName   = "ParamJson2",      
    pExtension  = ".json",
    pFolder      = null,
    ParamPathDefaut="D:\DATA\14__DEVELOPPEMENTS__PQY__LABS\$__PQ_PARAMS",
    ParamExtDefaut=".ini",
    DEFAULT = ParamPathDefaut & "\",
    BACK_SLASH="\",
    Extension =  if pExtension is null then 
                    if ParamExtDefaut is null then 
                       ".pq" else 
                       ParamExtDefaut
                    else pExtension,
                    
    PathInitial = if (pFolder <> null) then pFolder else DEFAULT,
    PathProcedure = PathInitial & (if Text.End(PathInitial, 1) <> BACK_SLASH then BACK_SLASH else ""),
    FileParam = PathProcedure & pCodeName & Extension,
    
    Source = Json.Document(File.Contents(FileParam)),    
    ToTable = Table.RenameColumns(Record.ToTable(Source),{{"Name", "PARAMETRE"}, {"Value", "VALEUR"}})
in
    ToTable 
	 
 
		