Précédent   Forum des professionnels en informatique > Logiciels > Solutions d'entreprise > Business Intelligence > SAS > Macro
Macro Forum d'entraide sur le langage Macro de SAS
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 08/11/2011, 22h02   #1
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Par défaut problème avec %sysfunc

Bonjour,
J'ai un problème avec la macro %sysfunc, elle me retourne un nombre inexact qui vaut tjrs 0, merci bien de m'aider à trouver ou se trouve le problème.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
%macro calcul_ind;
proc sql noprint;
SELECT DISTINCT formule INTO :formule1 separated BY ';' FROM sasuser.etape1 ORDER BY code_ind;
SELECT COUNT(*) INTO :NB_Enreg FROM sasuser.etape1;
quit;
DATA _null; 
%DO i=1 %TO &NB_Enreg;  
formule&i=SCAN("&formule1",&i,';');
ch&i=prxchange("s/[\/ + \- *]{1,}/\//",-1,strip(formule&i));
%let x&i=%sysfunc(count(ch&i,/));
%DO j=1 %TO &&x&i+1;
....
%end;
La table sasuser.etape1 :
code_ind | formule
Ind0 | etape1.Ind0+etape0.Ind1
Ind1 | etape1.Ind3-etape0.Ind3
Ind2 | etape1.Ind1*etape1.Ind5
Ind3 | etape0.Ind2/etape0.Ind4
Ind5 | etape0.Ind5
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 09h46   #2
Membre habitué
 
Homme
Consultant informatique
Inscription : mars 2002
Messages : 211
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Belgique

Informations professionnelles :
Activité : Consultant informatique

Informations forums :
Inscription : mars 2002
Messages : 211
Points : 133
Points : 133
Jai l'impression de voir déjà une petite erreur:

