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

Discussion :

proc import dans macro, passage de variable


Sujet :

Macro

  1. #1
    Membre régulier

    Homme Profil pro
    Inscrit en
    avril 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2003
    Messages : 71
    Points : 102
    Points
    102
    Par défaut proc import dans macro, passage de variable
    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 ?

  2. #2
    Modérateur

    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    février 2011
    Messages
    1 618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Conseil

    Informations forums :
    Inscription : février 2011
    Messages : 1 618
    Points : 3 385
    Points
    3 385
    Par défaut
    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

    Homme Profil pro
    SAS ALLIANCE SILVER. Consultant et formateur SAS et Cognos.
    Inscrit en
    avril 2009
    Messages
    2 497
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : SAS ALLIANCE SILVER. Consultant et formateur SAS et Cognos.
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2009
    Messages : 2 497
    Points : 6 061
    Points
    6 061
    Par défaut
    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

    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    février 2011
    Messages
    1 618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Conseil

    Informations forums :
    Inscription : février 2011
    Messages : 1 618
    Points : 3 385
    Points
    3 385
    Par défaut
    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

    Homme Profil pro
    Inscrit en
    avril 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2003
    Messages : 71
    Points : 102
    Points
    102
    Par défaut
    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. #6
    Membre expérimenté
    Avatar de MEGAMIND2
    Homme Profil pro
    Paris
    Inscrit en
    janvier 2011
    Messages
    1 020
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paris

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 020
    Points : 1 486
    Points
    1 486
    Par défaut
    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);

  7. #7
    Expert confirmé
    Avatar de olivier.decourt
    Homme Profil pro
    Formateur R/SAS/statistiques
    Inscrit en
    avril 2008
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Formateur R/SAS/statistiques
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2008
    Messages : 1 840
    Points : 4 089
    Points
    4 089
    Par défaut
    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

    Homme Profil pro
    Inscrit en
    avril 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2003
    Messages : 71
    Points : 102
    Points
    102
    Par défaut
    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 !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Changer le total dans une proc TABULATE (via macro variable?)
    Par Guyguy La Tambouille dans le forum ODS et reporting
    Réponses: 2
    Dernier message: 20/02/2015, 13h33
  2. Réponses: 4
    Dernier message: 29/11/2011, 18h37
  3. Probleme dans le passage des variables dans URL
    Par GarsDuCalvados dans le forum Syntaxe
    Réponses: 16
    Dernier message: 04/01/2011, 14h02
  4. Passage de variable dans une requête
    Par zestrellita dans le forum Langage SQL
    Réponses: 5
    Dernier message: 02/09/2004, 13h27
  5. Passage de variable dans un lien asp
    Par VirginieGE dans le forum ASP
    Réponses: 4
    Dernier message: 27/07/2004, 10h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo