oguruma
XLDnaute Impliqué
Bonjour Le Forum,
Sous Excel/Powerquery il est possible de combiner plusieurs dossiers avec des dossiers adjacents (hiérarchiques). Cependant il est impossible via les assistants de combiner des dossiers se trouvant à plusieurs endroits du disques, c'est-à-dire non hiérarchiques ou non adjacents.
Cependant avec un peu de programmation en langage M c'est entièrement réalisable.
Une nouvelle fois, le code présenté dans les requêtes est aussi pédagogique pour les non initiés ou les débutants en langage M.
Il est largement documenté.
Ce post fait suite en fait à la série publiée ICI ainsi que les autres traitant des différents types de combinaisons.
Cela passe bien entendu par des tables de paramétrage. Elle ressemble (voir identique presque) à celle présentée dans les post traitant de ce sujet.
		
		
	
	
		
	
Ensuite il faut déclarer dans une table la liste des dossiers à explorer comme suit
		
	
Attention : les fichiers devront tous avoir le même de tableau structuré - il est répété sur chaque ligne.
Nous avons la possibilité d'identifier fonctionnellement le nom du dossier importé - exemple Dossier1 pour la 1ère ligne
Exemple de résultat
		
	
On a aussi la possibilité d'ajouter le nom du dossier importé par le paramètre AJOUT_DU_CHEMIN_COMPLET
Le placement en tête des colonnes DOSSIER et ENSEIGNE est piloté par les paramètres TAG_PREMIERE_COLONNE, TAG_COL_DOSSIER
Tout comme les autres post concernant ces combinaisons vous êtes libre dans le choix des colonnes
		
	
Il faut tout simplement respecter l'ordre.
Egalement de la même manière que les autres post il y a des contrôles d'existence sur les Item (Table, Sheet).
Petite nouveauté sympathique : en cas d'erreur de traitement exemple dossier inconnu on le retour suivant :
		
	
		
	
En effet D:\DOSSIERXXX n'existe pas sur mon disque.
Environnement PowerQueyr
		
	
RQ_IMPORT_DONNEES_01 : C'est la requête pas à pas qui a permet de construire la fonction fnImportMultipleFolders
RQ_IMPORT_DONNEES_01 : C'est un exemple d'utilisation de la fonction fnImportMultipleFolders
Voici le code de la fonction
	
	
	
	
	
		
Je vous laisse construire vos jeux de tests ou utilisez et modifiez les fichiers de données fournis dans les post précédents.
	
		
			
		
		
	
				
			Sous Excel/Powerquery il est possible de combiner plusieurs dossiers avec des dossiers adjacents (hiérarchiques). Cependant il est impossible via les assistants de combiner des dossiers se trouvant à plusieurs endroits du disques, c'est-à-dire non hiérarchiques ou non adjacents.
