Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. ###raw>post.musername###
    Membre régulier
    Bonjour,
    Je me bats depuis plusieurs jours avec ce programme et je n'arrive toujours pas à le faire fonctionner correctement. Je voudrais lire plusieurs fichiers contenus dans un répertoire. Dans un premier temps, data all liste les fichiers du répertoire et met dans la table le nom des fichiers (champ name) et le nom complet du chemin+nom fichier (champ chemin). Je boucle sur cette table dans data _null_ et je fais passer la variable chemin dans la macro. Dans la macro importer, put &path; affiche bien la valeur de la variable (donc le chemin complet du fichier). Mais proc import... ne donne pas de résultat. Dans le log, il affiche: ERROR: Physical file does not exist, U:\chemin. C'est comme si il prenait la chaîne "chemin" et non la valeur de la variable. J'ai tout essayé: avec ou sans &, un double &, un "&path", etc. Rien ne passe.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    %let directo = 'C:\Documents and Settings\etc\';
    filename direct pipe 'dir "C:\Documents and Settings\etc\" /b';
    %let directy = 'C:\Documents and Settings\etc\fichier.csv';
     
    %macro importer(path=);
    	put &path;
     
    	proc import datafile= "&path" out= output dbms=csv replace;
    		delimiter=";";
    		getnames=yes;
    	run;
    %mend importer;
     
    data all;
    	infile direct truncover;
    	input name $26.;
    	chemin=trim(&directo || name);
    run;
     
    data _null_;
    	set all;
    	%importer (path=chemin)
    	run;
    run;


    J'ai testé la macro indépendamment de la table en mettant directement le nom complet du chemin via la variable directy, ça fonctionne.
    Quelqu'un peut-il me dire comment je dois procéder svp ?
      0  0

  2. #2
    Modérateur

    il faut mettre d'abord
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    x cd 'C:\Documents and Settings\etc';

    puis dir
    N'oubliez pas de consulter les FAQ SAS et les cours et tutoriels SAS
    N'oubliez pas de mettre votre message à si la solution donnée résout votre problème

  3. #3
    Rédacteur

    Sans tout casser (c'est tentant) je pense qu'il te faut un CALL EXECUTE dans ta DATA _null_ finale.

    Autrement, décompose la création de la table avec les chemins et les fichiers, puis crée une macro variable pour chacun de ces fichiers. Fini par une boucle autour de la proc IMPORT permettant de reprendre chaque macro-variable. Mais le CALL EXECUTE est plus simple peut-être.
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

  4. #4
    Modérateur

    oui aussi,
    sinon autre alternative: filevar dans l'infile
    regardes ce poste et ce lien
    N'oubliez pas de consulter les FAQ SAS et les cours et tutoriels SAS
    N'oubliez pas de mettre votre message à si la solution donnée résout votre problème

  5. #5
    Membre régulier
    merci pour ces réponses.
    1) s_a_m:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    x cd ':\Documents and Settings\etc';
    donne le même résultat

    2) datametric: call execute donne le même résultat. A ce propos, je vois que l'erreur est plutôt ceci : ERROR: Physical file does not exist, C:\Documents and
    Settings\...\CHEMIN
    . C'est étrange car je fais passer la variable chemin qui contient c:\...\fichier.csv.
    Concernant ta deuxième solution, je ne la comprends pas. D'ailleurs je ne sais pas affecter à une variable macro la valeur d'un champ d'une table. Comment tu fais ?

    3) s_a_m: filevar est une option qui m'avait plue mais il faut avoir une structure de fichier identique et bien la connaître. Or les fichiers csv contiennent une colonne qui contient une chaîne de caractères variant à chaque ligne. Je pourrais la mettre dans chaine $100. par exemple mais je préfère la flexibilité de proc import qui sépare toutes les colonnes directement.

  6. ###raw>post.musername###
    Membre expérimenté
    J'avais bricolé une macro qui marche très bien. Elle prend en paramètre le repertoire où sont stockés tes fichiers csv.


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    options mprint mlogic symbolgen ;
     
    %MACRO IMPORT(dir=);
     
    DATA fichierscsv ;
    	LENGTH fic $ 1000;
    	INFILE "&dir.\*.csv" FILENAME = fic ;
    	INPUT ;
    	fichier = fic ;
     
    RUN ;
     
    proc sort data=fichierscsv nodupkey;
    by fichier;
    run;
     
     
    DATA fichierscsv ;
    	ATTRIB nom_fichier FORMAT=$10000.;
    	SET fichierscsv ;
    	nom_fichier=TRANWRD(TRANWRD(scan(fichier,-1,'\'),'.csv', ' '),',', '.');
    		fichier=quote(cats(fichier));
    RUN;
     
     
     
    DATA _NULL_;
    	SET fichierscsv;
    	CALL SYMPUT("NB",_N_);
    	CALL SYMPUT("nom_fichier"!!LEFT(_N_),nom_fichier);
    	CALL SYMPUT("rep"!!LEFT(_N_),fichier);
    RUN;
     
    %DO i=1 %TO &NB;
    	PROC IMPORT DATAFILE =&&rep&i	
    		OUT = &&nom_fichier&i.					
    		DBMS = csv  replace;	
             delimiter=";";	
     
    	getnames=yes; 
    run;
     
    %END;
     
    %MEND;
    %IMPORT(dir=C:\Documents and Settings\wwwww);
      0  0

  7. #7
    Expert confirmé
    La raison pour laquelle ton programme ne fonctionne pas actuellement : c'est que le compilateur macro travaille toujours AVANT le compilateur SAS. Donc quand tu incrustes un appel à ton macro-programme à l'intérieur de l'étape DATA, il exécute d'abord le macro-programme (c'est à dire qu'il fait un copier/coller de ce que le macro-programme contient) avant d'exécuter l'étape DATA.
    C'est donc comme si tu avais exécuté, sans macro :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    data _null_;
    	set all;
    	put &path;
     
    	proc import datafile= "&path" out= output dbms=csv replace;
    		delimiter=";";
    		getnames=yes;
    	run;
    	run;
    run;

    On voit bien alors qu'il y a beaucoup (trop) de RUN; et surtout qu'ils ne sont pas bien placés. Quant à la proc IMPORT, SAS ne peut pas l'exécuter sans finir l'étape DATA. Donc il affiche (instruction PUT) à toutes les observations puis attaque la proc IMPORT, avec un fichier à importer qui n'est pas mentionné.
    Si tu crées autant de macro-variables qu'il y a de fichiers à importer (avec CALL SYMPUTX) tu devras en plus faire une boucle. Brice te montre très bien comment faire.
    Sinon, la solution de CALL EXECUTE proposée par Stéphane ressemble plus à l'esprit actuel de ton programme.
    Bon courage en tout cas.
    Olivier
    Bon courage.
    Olivier

  8. #8
    Membre régulier
    Merci Olivier pour ces précisions !
    Je ne connais pas les subtilités de SAS. Maintenant, je comprends mieux pourquoi la variable ne passe pas correctement dans la macro. Je suis plutôt habitué aux langages linéaire et objet. En effet, le programme proposé par Brice fonctionne très bien et me convient bien. Merci beaucoup !