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

SAS Base Discussion :

Si erreur / try catch / swith pour gérer une exception


Sujet :

SAS Base

  1. #1
    Inactif  

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    3 064
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 064
    Points : 4 605
    Points
    4 605
    Par défaut Si erreur / try catch / swith pour gérer une exception
    Bonjour,

    Je possède 5 fichiers Excel qui ont le même schèma :

    "N° Police"n > text format
    Application > text format
    "Nature événement"n text format
    "Cause événement"n > text format
    "Anomalie(s)"n > text format
    "Date rejet initial"n > numeric format
    Acteur > text format
    Statut > text format
    "Analyse Gestion"n > text format
    "Analyse MOE" > text format
    "Date correction"n > text format (si la colonne excel est vide) , date format (si la colonne contient au moins une date) .
    Lead > text format
    Une fois par jour j'importe mes fichiers excel dans mon prgramme SAS sans savoir par avance su la colonne "Date correction"n est vide ou contient au moins une valeur.

    A cause de ce cas je voudrais utiliser un switch.

    Si la colonne est vide (le format d'entrée étant du texte), je veux exécuter une requête qui va me convertir la colonne au format date :

    Code sas : Sélectionner tout - Visualiser dans une fenêtre à part
    call execute (' proc sql ; create table '!!tp_1!!'2 as select "N° Police"n , Application , "Nature événement"n , "Cause événement"n , "Anomalie(s)"n , "Date rejet initial"n , acteur , statut , "Analyse Gestion"n , "Analyse MOE"n , '!!' case when "Date correction"n like '' then ''d end as dtcorr '!!' , Lead from work.'!!tp_1!!' ; run ; ');

    Sinon j’exécute ma requête de traitement standard des dates :

    Code sas : Sélectionner tout - Visualiser dans une fenêtre à part
    call execute (' proc sql ; create table '!!tp_1!!'2 as select "N° Police"n , Application , "Nature événement"n , "Cause événement"n , "Anomalie(s)"n , "Date rejet initial"n , acteur , statut , "Analyse Gestion"n , "Analyse MOE"n , '!!' case when "Date correction"n < 0 then "Date correction"n  else ''d end as dtcorr '!!' , Lead from work.'!!tp_1!!' ; run ; ');

    Mon programme a cette tête :

    Code sas : 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
    options compress=yes sortsize=max; 
     
    /* macro d'import des données de Excel */
     
    %impxlsx2('\\serveur\underfile\INPUT_test\8X_DECES-SUIVI_ANO_FCT.xlsx', huitX_DECES_imp , 'Anomalies à traiter');
    %impxlsx2('\\serveur\underfile\INPUT_test\8X_SUIVI_ANO_FCT.xlsx', huitX_imp , 'Anomalies à traiter');
    %impxlsx2('\\serveur\underfile\INPUT_test\OBSEQUES_SUIVI_ANO_FCT.xlsx', OBSEQUES_imp , 'Anomalies à traiter');
    %impxlsx2('\\serveur\underfile\INPUT_test\PEGASE_DECES-SUIVI_ANO_FCT.xlsx', PEGASE_DECES_imp , 'Anomalies à traiter');
    %impxlsx2('\\serveur\underfile\INPUT_test\PEGASE_SUIVI_ANO_FCT.xlsx', PEGASE_imp , 'Anomalies à traiter');
     
    /* conversion du champ date de correction en champ date vide lorsque celui ci n'est pas renseigné */
     
    %let tp1='huitX_DECES_imp';
    %let tp2='huitX_imp';
    %let tp3='OBSEQUES_imp';
    %let tp4='PEGASE_DECES_imp';
    %let tp5='PEGASE_imp';
     
    data _null_ ;
     
    tp_1=&tp1;
    tp_2=&tp2;
    tp_3=&tp3;
    tp_4=&tp4;
    tp_5=&tp5;
     
    /* il faut réussir à mettre une sortir de si/erreur comme sur Excel un genre de try catch en java */
     
    /* if " call excuete 1 " >> generate an error */
    /* " call execute 2 " */
    /* else */
    /* " call execute 1 " */
     
    run;

    C'est possible d'avoir une structure de programme qui a la tronche suivante ?

    Merci de l'aiguillage

  2. #2
    Inactif  

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    3 064
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 064
    Points : 4 605
    Points
    4 605
    Par défaut
    Après plusieurs heures de recherche je propose ceci comme 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
    60
    61
    62
    63
    64
    65
    66
    67
    data _null_ ;
     
    do i=1 to 5;
     
        call execute (' data work.tp'!!cats(i)!!' ; ');
     
        call execute (' set work.tp'!!cats(i)!!' ; ');
     
        call execute (' length dtcorr2 8. ; ');
        call execute (' format dtcorr2 date9. ; ');
        call execute (' informat dtcorr2 date9. ; ');
        call execute (' dtcorr2=input("Date correction"n,12.) ; ');
        call execute (' length nopol2 coapp2 lbnateve2 lbcaueve2 anomalie2 lbact2 lbsta2 anages2 anamoe2 Lid2 $1500. ; ');
        call execute (' format nopol2 coapp2 lbnateve2 lbcaueve2 anomalie2 lbact2 lbsta2 anages2 anamoe2 Lid2 $1500. ; ');
        call execute (' informat nopol2 coapp2 lbnateve2 lbcaueve2 anomalie2 lbact2 lbsta2 anages2 anamoe2 Lid2 $1500. ; ');
        call execute (' nopol2="N° Police"n ; ') ;
        call execute (' coapp2=Application  ; ') ;
        call execute (' lbnateve2="Nature événement"n  ; ') ;
        call execute (' lbcaueve2="Cause événement"n ; ') ;
        call execute (' anomalie2="Anomalie(s)"n ; ') ;
        call execute (' lbact2=Acteur ; ') ;
        call execute (' lbsta2=Statut ; ') ;
        call execute (' anages2="Analyse Gestion"n ; ') ;
        call execute (' anamoe2="Analyse MOE"n ; ') ;
        call execute (' Lid2=Lead ; ') ;
        call execute (' drop "Date correction"n ; ');
     
        call execute ('run;');
     
    end;
     
    run;
     
    data cinq_fichiers;
     
    length fichier $100;
     
    set
    work.tp1 (in=a)
    work.tp2 (in=b)
    work.tp3 (in=c)
    work.tp4 (in=d)
    work.tp5 (in=e)
    /*indsname=inds*/;
     
    rename
    nopol2=nopol
    coapp2=coapp  
    lbnateve2=lbnateve
    lbcaueve2=lbcaueve
    anomalie2=anomalie  
    "Date rejet initial"n=dtcrerej
    lbact2=lbact
    lbsta2=lbsta
    anages2=anages  
    anamoe2=anamoe
    dtcorr2=dtcorr
    Lid2=Lid;
     
    /*fichier = inds;*/
    if a then fichier="huitX_DECES_imp";
    if b then fichier="huitX_imp";
    if c then fichier="OBSEQUES_imp";
    if d then fichier="PEGASE_DECES_imp";
    if e then fichier="PEGASE_imp";
     
    run;
    J'ai inséré une boucle car je répète 5 fois la même opération sur 5 tables différentes .

    Vous pensez que ce code n'est pas optimal ou qu'il comporte un risque lors de l’exécution ? Je suis preneur de vos idée

  3. #3
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Novembre 2017
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Novembre 2017
    Messages : 63
    Points : 82
    Points
    82
    Par défaut
    Personnellement je ne comprends pas l'intérêt de la syntaxe call execute par rapport à une boucle dans une macro étant donné que vos instructions sont écrites en dur dans le code.
    Je trouve que cela rend le code assez illisible mais peut être pourriez-vous m'indiquer les avantages que vous y trouvez?

    (je m'excuse de vous répondre par une question)

  4. #4
    Inactif  

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    3 064
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 064
    Points : 4 605
    Points
    4 605
    Par défaut
    Bonjour,

    Citation Envoyé par JQuem Voir le message
    Personnellement je ne comprends pas l'intérêt de la syntaxe call execute par rapport à une boucle dans une macro étant donné que vos instructions sont écrites en dur dans le code.
    Le "call execute" permet d’exécuter un sous code de manière dynamique. Ici j'ai 5 tables qui ont la même structures de données (sauf une colonne qui est au format texte ou date selon qu'elle contient de la donnée ou non et qui est recréée pour harmoniser son format ). Lors de l'import de mes tables (ici tp1 à tp5) je ne vais pas dupliquer 5 fois " data work.matable instruction ; run; " ... Imaginez que vous avez 20 tables à importer et le nombre de ligne de code .. Cela va vite devenir illisible et une tartine de code imbuvable ... D’où l'idée de faire boucler le code . Se serait la même chose en php/vba .. il ne vous viendrait jamais à l'idée de dupliquer une instruction de création de fichier par exemple ? Vous utiliseriez une boucle.

    Citation Envoyé par JQuem Voir le message
    Je trouve que cela rend le code assez illisible mais peut être pourriez-vous m'indiquer les avantages que vous y trouvez?
    Vous enlevez le data _null_ , do i=1 to 5; et call execute . Votre code s’exécutera sur une seule table ... Donc vous devriez fatalement le copier/coller pour le réemployer. Autant le rendre "dynamique". Un peu à la façon d'une qbquery tapé en dure sur programme php. On peut prendre pour exemple un formulaire ou un client veut modifier ces données . Il faut rendre le code à executer dynamique/adaptable à ce que l'on veut modifier.

    Vous voyez le concept ?

  5. #5
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Macros
    Bonjour,

    Je partage l'avis de JQuem. Vous pouvez faire une boucle dans une macro, c'est plus lisible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    %macro tp;
      %do i=1 %to 5;
        data work.tp&i;
          set work.tp&i;
          /* vos instructions sans call execute */
        run;
      %end;
    %mend;
     
    %tp;
    Cordialement,

  6. #6
    Inactif  

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    3 064
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 064
    Points : 4 605
    Points
    4 605
    Par défaut
    Bonjour,

    Pouvez vous teste votre code et retourner les log du journal ?

    Code sas : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    %macro tp;
      %do i=1 %to 5;
        data work.tp&i;
          set work.tp&i;
          /* vos instructions sans call execute */
        run;
      %end;
    %mend;
     
    %tp;

    En effet lors de lorsque vous mettez " data work.tp&i; " vous attendez que votre programme boucle. Mais " data work.tp&i; " peut générer ceci dans votre journal " data work.tp 1 ;" ; Une tabulation intempestive risque de venir se glisser et votre code ne fonctionnera pas. Je doute que " data work.&tpcats(i); " ou " data work.cats(tp,&i); " retourne " data work.tp1 ;" .

    Avec la même instruction en call execute vous devez ajouter un cats pour supprimer l'ensemble des blancs " call execute (' data work.tp'!!cats(i)!!' ; '); " . Dans le cas présent la sortie de journal donnera bien " data work.tp1 " . Le call permet de fabriquer une instruction de manière dynamique.

  7. #7
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Macro
    Bonjour,

    La macro fonctionne parfaitement :

    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
    1    %macro tp;
    2      %do i=1 %to 5;
    3        data work.tp&i;
    4          /* vos instructions sans call execute */
    5        run;
    6      %end;
    7    %mend;
    8
    9    %tp;
     
    NOTE: The data set WORK.TP1 has 1 observations and 0 variables.
    NOTE: DATA statement used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
     
     
     
    NOTE: The data set WORK.TP2 has 1 observations and 0 variables.
    NOTE: DATA statement used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
     
     
     
    NOTE: The data set WORK.TP3 has 1 observations and 0 variables.
    NOTE: DATA statement used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
     
     
     
    NOTE: The data set WORK.TP4 has 1 observations and 0 variables.
    NOTE: DATA statement used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
     
     
     
    NOTE: The data set WORK.TP5 has 1 observations and 0 variables.
    NOTE: DATA statement used (Total process time):
          real time           0.01 seconds
          cpu time            0.01 seconds
    Cordialement,

  8. #8
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Novembre 2017
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Novembre 2017
    Messages : 63
    Points : 82
    Points
    82
    Par défaut
    Bonjour, merci pour votre réponse.

    Je comprends parfaitement l’intérêt d’exécuter dynamiquement du code, mais pour moi le macro-language est souvent plus adapté, en tout cas plus lisible et moins long à rédiger.
    Pour ce qui est de la méthode call execute dans un data step, il me semble que sa principale utilité est de composer les instructions d'un datastep qui contiennent de nombreux noms de variables, ou bien si les instructions sont elles-mêmes constituées du contenu des variables d'une table.
    Je me demandais donc si j'avais manqué une autre utilité particulière de la syntaxe call execute.

    J'utilise moi-même régulièrement le macro-langage et je n'ai jamais rencontré le problème de tabulation intempestive dont vous parlez.

    En tout cas merci pour cette discussion intéressante.

    Cordialement,

  9. #9
    Membre expérimenté
    Homme Profil pro
    Attaché statisticien
    Inscrit en
    Mai 2011
    Messages
    687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Attaché statisticien
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Points : 1 581
    Points
    1 581
    Par défaut
    Je suis étonné de l'erreur citée par tanaka59 sur l'utilisation du macro code, je n'ai à ce jour jamais rencontré de telles "tabulations intempestives" avec le macro code... Et pourtant j'ai beaucoup plus souvent utilisé le macro code que la call execute.

    Au contraire même, côté call execute j'ai renoncé à l'utiliser sauf en cas de stricte impossibilité de faire autrement (ce qui concrètement n'arrive jamais...) en raison de désynchronisation potentielle du code exécuté par la call exécute et le code exécuté directement en SAS...

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

Discussions similaires

  1. [XL-2013] pb pour gérer une routine d'erreur
    Par magali13 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 15/07/2017, 02h37
  2. try et tryCatch pour eviter une erreur
    Par ghatfan99 dans le forum R
    Réponses: 2
    Dernier message: 07/01/2013, 15h34
  3. Utilisation de classes pour gérer une table
    Par mathias dans le forum Access
    Réponses: 11
    Dernier message: 30/08/2006, 16h57
  4. Réponses: 1
    Dernier message: 22/02/2006, 09h02
  5. Réponses: 3
    Dernier message: 09/10/2005, 19h10

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