Cependant avec un peu de programmation en langage M c'est entièrement réalisable.
Une nouvelle fois, le code présenté dans les requêtes est aussi pédagogique pour les non initiés ou les débutants en langage M.
Il est largement documenté.
Ce post fait suite en fait à la série publiée ICI ainsi que les autres traitant des différents types de combinaisons.
Cela passe bien entendu par des tables de paramétrage. Elle ressemble (voir identique presque) à celle présentée dans les post traitant de ce sujet.
Ensuite il faut déclarer dans une table la liste des dossiers à explorer comme suit
Attention : les fichiers devront tous avoir le même de tableau structuré - il est répété sur chaque ligne.
Nous avons la possibilité d'identifier fonctionnellement le nom du dossier importé - exemple Dossier1 pour la 1ère ligne
Exemple de résultat
On a aussi la possibilité d'ajouter le nom du dossier importé par le paramètre AJOUT_DU_CHEMIN_COMPLET
Le placement en tête des colonnes DOSSIER et ENSEIGNE est piloté par les paramètres TAG_PREMIERE_COLONNE, TAG_COL_DOSSIER
Tout comme les autres post concernant ces combinaisons vous êtes libre dans le choix des colonnes
Il faut tout simplement respecter l'ordre.
Egalement de la même manière que les autres post il y a des contrôles d'existence sur les Item (Table, Sheet).
Petite nouveauté sympathique : en cas d'erreur de traitement exemple dossier inconnu on le retour suivant :
En effet D:\DOSSIERXXX n'existe pas sur mon disque.
Environnement PowerQueyr
RQ_IMPORT_DONNEES_01 : C'est la requête pas à pas qui a permet de construire la fonction fnImportMultipleFolders
RQ_IMPORT_DONNEES_01 : C'est un exemple d'utilisation de la fonction fnImportMultipleFolders
Voici le code de la fonction
		PowerQuery:
	
	
	let fnImportMultipleFolders = (
    pType           as text,
    pPromote        as text,
    pTableCombine   as text,
    pTag            as text,
    pFolder         as text,
    pPath           as text
        ) as table => 
          
        let
            //******************************************************************************
            //                      FONCTIONS SECTION
            //******************************************************************************
            //******************************************************************************
            // Combinaison des dossiers
            //******************************************************************************
            COMBINE_FOLDERS = () as any =>
                // Dans cette fonction on balayer la liste des dossiers à importer contenus dans TBL_COMBINE_FOLDERS_TO_RECORDS
                    let
                        //***********************************************************************************************
                        // On va construire la liste des fichiers à combiner
                        //***********************************************************************************************
                        ListAccumlateCombineFolders = List.Accumulate(
                            LST_COMBINE_FOLDERS_TO_RECORDS,
                            {}, //#table({},{}),
                            (state, current) =>
                                    let
                                        Folder=Record.Field(current,LIST_COLUMNS_TBL_COMBINE{0}),  // On récupère le dossier en cours de lecture
                                        // Si le nom du dossier n'est pas renseigné on passe au suivant
                                        ListCombineFolders=if Folder <> null
                                                        then
                                                                let
                                                                    TblSourceFolder=Folder.Files(Folder),                      // Table contenant la liste des fichiers dans le dossier
                                                                    TblRemoveFields = Table.RemoveColumns(TblSourceFolder, {"Content", "Extension", "Date accessed", "Date modified", "Date created", "Attributes"}),
                                                                    // On récupère les noms des nouvelles colonnes qui seront ajoutées
                                                                    CurrentTag=Record.Field(current, LIST_COLUMNS_TBL_COMBINE{1}),    // Tag fichier
                                                                    CurrentItem=Record.Field(current, LIST_COLUMNS_TBL_COMBINE{2}),   // Item
                                                                    CurrentFolder=Record.Field(current, LIST_COLUMNS_TBL_COMBINE{3}), // Tag dossier
                                                                    // Ajout des nouvelles colonnes
                                                                    TblAddTagColumn=Table.AddColumn(TblRemoveFields, LIST_COLUMNS_TBL_COMBINE{1}, each CurrentTag),     // Ajout colonne tag fichier
                                                                    TblAddItemColumn=Table.AddColumn(TblAddTagColumn, LIST_COLUMNS_TBL_COMBINE{2}, each CurrentItem),   // Ajout colonne Item
                                                                    TblAddTagFolder=Table.AddColumn(TblAddItemColumn, LIST_COLUMNS_TBL_COMBINE{3}, each CurrentFolder), // Ajout colonne tag dossier 
                                                                    TblAddTagPath=if STR_AJOUT_DU_CHEMIN_COMPLET = "OUI" then Table.AddColumn(TblAddTagFolder, "CHEMIN_COMPLET", each Folder) else TblAddTagFolder,
                                                                    // On construit la liste des fichiers qui seront combinés après exploration de tous les dossiers
                                                                    ListFilesToRecords=Table.ToRecords(TblAddTagPath),         // Liste des enregistrements - fichiers de la table
                                                                    ListCombineRecords=List.Combine({state, ListFilesToRecords}) // Liste finale des fichiers à traiter et à combiner entre-eux                         
                                                                in
                                                                    ListCombineRecords
                                                            else state // on passe au dossier suivant
                                    in
                                    ListCombineFolders
                            ),
                    //***********************************************************************************************
                    // On va combiner la liste des fichiers contruite au prélable
                    //***********************************************************************************************
                    TableAccumlateCombineFiles = List.Accumulate(
                            ListAccumlateCombineFolders,
                            #table({},{}),
                            (state,current) =>
                                    let
                                        PathName=current[Folder Path] & current[Name],                             
                                        // Récupération des valeurs Tag Colonne, Table(Item), Dossier
                                        TagColumn=Record.Field(current, LIST_COLUMNS_TBL_COMBINE{1}),
                                        CurrentItem=Record.Field(current, LIST_COLUMNS_TBL_COMBINE{2}),
                                        TagFolder=Record.Field(current, LIST_COLUMNS_TBL_COMBINE{3}),
                                        Path=if STR_AJOUT_DU_CHEMIN_COMPLET = "OUI"  then PathName else null,
                                        // Test existence de l'Item
                                        isExistsIem = if CurrentItem is null then false else fnIsExistsTableSheet(PathName,CurrentItem, STR_TYPE),
                                        TableCombine=if isExistsIem
                                                    then
                                                        let
                                                            wbExcelTmp=try Excel.Workbook(File.Contents(PathName), null, true){[Item=CurrentItem,Kind=STR_TYPE]}[Data] otherwise state,
                                                            wbExcel=if STR_PROMOTE ="OUI" then Table.PromoteHeaders(wbExcelTmp, [PromoteAllScalars=true]) else wbExcelTmp,
                                                            TblAddTagColumn=Table.AddColumn(wbExcel, LIST_COLUMNS_TBL_COMBINE{1}, each TagColumn),     // Ajout colonne tag fichier                                       
                                                            TblAddTagFolder=Table.AddColumn(TblAddTagColumn, LIST_COLUMNS_TBL_COMBINE{3}, each TagFolder), // Ajout colonne tag dossier
                                                            TblAddPath=if STR_AJOUT_DU_CHEMIN_COMPLET = "OUI" then Table.AddColumn(TblAddTagFolder, "CHEMIN_COMPLET", each Path) else TblAddTagFolder, // Ajout colonne tag dossier
                                                            TableCombine=Table.Combine({state,TblAddPath})                                                 
                                                        in
                                                            TableCombine
                                                    else state,  // Si l'Item n'existe pas on passe au fichier suivant
                                        v= TableCombine
                                    in 
                                        v
                            )             
                    in
                    TableAccumlateCombineFiles,
            //******************************************************************************
            // Déplacement de l'étiquette à la 1ère colonne
            //******************************************************************************
            MOVE_COLUMN_TAG = (pTable as table, pCol as number) as any =>
                    let
                        LstColumns=Table.ColumnNames(pTable),
                        NbrColumnsTotal=List.Count(LstColumns),
                        NbColumns=if STR_AJOUT_DU_CHEMIN_COMPLET = "OUI" then NbrColumnsTotal - 3 else NbrColumnsTotal - 2,
                        L1={LIST_COLUMNS_TBL_COMBINE{pCol}},
                        L2=List.FirstN(LstColumns,NbColumns),
                        LstCombine=List.Combine({L1,L2}),
                        TblReorder=Table.ReorderColumns(pTable,LstCombine)
                    in
                    TblReorder, //TblReorder,
                      
            //******************************************************************************
            //                      PRINCIPALE SECTION
            //******************************************************************************
            //******************************************************************************
            // Identification des paramètres
            //******************************************************************************
            STR_TYPE=pType,
            STR_PROMOTE=pPromote,
            STR_TBL_COMBINE=pTableCombine,
            STR_TAG_PREM=pTag,
            STR_TAG_COL_DOSSIER=pFolder,
            STR_AJOUT_DU_CHEMIN_COMPLET=pPath,
            //******************************************************************************
            // On prépare les éléments pour la fusion
            //******************************************************************************
            // Message d'erreur si plantage en fin de traitement
            TBL_MSG_ERROR=#table(type table [STATUT=text, MSG=text, ERRNUM=Int64.Type],{{"ERREUR DE TRAITEMENT", "Vérifier le chemin de vos dossiers et votre paramétrage",99}}),
            // Ordre des colonnes de la table comportant la liste des dossiers à traiter
            // FICHIERS_EXCEL_COMBINE    ENSEIGNE    SHEET_COMBINE    DOSSIER
            TBL_COMBINE = Excel.CurrentWorkbook(){[Name=STR_TBL_COMBINE]}[Content],
            LIST_COLUMNS_TBL_COMBINE=Table.ColumnNames(TBL_COMBINE),
            STR_NOM_COLONNE_COMBINE=LIST_COLUMNS_TBL_COMBINE{0},  // Colonne comportant le nom du dossier à importer
            LST_COMBINE_FOLDERS_TO_RECORDS=Table.ToRecords(TBL_COMBINE),  // Transformation de la table en liste de Records
            //******************************************************************************
            // Fusion des fichiers
            //******************************************************************************
            TBL_DATA_COMBINE_FOLDERS=COMBINE_FOLDERS(),
            TBL_DATA_FINAL_01=if STR_TAG_PREM = "OUI" then MOVE_COLUMN_TAG(TBL_DATA_COMBINE_FOLDERS, 1) else TBL_DATA_COMBINE_FOLDERS,
            TBL_DATA_FINAL_02=try if STR_TAG_COL_DOSSIER = "OUI" then MOVE_COLUMN_TAG(TBL_DATA_FINAL_01, 3) else TBL_DATA_FINAL_01,
            HAS_ERROR=TBL_DATA_FINAL_02[HasError],
            TBL_TRY_02=if HAS_ERROR then TBL_MSG_ERROR else TBL_DATA_FINAL_02[Value]
        in
            TBL_TRY_02
in
    fnImportMultipleFolders
	Je vous laisse construire vos jeux de tests ou utilisez et modifiez les fichiers de données fournis dans les post précédents.
Pièces jointes
			
				Dernière édition: