Importer tous les fichiers CSV d'un dossier dans des tables SAS

SAS MACRO 17 juin 2020

Objectif: Importer dans des tables SAS via une proc import tous les fichiers CSV qui sont dans un dossier.

Nous allons décortiquer le programme proposé par SAS dans sa documentation,  comprendre le processus suivi et voir comment l'adapter.

Code d'exemple dans la documentation SAS:

%macro drive(dir,ext); 
   %local cnt filrf rc did memcnt name; 
   %let cnt=0;          

   %let filrf=mydir;    
   %let rc=%sysfunc(filename(filrf,&dir)); 
   %let did=%sysfunc(dopen(&filrf));
    %if &did ne 0 %then %do;   
   %let memcnt=%sysfunc(dnum(&did));    

    %do i=1 %to &memcnt;              
                       
      %let name=%qscan(%qsysfunc(dread(&did,&i)),-1,.);                    
                    
      %if %qupcase(%qsysfunc(dread(&did,&i))) ne %qupcase(&name) %then %do;
       %if %superq(ext) = %superq(name) %then %do;                         
          %let cnt=%eval(&cnt+1);       
          %put %qsysfunc(dread(&did,&i));  
          proc import datafile="&dir\%qsysfunc(dread(&did,&i))" out=dsn&cnt 
           dbms=csv replace;            
          run;          
       %end; 
      %end;  

    %end;
      %end;
  %else %put &dir cannot be open.;
  %let rc=%sysfunc(dclose(&did));      
             
 %mend drive;
 
%drive(c:\temp,csv)

Description du programme:

%macro drive(dir,ext); /* Création de la macro*/
	/* Déclaration de macro variables locales à la macro */
	%local cnt filrf rc did memcnt name;
    %let cnt=0;
    %let filrf=mydir;
%mend drive; /* Fermeture macro */
 
%drive(c:\temp,csv) /* Appel Macro */
  • &cnt = compteur
  • &filrf = utilisé comme 'fileref' dans le programme
  • &rc = variable test
  • &did = assignement du dossier
  • &memcnt = le nombre de fichiers lus dans le dossier
  • &name = nom de l'extension lors de la lecture du programme
 %let rc=%sysfunc(filename(filrf,&dir)); 

La fonction filename va "essayer" d'assigner le dossier. La macro variable &rc aura pour valeur 0 si il n'y a pas d'erreur. La macro n'est pas réutilisée dans le programme donc n'est pas vraiment utile ici. On verra comment l'utiliser dans la partie Adaptations.

%let did=%sysfunc(dopen(&filrf));

La fonction dopen de SAS ouvre le dossier passé en paramètre et renvoie 0 si le dossier ne peut pas être ouvert.

%macro;
/* ----- */
%if &did ne 0 %then %do;
    /* ---- Code --- */
%else %put &dir cannot be open.;
/* ----- */
%mend; 

Dans le cas où le dossier ne pas être ouvert toutes les autres instructions sont passées et on print un message dans la log le dire.

%let memcnt=%sysfunc(dnum(&did)); 

La fonction dnum renvoie le nombre de fichiers présents dans le dossier.

%do i=1 %to &memcnt;              
   /* Boucle sur les fichiers */
%end;

Le programme boucle ensuite de 1 à Nb de fichiers dans le dossier.

%let name=%qscan(%qsysfunc(dread(&did,&i)),-1,.);

Dans la boucle le programme récupére le nom du fichier i du dossier did, ensuite son extension avec un scan en partant de la fin (-1) avec '.' comme séparateur. le choix de la macrovariable "name" n'est pas très judicieux ici.

%if %qupcase(%qsysfunc(dread(&did,&i))) ne %qupcase(&name) %then %do;
	/* Code */
%end; 

Le programme vérifie que chaque fichier à une extension pour continuer.

%if %superq(ext) = %superq(name) %then %do;  
	/* Code */
%end; 

Avant de lancer le code le programme vérifie que l'extension du fichier "name" correspond bien à l'extension que l'on a demandée dans l'appel du macro programme. Dans ce cas on vérifie que "csv" = "csv".

Note: Pour faire la comparaison des deux macros ils utilisent la fonction %SUPERQ qui permet d'utiliser la macro variable en la "quotant" automatiquement quelque soit la valeur.

%let cnt=%eval(&cnt+1);
%put %qsysfunc(dread(&did,&i));

proc import datafile="&dir\%qsysfunc(dread(&did,&i))" 
out=dsn&cnt 
dbms=csv replace;
run;

Incrémente le compteur pour chaque fichier lu. On print le nom complet du fichier qui va être importé. Le programme lance ensuite une PROC IMPORT sur le fichier pour l'importer.

 %let rc=%sysfunc(dclose(&did)); 

En fin de programme on ferme proprement le dossier ouvert par le programme.

Commentaires

Certaines macro variables ne sont pas utilisées dans le programme d'originie et les noms ne sont pas forcemment très explicites.

Aussi il y a une petite erreur dans le programme (certainement une faute de frappe), &name devrait être remplacé par name puisqu'on utilise la fonction %superq.

%if %superq(ext) = %superq(&name) %then %do;  

Adaptations

  • Ce que l'on peut déja faire est de renommer les macros variables et rendre le programme un peu plus verbeux.
  • La macro variable &name va devenir &file_ext pour bien se souvenir que l'on cherche les extensions.
  • Création de la macro variable &file_name pour récupérer le nom du fichier.
  • Utilisation du résultat de la fonction filename dans la macrovariable &rc pour avoir le message d'erreur en cas de problème lors de l'indentification du fichier.
  • Modification de la PROC IMPORT  en changeant le délimiteur à ce que nous utilisons le plus en France le ';'.
  • Ajout de messages dans la log.

options nosource nonotes; /* Optionnel Cacher les autres messages */

%macro drive(dir,ext);
	%put ---------------;
	%put Lancement Macro;
	%put Dossier: &dir.;
	%put Extension: &ext; ;
	%put ---------------;
	/* Déclaration Macro locale */
	%local cnt filrf rc did memcnt name;
	%let cnt=0;
	%let filrf=mydir;

	/* Affichage du message système dans le cas ou l'on arrive pas à assigner le dossier */
	%let rc=%sysfunc(filename(filrf,&dir));
	%if &rc ne 0 %then %put %sysfunc(sysmsg());

	/* Ouverture du dossier */
	%let did=%sysfunc(dopen(&filrf));

	/* Si on peut ouvrir le dossier on continue */
	%if &did ne 0 %then %do;
	/* On compte le nombre de fichiers à importer */
			%let memcnt=%sysfunc(dnum(&did));
			%put --- &memcnt. Fichiers dans le dossier ---;

		/* On boucle sur le Nb de fichiers */
			%do i=1 %to &memcnt;
			%put ---------------;

				/* On assigne les macros nom et ext pour le fichier lu */
				%let file_ext =%qscan(%qsysfunc(dread(&did,&i)),-1,.);
				%let file_name = %qsysfunc(dread(&did,&i));
				%put Fichier &i. : &file_name ; 

				/* On vérifie que le fichier à bien une extension */
				%if %qupcase(%qsysfunc(dread(&did,&i))) ne %qupcase(&file_ext) %then 
				%do;
						/* On vérifie que l'extension match bien avec celle 
							que l'on veut importer*/
						%if %superq(ext) = %superq(file_ext) %then %do;
								/* On lance l'import */
								/* On incrémente de 1 le compteur  */
								%let cnt=%eval(&cnt+1); 
								%put "Import &file_name.";

								/* PROC IMPORT DU FICHIER */
								proc import datafile="&dir\%qsysfunc(dread(&did,&i))" 
									out=dsn&cnt
									dbms=csv replace;
									delimiter=';';
									getnames=yes;
								run;

						%end;
						%else %do; 
						%put "L'extension du fichier ne correspond pas à &ext";
						%end;
				%end; 
				%else %do; 
				%put "Le fichier &file_name. n'a pas d'extension";
				%end;
			%end; /* fin de la boucle */


	%end; 
		
	/* On poste un message d'erreur si on ne peut pas ouvrir le dossier */
	%else %put Erreur le dossier &dir ne peut pas être ouvert.;

	/* Fermeture du dossier */
	%let rc=%sysfunc(dclose(&did));
	%put ---------------;
	%put Fin Macro;
	%put ---------------;
%mend drive;

%drive(C:\Users\GM\Desktop\MACROSERIE\IMPORTCSV\CSV_FOLDER,csv);

On peut regarder ce que donne la log:

---------------
Lancement Macro
Dossier: C:\Users\GM\Desktop\MACROSERIE\IMPORTCSV\CSV_FOLDER
Extension: csv
---------------
--- 3 Fichiers dans le dossier ---
---------------
Fichier 1 : autre_fichier.txt
"L'extension du fichier ne correspond pas à csv"
---------------
Fichier 2 : consommation-quotidienne-brute-elec-grand-nancy.csv
"Import consommation-quotidienne-brute-elec-grand-nancy.csv"
4608 rows created in WORK.DSN1 from 
C:\Users\GM\Desktop\MACROSERIE\IMPORTCSV\CSV_FOLDER\consommation-quotidienne-brute-elec-grand-nancy.csv.
---------------
Fichier 3 : Pays_Villes.csv
"Import Pays_Villes.csv"
5 rows created in WORK.DSN2 from C:\Users\GM\Desktop\MACROSERIE\IMPORTCSV\CSV_FOLDER\Pays_Villes.csv.
---------------
Fin Macro
---------------

Le programme fait bien l'import des fichiers csv et non du fichier txt.

Ressources pour aller plus loin:

Vous pouvez retrouver les données et le programme sur Github.

Documentation officielle de cet exemple: https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=n0ctmldxf23ixtn1kqsoh5bsgmg8.htm&docsetVersion=9.4&locale=en

Documentation des fonctions:

Super ! Vous vous êtes inscrit avec succès.
Super ! Effectuez le paiement pour obtenir l'accès complet.
Bon retour parmi nous ! Vous vous êtes connecté avec succès.
Parfait ! Votre compte est entièrement activé, vous avez désormais accès à tout le contenu.