IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Macro Discussion :

Vérifier toutes les variables de tous mes datasets


Sujet :

Macro

  1. #1
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut Vérifier toutes les variables de tous mes datasets
    Bonjour,

    Je cherche à vérifier les valeurs de l'ensemble des variables de l'ensemble de mes datasets.

    Pour cela, j'ai voulu créer une macro qui prend en paramètre la librairie contenant mes datasets.

    J'ai 1 problème dans mon Array où chaque colonne correspond à une variable du dataset sauf que je ne connais pas les noms des colonnes, et je voudrais les appeler var1, var2, ... donc je ne sais pas comment déclarer mon array.

    Voici mon code:
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
     
    %macro CheckProblems(MyLibrary);
     
    	ods output members=ListTables;
    	proc datasets lib=&MyLibrary nodetails nowarn;
    	quit;
     
    	data ListTables;
    		set ListTables;
    		order=_N_;
    	run;
     
    	proc sql noprint;
    		select max(order)
    		into: nbtable
    		from ListTables;
    	quit;
     
    	%do i=1 %to &nbtable;
    		proc sql noprint; 
    			select name
    			into: NameTable
    			from ListTables
    			where order=&i; 
    		quit;
     
    		proc sql; 
    			create table ListVariables as
    			select name
    			from dictionary.columns
    			where upcase(libname)=&MyLibrary and upcase(memname)=&NameTable;
    		quit;
     
    		data ListVariables;
    			set ListVariables;
    			order=_N_;
    		run;
     
    		proc sql noprint;
    			select max(order)
    			into: nbvar
    			from ListVariables;
    		quit;
     
    		data &NameTable;
    			set &MyLibrary..&NameTable;
    			array AllVariables {*} var1 - var.&nbvar; /* probleme */
    			%do i=1 %to dim(AllVariables);
    				%if AllVariables[i]=888 or AllVariables[i]=999 %then problem=1;
    			%end;
    		run;
     
    		proc sql;
    			select * from &NameTable where problem=1;
    		quit;
    	%end;
     
    %mend;


    Je vous remercie par avance pour votre aide.

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 249
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    Il me semble que toutes les informations utiles recherchées se trouvent dans la vue sashelp.vcolumn, non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    %let test = mylib ;
    data resultat ;
       set sashelp.vcolumn (where = (libname = "%upcase(&test)")) ;
    run ;
    ou en SQL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    proc sql ;
       create table resultat as
          select *
          from dictionary.columns
          where libname = "%upcase(&test)"
          ;
    quit ;
    Pour retrouver facilement les valeurs de variables tout en utilisant le macro-langage, voici une proposition...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    data _null_ ;
    /* Mise en macro-variables des noms de tables et de variables */
       set resultat ;
       by memname ;
       retain j 0 ;
       i+1 ;
       if first.memname then call symput ("mv_tab"||compress(i),compress(memname)) ;
       j=j+1 ;
       call symput ("mv_var"||compress(i)||"_"||compress(j),compress(name)) ;
       if last.memname then do ;
          call symput ("mv_max"||compress(i),compress(j)) ;
          j = 0 ;
       end ;
    run ;
    Ainsi mv_tab1 aura les mv_var1_1 mv_var1_2... jusqu'à mv_max1, et mv_tab2 aura les mv_var2_1 mv_var2_2... jusqu'à mv_max2, etc... !
    (Solution non-testée, désolé si faute de frappe !)

    Bon courage !

  3. #3
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut
    Je teste tout ça dès demain matin.

    Merci pour la solution proposée.

    Je te tiens au courant si ça fonctionne (ou pas )

    Bonne soirée.

  4. #4
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut
    Bonjour,

    Alors, depuis ce matin, je me prends pas mal la tete sur ce problème.
    Pour ne pas à avoir à utiliser l'array, je me suis servi de ton code Bruno que j'ai mixé avec le mien et ça donne:
    1. récupération des noms des tables et variables avec le dictionary
    2. comptage du nombre de tables distinctes pour la boucle
    3. attribution d'un numéro à chaque table
    4. récupération de chaque variable dans une macrovariable que je nomme Tx_Vy avec x le numéro de la table et y le numéro de la variable
    5. boucle sur chaque table où
    5.1. je récupère le nom de la table
    5.2. je récupère le nombre maximum de variable pour cette table. NE FONCTIONNE PAS SAUF SI TABLE TAPEE EN DUR
    5.3. boucle sur chaque variable où dans une étape data, si ma variable vaut 999 alors la variable probleme vaut 1. NE FONCTIONNE PAS A CAUSE DE L'ECRITURE DU NOM DE MA VARIABLE


    Voici le code avec les 2 problèmes (5.2 et 5.3).

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
     
    %macro CheckProblems(MyLibrary);
     
    	proc sql noprint;
    		create table AllTablesVariables as
    			select memname, name
    			from dictionary.columns
    			where libname = "%upcase(&MyLibrary)"
    		;
    	quit;
     
    	proc sql noprint;
    		create table AllTables as
    			select distinct memname
    			from dictionary.columns
    			where libname = "%upcase(&MyLibrary)"
    		;
    	quit;
     
    	proc sql noprint;
    		select count (distinct memname)
    		into: nbTable
    		from AllTables;
    		;
    	quit;
     
    	data AllTables;
    		set AllTables;
    		order=_N_;
    	run;
     
    	data AllTablesVariables;
    		merge AllTablesVariables AllTables;
    		by memname;
    	run;
     
    	data AllTablesVariables;
    	   set AllTablesVariables;
    	   by memname;
    	   if first.memname then i=0;
    	   call symput ("T"||compress(order)||"_V"||compress(i),compress(name));
    	   i+1;
    	run;
     
    	%do k=1 %to &nbTable;
     
    		proc sql noprint;
    			select memname
    			into: nameTable
    			from AllTablesVariables
    			where order=&k
    			;
    		quit;
     
    		proc sql noprint;
    			select max (i)
    			into: nbVariable
    			from AllTablesVariables
    			where memname=%upcase(&nameTable)		/* avec cette ligne, ça ne marche pas: ça met The following columns were not found in the contributing tables: TABLESOURCE  */
    			where memname="TABLESOURCE  "				/* avec cette ligne, ça marche */
    			;
    		quit;
     
    		%do x=1 %to &nbVariable;
    			data &nameTable;
    				set &MyLibrary..&nameTable;
    				if 'T'.&k.'_V'.&x=999 then problem=1; 
    				/* dans le if, avec des " ou des ', ça ne marche pas. 
    				dans le log, il est écrit 
    				(pour _V): The symbol is not recognized and will be ignored. 
    				(pour .1 quand k vaut 1): Expecting an arithmetic operator.*/
    			run;
    		%end;
     
    		proc sql;
    			select * from &nameTable where problem=1;
    		quit;
     
    	%end;
     
    %mend;

    Merci de votre aide.

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 249
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    J'ai relu ton code qui me paraît un peu compliqué
    Pour reprendre la solution proposée...
    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
    %macro mp_checkpb (MyLib) ;
    proc sql ;
       create table resultat as
          select memname /* Sélection des tables */
    	         ,name /* Sélection des variables */
    	         ,memtype /* Sélection du type des variables */
          from dictionary.columns
          where libname = %upcase("&Mylib")
    	     and compress(upcase(memtype))='DATA' /* Ne regarder que les DATA */
    		 and compress(upcase(type))='NUM'/* Ne regarder que les variables numériques  */
          ;
    quit ;
    data _null_ ;
    /* Mise en macro-variables des noms de tables et de variables */
       set resultat ;
       by memname ;
       retain i 0 j 0 ; /* i=indice table j=indice variable */
       if first.memname then do ;
          i=i+1 ;
    	  j=0 ;
          call symput ("mv_tab"||compress(i),compress(memname)) ;
       end ;
       j=j+1 ;
       call symput ("mv_var"||compress(i)||"_"||compress(j),compress(name)) ;
       IF last.memname then do ;
          call symput ("mv_maxtab",compress(i)) ; /* Nb maximum de tables */
          call symput ("mv_maxvar"||compress(i),compress(j)) ;/* Nb maximum de variables pour la table considérée */
       end ;
    run ;
    /* Utilisation des macro-variables des noms de tables et de variables */
    %do i=1 %to &mv_maxtab ;
       data work.&&mv_tab&i ;
          set &Mylib..&&mv_tab&i ;
          problem = 0 ;
    	  %do j=1 %to &&mv_maxvar&i ;
             if &&mv_var&i._&j = 999 then problem = 1 ;
    	  %end ;
       run ;
       proc sql;
         select * from work.&&mv_tab&i where problem = 1 ;
       quit;
    %end ;
    /* Test */
    %mend mp_checkpb ;
    Bon courage !
    Bruno

  6. #6
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut


    Ton code marche nickel. Le mien, toujours pas ...

    J'ai modifié 2-3 trucs en regardant sur le tien. Je regarderai de plus près demain.

    Mais j'ai quand même une question pour toi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET &Mylib..&&mv_tab&i ;
    Pourquoi mettre 2 & ? un seul ne suffit pas ? idem à d'autres endroits.

    En tout cas, je te remercie vraiment. Le code fait ce que je veux, il me reste plus qu'à essayer de le comprendre

    Bonne soirée

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 249
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    Ravi d'avoir pu te rendre service.
    SET &Mylib..&&mv_tab&i ;
    Les macro-variables sont résolues par le compilateur macro selon ces règles une règle à la fois :
    1.- && rend &
    2.- Un point termine le nom d'une macrovariable => il faudra le doubler si à la finale on veut obtenir un point
    3.- &mavar rend la valeur que contient mavar

    Donc voici les étapes de résolution :
    1.- &Mylib..&&mv_tab&i
    2.- nomdelabibliotheque.&mv_tab1 (règles 3 / 2 / 1 / 3 )
    3.- nomdelabibliotheque.nomdelatable (règle 3 )

    En conclusion on peut dire que généralement si l'on dispose de macrovariables indicées par leur suffixe, leur radical doit être précédé de &&...

    Bon courage !
    Bruno

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    747
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 747
    Points : 978
    Points
    978
    Par défaut
    Si tu n'aimes pas les array, en voici un (pour progresser )

    Il existe un mot clé _NUMERIC_ qui permet de mettre toutes les variables numériques dans un array.

    On boucle sur l'array pour evaluer chaque variable

    si on trouve 999, on déduit le nom de la variable via une fonction d'information d'array vname

    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
     
    %macro FindValue;
       %local _nbTable tableI;
     
       /* Produit la liste des tables */
       %let _nbTable = 0;
       data _NULL_;
          set SASHELP.VSTABLE end=eof;
          where LIBNAME = 'WORK' and MEMNAME ^= '_TROUVE999';
          i + 1;
          call symput('_' || put(i, 8. -L), trim(MEMNAME));
          if eof then call symputx('_nbTable', i);
       run;
     
       %put _nbTable = <&_nbTable>;
     
       data WORK._TROUVE999;
          /* Concaténation des tables */
          set
          %do tableI = 1 %to &_nbTable;
             &&_&tableI(in=_&&_&tableI.._)
          %end;
          /* Si tu es en 9.2 tu peux utiliser cette option donnant le nom de la table qui fournit l'observation */
          indsname=_dsnT_
          ;
          /* Mets toutes les variables numériques dans un tableau (pas besoin de les lister) */
          array nums[*] _numeric_;
          length _dsn_ _dsd_ _varname_ $ 32 ;
          do i = lbound(nums) to hbound(nums);
             if nums [i] = 999 then do;
                /* Si tu es pas en 9.2 tu dois deviner d'où vient l'observation */
                %do tableI = 1 %to &_nbTable;
                   if _&&_&tableI.._ then _dsd_ = "_&&_&tableI.._" ;
                %end;
                /*Stocke le nom de la variable = 999 */
                _varname_ = vname(nums [i]);
                /*Stocke le nom de la table */
                _dsn_ = scan(_dsnT_, -1, '.') ;
               /*j'ai pas mis de keep*/
                output;
             end;
          end;
       run;
    %mend FindValue;
     
    %FindValue;
    enjoy !

    Xav

  9. #9
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut
    Bonjour,

    Waow, ce fut dur de décrypter le code à 8h30 du matin
    D'ailleurs, j'ai découvert pleins de nouveaux trucs dans ton code Xav: vname, lbound, vstable et surtout les arrays sans avoir à mettre des noms de variables et ça, ça me sera super utile.
    Ton code marche parfaitement également donc ça me fait 2 méthodes pour obtenir ce que je voulais grâce à vous 2. Donc

    Néanmoins, je reviens sur ton dernier message Bruno car je comprends toujours par certains trucs :
    il faudra le doubler si à la finale on veut obtenir un point
    = je suis ok avec ça
    Un point termine le nom d'une macrovariable
    = seulement quand on veut concaténer la macrovariable avec du texte, c'est ça ? car si 2 macrovariables se suivent comme dans &mv_tab&i, on n'a pas besoin de point
    && rend &
    = ça, je suis d'accord et je ne vois donc toujours pas l'interet du double & ... Pourquoi &Mylib..&&mv_tab&i ne peut il pas être remplacé par &Mylib..&mv_tab&i ? Comme ça, on a:
    - &Mylib qui correspond au nom de la librairie
    - le double point pour obtenir un point pour accrocher la librairie à la table
    - &mv_tab qui correspond à la première partie du nom, &i qui correspond à la deuxième partie du nom donc on a le nom complet de la table. &mv_tab&i ne peut pas se résoudre en une seule fois ?

    Bon, toujours est il que je vous remercie pour votre aide. Je mets le post en résolu mais Bruno, si tu as le courage de me réexpliquer l'histoire des &, je suis preneuse

    Merci

    Bonne journée

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 249
    Points : 290
    Points
    290
    Par défaut
    Bonjour,
    si 2 macrovariables se suivent comme dans &mv_tab&i, on n'a pas besoin de point
    Exact, le point en macro langage est le caractère de concaténation, dans l'exemple on peut le metrre ... ou non !
    &mv_tab qui correspond à la première partie du nom, &i qui correspond à la deuxième partie du nom
    Le seul petit problème c'est que &mv_tab provoquera une erreur : cette macrovariable n'existe pas d'où le && qui empêchera la résolution au premier passage tant que &i n'est pas résolu !
    1.- &&mv_tab.&i
    2.- &mv_tab1
    3.- résolution complète...

    Petit exercice
    Si
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    %let i = 1 ;
    %let tab = data ;
    %let data1 = tout est clair ;
    Que donnera (sans faire le test avec un %put dans ta session évidemment !)
    Bon courage !
    Bruno

  11. #11
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut
    euh ... tout n'est pas clair

    donc une dernière question sur ton exemple et après je ne t'embete plus avec ça, je chercherai sur internet si je ne comprends toujours pas :
    pourquoi la résolution de &&&tab&i n'est elle pas:
    au 1er tour, &&tab1 car on annule un & et on résoud &i
    au 2ème tour, erreur car tab1 n'existe pas

    Merci encore pour tes explications et ... ta patience

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 249
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    SAS lit de gauche à droite séquentiellement et résoud ce qu'il peut résoudre et fait autant de lectures jusqu'à éliminer tous les &

    1.- &&&tab.&i

    2.- && -> &
    &tab. -> data
    &i -> i

    3.- &data1 -> tout est clair

    Bon courage !
    Bruno

  13. #13
    Membre actif
    Inscrit en
    Janvier 2005
    Messages
    629
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 629
    Points : 203
    Points
    203
    Par défaut

    ça y est, j'ai compris, tout est clair

    faut que je me garde ton exemple en tête mais bon, je suppose qu'à force de pratiquer, je mettrai moins de temps pour résoudre une expression !

    merci beaucoup pour toutes tes explications.

    a+

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 04/03/2007, 20h16
  2. Comment effacer toutes les variables de sessions en une fois
    Par dessinateurttuyen dans le forum Langage
    Réponses: 4
    Dernier message: 03/08/2006, 10h20
  3. Récupérer toutes les variables commençant pareil
    Par Leobaillard dans le forum Langage
    Réponses: 3
    Dernier message: 14/06/2006, 16h14
  4. Répeter les modifications sur tous mes pages web?
    Par mamiberkof dans le forum Balisage (X)HTML et validation W3C
    Réponses: 8
    Dernier message: 19/04/2006, 10h59
  5. [FLASH 8] Toutes les variables
    Par Destiny dans le forum Flash
    Réponses: 2
    Dernier message: 08/03/2006, 17h20

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