Code :
formule&i=SCAN("&formule1",&i,';');
N'oublie pas que tu es dans une macro:
donc:
Code :
1
2
%sysfunc(scan
ou %scan
A vérifier...
L0007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 09h49   #3
Membre Expert
 
Homme
Biostatisticien
Inscription : juin 2009
Messages : 1 147
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Irlande

Informations professionnelles :
Activité : Biostatisticien
Secteur : Industrie Pharmaceutique

Informations forums :
Inscription : juin 2009
Messages : 1 147
Points : 1 766
Points : 1 766
Bonjour,

as tu essaye sans le mode macro et est ce que ca marche? Tu cherches a compter quoi? Tu as essaye avec un quote:

Code :
%let x&i=%sysfunc(count(ch&i,'/'));
Manoutz est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 09h57   #4
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Bonjour,

Tu veux faire quoi?

Salah
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 10h42   #5
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Bonjour,

Merci d'abord pour vos réponses, mais je les ai déjà essayées, ca marche pas.
voilà mon programme ce que doit faire :

par exemple pour la formule "etape0.Ind0+etape0.Ind1-etape0.Ind2", il doit remplacer les opérateurs "+-*/" par des "/" j'obtiens comme résultat
"etape0.Ind0/etape0.Ind1/etape0.Ind2" puis je veux obtenir le nombre de "/" pour l'utiliser dans une boucle , quand j'utilise :

Code :
1
2
3
x&i=count(ch&i,'/'); ca marche mais lorsque j'utilise ce compteur dans ma boucle
%DO j=1 %TO x&i; 
%end;
il me renvoie cette erreur :
Code :
1
2
3
A character operand was found IN the %EVAL FUNCTION OR %IF condition WHERE a numeric operand IS required. The condition was: x&i 
ERROR: The %TO value of the %DO J loop IS invalid.
ERROR: The macro CALCUL_IND will stop executing.
c'est pourquoi j'ai passé par la macro %sysfunc, sauf qu'elle me retourne tjrs 0.
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 10h48   #6
Membre Expert
 
Homme
Biostatisticien
Inscription : juin 2009
Messages : 1 147
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Irlande

Informations professionnelles :
Activité : Biostatisticien
Secteur : Industrie Pharmaceutique

Informations forums :
Inscription : juin 2009
Messages : 1 147
Points : 1 766
Points : 1 766
j'essaierai un

Code :
%DO j=1 %TO %sysevalf(&&x&i+1);
Manoutz est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 10h49   #7
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 012
Détails du profil
Informations personnelles :
Nom : Homme Samir SELMANE
Localisation : France

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

Informations forums :
Inscription : février 2011
Messages : 1 012
Points : 1 713
Points : 1 713
Hello;

je n'ai pas trop compris ce que tu veux faire ;
mais comme tu teste des macro variables , le DATA "_null"(data _null_), n'a aucun interêt ici; dans le code macro , il faut utiliser des %sysfunc pour toutes les fonctions.


Utilises le COUNTC et non pas le count , et entoure ton / de quôtes.
exemple
Code :
1
2
3
4
 
%let a = %sysfunc (countc('a/b/c/d','/'));
 
%put aaaa &a.;
et ... et...
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h00   #8
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
J'ai déjà utilisé %sysevalf mais elle retrourne tjrs 0 (un nombre inexact)
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
%macro calcul_ind;
proc sql noprint;
SELECT DISTINCT formule INTO :formule separated BY ';' FROM etape1 ORDER BY code_ind;
SELECT COUNT(*) INTO :NB_Enreg FROM etape1;
quit;
%DO i=1 %TO &NB_Enreg;  
%let formule&i=%sysfunc(scan("&formule",&i,';'));
%let ch&i=%sysfunc(prxchange("s/[\/ + \- *]{1,}/\//",-1,strip(formule&i)));
%let x&i=%sysfunc(countc(ch&i,'/'));
%DO j=1 %TO &&x&i+1;
comp&i.&j=scan(ch&i,&j,'/');
%END; 
%END;
%mend;
J'ai supprimé le data _null et j'ai utilisé des %sysfunc mais il me donne l'erreur suivante :

Code :
1
2
ERROR: Literal contains unmatched quote.
ERROR: The macro CALCUL_IND will stop executing.
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h05   #9
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
%macro calcul_ind;
proc sql noprint;
SELECT DISTINCT formule INTO :formule separated BY ';' FROM etape1 ORDER BY code_ind;
SELECT COUNT(*) INTO :NB_Enreg FROM etape1;
quit;
%DO i=1 %TO &NB_Enreg;  
%let formule&i=%sysfunc(scan("&formule",&i,';'));
%let ch&i=%sysfunc(prxchange("s/[\/ + \- *]{1,}/\//",-1,strip(&&formule&i)));
%let x&i=%sysfunc(countc(&&ch&i,"/"));
%DO j=1 %TO %sysevalf(&&x&i+1);
comp&i.&j=scan(&&ch&i,&j,"/");
%END; 
%END;
%mend;
tjrs même erreur:
Code :
1
2
ERROR: Literal contains unmatched quote.
ERROR: The macro CALCUL_IND will stop executing.
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h22   #10
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
ajoute l'option
Avant d'exécuter ton code, comme ça tu aura le code qui va être exécuté.
Cela facilitera la recherche de l'erreur.
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h26   #11
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Citation:
Envoyé par aminao Voir le message
Bonjour,

Merci d'abord pour vos réponses, mais je les ai déjà essayées, ca marche pas.
voilà mon programme ce que doit faire :

par exemple pour la formule "etape0.Ind0+etape0.Ind1-etape0.Ind2", il doit remplacer les opérateurs "+-*/" par des "/" j'obtiens comme résultat
"etape0.Ind0/etape0.Ind1/etape0.Ind2" puis je veux obtenir le nombre de "/" pour l'utiliser dans une boucle , quand j'utilise :

Code :
1
2
3
x&i=count(ch&i,'/'); ca marche mais lorsque j'utilise ce compteur dans ma boucle
%DO j=1 %TO x&i; 
%end;
il me renvoie cette erreur :
Code :
1
2
3
A character operand was found IN the %EVAL FUNCTION OR %IF condition WHERE a numeric operand IS required. The condition was: x&i 
ERROR: The %TO value of the %DO J loop IS invalid.
ERROR: The macro CALCUL_IND will stop executing.
c'est pourquoi j'ai passé par la macro %sysfunc, sauf qu'elle me retourne tjrs 0.
Est ce que c'est ça ce que tu cherches?
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
DATA etape1;
code_ind="Ind0";formule="etape1.Ind0+etape0.Ind1";output;
code_ind="Ind1";formule="etape1.Ind3-etape0.Ind3";output;
code_ind="Ind2";formule=" etape1.Ind1*etape1.Ind5";output;
code_ind="Ind3";formule=" etape0.Ind2/etape0.Ind4";output;
code_ind="Ind5";formule=" etape0.Ind5";output;
run;
DATA t;
SET etape1;
t=translate(formule,'/','*','/','+','/','-');
nb_slash=count(t,'/');
run;
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h35   #12
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 012
Détails du profil
Informations personnelles :
Nom : Homme Samir SELMANE
Localisation : France

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

Informations forums :
Inscription : février 2011
Messages : 1 012
Points : 1 713
Points : 1 713
Ah oui si c'est sa , peut être mieux avec les Expressions Régulières:
Code :
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
 
DATA etape1;
INFILE cards dlm='|' ;
input 
code_ind $4. @8 formule $25.;
cards;
Ind0 | etape1.Ind0+etape0.Ind1
Ind1 | etape1.Ind3-etape0.Ind3
Ind2 | etape1.Ind1*etape1.Ind5
Ind3 | etape0.Ind2/etape0.Ind4
Ind5 | etape0.Ind5 
Ind0 | etape1.Ind0+*etape0.Ind1
Ind1 | etape1.Ind3-+*etape0.Ind3
Ind2 | etape1.Ind1**etape1.Ind5
;
run;
 
 
DATA tab1;
SET etape1;
var_new= prxchange("s/[\/ + \- *]{1,}/\//",-1,strip(formule));
nbr=countc(var_new,"/");
run;
 
 
 
DATA t;
SET etape1;
t=translate(formule,'/','*','/','+','/','-');
nb_slash=count(t,'/');
run;
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h38   #13
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Merci d'abors pour les réponses, mais mon problème c'est comment utiliser le compteur de "/" (aprés remplacement) dans la boucle %do
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 11h41   #14
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Est ce que le code présenter répond à ton premier besoin?
Si oui tu fais quoi dans la boucle.
Si on put le faire sans macro langage ça sera plus simple à lire et corriger par la suite.
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 12h02   #15
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Bjr,
Je vous explique en gros ce que je veux faire:
normalement j'ai deux tables etape0(code_ind,libelle,formule) et etape1(code_ind,libelle,formule) comme suit:

etape0

code_ind | formule
Ind0 | 1230
Ind1 | 1000
Ind2 | 500
Ind3 | 4569

etape1

code_ind | formule
Ind0 | etape0.Ind0
Ind1 | etape1.Ind2+etape0.Ind3
Ind2 | etape1.Ind0+etape1.Ind1
comme vous pouvez remarquer, les indicateurs de l'etape1 se calculent en fonction de l'etape0 comme ca peut etre en fonction des indic de l'etape0 et de l'etape1. En premier temps, je veux identifier les indicateurs de l'etape1 qui sont en fonction seulement de l'etape0 et les caluler, puis traiter les indics=f(etape0.Indi,etape1.Indj) rempler les etape1.indj par des etape0.indi et les calculer après. Pour identifier les indicateursqui sont en fonction que des indics de l'etape0, je dois décomposer la formule de l'etape1 :
par exemple :
etape1.Ind0=etape0.Ind0+etape0.Ind1 je la décompose :
etape0.Ind0/etape0.Ind1 (remplacer l'opérateur)
etape0.Ind0 (chercher le premier composant et tester si le prefixe etapei=etape0 si oui tester le deuxième composant)
donc j'aurais besoin de savoir le nbre de composants dans chaque formule et l'utiliser dans une boucle
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 12h14   #16
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
J'ai modifié la structure de la table.
Est ce que sous cette format c'est plus simple de traiter ton problème?
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DATA etape1;
code_ind="Ind0";formule="etape1.Ind0+etape0.Ind1";output;
code_ind="Ind1";formule="etape1.Ind3-etape0.Ind3";output;
code_ind="Ind2";formule=" etape1.Ind1*etape1.Ind5";output;
code_ind="Ind3";formule=" etape0.Ind2/etape0.Ind4";output;
code_ind="Ind5";formule=" etape0.Ind5";output;
run;
DATA t4;
SET etape1;
t=translate(formule,'/','*','/','+','/','-');
nb_slash=count(t,'/');
do i=1 TO nb_slash+1;
put i nb_slash;
	k=scan(t,i,'/');output;
end;
 
run;
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 12h34   #17
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
nn ca répond pas à mon besoin, puisqu'il ne me ramène que le dernier composant de la fomrule, en fait chaque formule a un nbre variable de composants (séparés pard des opérateurs) et je dois traiter chaque composant de chaque formule à part.
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 12h42   #18
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
tu as bien contrôler le nombre de ligne?
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 12h47   #19
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
yep, mais ca marche po
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 13h01   #20
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
si j'ai bien compris tu veux comparer etape1.Ind0 avec etape0.Ind1
les comparaison sont a faire sur les éléments de la même ligne.
tu peux t'inspirer de cette exemple pour résoudre ton problème.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
DATA t4;
SET etape1;
t=translate(formule,'/','*','/','+','/','-');
nb_slash=count(t,'/');
array tab{30} $30. _TEMPORARY_; /*on initialise un tableau de 30 éléments*/
 
/*boucle pour alimenter mon tableau*/
do i=1 TO nb_slash+1;
	tab[i]=scan(t,i,'/');/*Alimentation du tableau*/
end;
/*boucle pour comparer les éléments*/
do i=2 TO nb_slash+1;
	IF tab[i]= tab[i-1] then top=1;
	else top=0;
end;
run;
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 10h22.


 
 
 
 
Partenaires

Hébergement Web