Makro-Schleife
Verfasst von bezNika am 1 Februar, 2010 - 15:02
hallo, wenn ich unten stehendes macro ausführe, bekomme ich folgende Fehlermeldung:
'a character operand was found in the %eval function or %if condition where a numeric operand is required. The condition was: anzz'.
weiß vielleicht jemand, woran es liegen könnte?
vielen Dank im Voraus!
%macro probe;
proc sql noprint;
select distinct(waehiso) into: lfd separated by ' '
from ivgessum;
quit;
proc sql noprint;
create table a as
select distinct(waehiso)
from ivgessum;
quit;
proc sql noprint;
select count(*) into: anzz
from a;
quit;
%put &anzz;
%do i = 1 %to &anzz;
dat = %scan(&lfd, i, ' ');
data iv_&dat;
set ivgessum;
run;
%end;
%mend;
proc sql noprint;
select distinct(waehiso) into: lfd separated by ' '
from ivgessum;
quit;
proc sql noprint;
create table a as
select distinct(waehiso)
from ivgessum;
quit;
proc sql noprint;
select count(*) into: anzz
from a;
quit;
%put &anzz;
%do i = 1 %to &anzz;
dat = %scan(&lfd, i, ' ');
data iv_&dat;
set ivgessum;
run;
%end;
%mend;
%probe;
»
- Anmelden oder Registrieren um Kommentare zu schreiben

Hallo, und noch ein weiteres
Hallo, und noch ein weiteres Problem:
mit folgendem data-step in diesem Macro wollte ich gleich die werte in eine andere Tabelle schreiben, doch es geht irgendwie nicht. Weiß vielleicht jemand, woran es liegt?
set &nam.&dat. (keep = KTO);
run;
_____________________________________________
proc sort data=kund;
by lfdatum;
run;
proc sql noprint;
select distinct(lfdatum) format mmyyn4. into: lfd separated by ' '
from kund;
quit;
%let i = 1;
%let dat = %scan(&lfd, &i, ' ');
%do %while (%length(&dat.));
data iv_&dat.;
set kund;
if lfdatum = &dat.;
run;
data zieldat;
set &nam.&dat. (keep = KTO);
run;
%let i = %eval(&i.+1);
%let dat = %scan(&lfd., &i.);
%end;
%mend;
RE: Hallo, und noch ein weiteres
Auf den ersten Blick:
ist eine Makrovariable. Die Bezeichnung
soll zu
aufgelöst werden. Der Punkt ist aber das Begrenzungszeichen für die Makrovariable, gehört also zur Makrovariable und löst sich in wohlgefallen auf. Also muss es heißen:
.
Sieht blöd aus, ist aber so :-)
Viel Spass
Dubravko Dolic
RE:RE: Noch ein weiteres
Hallo Herr Dolic,
woher wissen Sie das? Es kann doch auch sein, dass
zu dem Inhalt der Macrovariable
aufgelöst werden soll. Dann wäre die Syntax
Der Code
würde z.B. zu
führen, da in &Dat. ein Datum mit dem Format DDMM4. steckt. Dann wäre ein Fehler unvermeidlich, da ein solcher Name nicht zulässig ist.
Ich bleib dabei, ohne weitere Informationen kann man nicht helfen. Und die Aussage "...doch es geht irgendwie nicht. Weiß vielleicht jemand, woran es liegt?" hilft da nicht gerade weiter.
Jan
Sie Fuchs
...das kann natürlich sein. Ich habe mir erlaubt, den Inhalt zu interpretieren und aufgrund der Erfahrung ist es in vielen Fällen so, wie von mir beschrieben.
Und natürlich haben Sie recht, mit "irgendwie" kommt man selten weiter.
Hallo,
Hallo,
ein bisschen mehr an Information wäre schon hilfreich?
Woher kommt &nam.? Und was sollte darin sein?
Was für eine Fehlermeldung bekommst Du?
Füg doch mal die Zeile "%PUT &Nam.&dat.;" ein, damit Du siehst, zu was der Code aufgelöst wird.
Beschäftige Dich mal mit den Optionen mfile mprint mprintnest mlogic mlogicnest symbolgen.
Außerdem ist %PUT eine Möglichkeit zur Ausgabe von Variableninhalten.
Das Debuggen von Macros ist mühsam, geht aber.
Und wenn Dir das Verhalten von SAS allzu merkwürdig vorkommt, dann sicher Deine Arbeit , schließe SAS und starte es neu. Gerade bei der Macroprogrammierung wirkt dies manchmal Wunder.
Jan
Makro Magic String
Ja, dem Vorredner (resp. Schreiber) ist absolut zuzustimmen. Gerade in der Lernphase wird man wohl um das eine oder andere mal SAS schließen und wieder öffnen nicht herum kommen. Ggf. könnte man es zunächst noch mit folgendem String versuchen
In der Regel reagiert SAS nämlich empfindlich auf vergessene Schlüsselworte (oder vergessene token). Mit dem String kann man versuchen, diese abzufangen.
Am besten speichert man sich den String in einem Tastaturmakro und hat ihn somit schnell verfügbar.
Hier ein Tastaturmakro, mit dem sich der Magic-String schnell erzeugen lässt. Was Tastaturmakros sind kann man im Schnellüberblick oder ausführlich hier nachlesen.
Viel Spass
Dubravko Dolic
jetzt habe ich aber ein
jetzt habe ich aber ein weiteres Problem:
das Makro soll eine große Datei in Monatsscheiben schneiden.
In diesem DATA-Step(aus dem Makro)
data iv_&dat.;
set kund;
if lfdatum = &dat.;
run;
sollen nur die Sätze gelesen, bei denen lfdatum = &dat ist.
Benannt werden die Tabellen richtig, entsprechende Sätze werden aber nicht rausgefiltert.
proc sort data=kund;
by lfdatum;
run;
proc sql noprint;
select distinct(lfdatum) format mmyyn4. into: lfd separated by ' '
from kund;
quit;
%let i = 1;
%let dat = %scan(&lfd, &i, ' ');
%do %while (%length(&dat.));
data iv_&dat.;
set kund;
if lfdatum = &dat.;
run;
%let i = %eval(&i.+1);
%let dat = %scan(&lfd., &i.);
%end;
%mend;
Hallo, führe mal folgenden
Hallo,
führe mal folgenden Code aus und schaue in das Log:
%macro MonatsScheiben2;
proc sort data=kund;
by lfdatum;
run;
proc sql noprint;
select distinct(lfdatum) format mmyyn4. into: lfd separated by ' '
from kund;
quit;
%put &lfd.;
options mprint;
%let i = 1;
%let dat = %scan(&lfd, &i, ' ');
%do %while (%length(&dat.));
data iv_&dat.;
set kund;
if lfdatum = &dat.;
run;
%let i = %eval(&i.+1);
%let dat = %scan(&lfd., &i.);
%end;
%mend;
Daran erkennst Du, dass rechts des Gleichheitszeichens im Datastep nicht mehr das ursprüngliche Datum mehr steht, sondern irgendetwas (format: mmyyn4.) vierstelliges, sprich ein Datum um 1964 (Tage ab dem 01.01.1960).
Du müsstest dieses Format auch im Datastep verwenden, also
Ob die Verstümmelung auf den Monat allerdings fachlich korrekt ist vermag ich nicht zu beurteilen.
Viele Grüße
Wolfgang
Hallo, im Datastep muss die
Hallo,
im Datastep muss die Makrovariable &DAT. in Anführungszeichen gesetzt werden, da die Funktion PUT einen Text liefert. Wenn man den Vorschlag von Alex aufgreift sähe der Code so aus:
proc sql noprint;
select distinct(lfdatum) format mmyyn4. into: lfd separated by ' '
from kund;
quit;
%DO I = 1 %TO &SQLOBS.;
%LET DAT = %SCAN(&LFD., &I.,%STR( ));
data iv_&dat.;
set kund;
if put(lfdatum,mmyyn4.) = "&DAT.";
run;
%END;
%mend;
%monatsscheiben2;
Im Makrocode werden Texte nicht in Hochkommas gesetzt, also %SCAN(&LFD., &I., %STR( )), wenn nur das Leerzeichen ein Trennzeichen sein soll. Generiert man dagegen Code für den SAS-Prozessor, werden Texte wie gewöhnlich in Anführungszeichen eingeschlossen z. B. if put(lfdatum,mmyyn4.) = "&DAT.";
.
Schöne Grüße
Jan
Hochkommata
stimmt, die hatte ich im Eifer des Gefechts noch vergessen.
Viele Grüße
Wolfgang
Macro-Texte nicht in Hochkommas
Hallo,
die Anzahl muss man vorher nicht ermitteln, dass geht auch mit einer %WHILE-Schleife.
In %SCAN ist zusätzlich zu dem vergessenen '&' vor i das Leerzeichen als Trenner mit Hochkommas angegeben. Das Leerzeichen muss nicht extra angegeben werden, und wenn, nicht in Hochkommas, sondern mit %STR( ). In Makros werden Texte nicht in Anführungszeichen oder Hochkommas gesetzt.
Vor dat = %scan(&lfd, i, ' '); fehlt ein %LET.
So würde der Code laufen:
proc sql noprint;
select distinct(waehiso) into: LFD separated by ' '
from ivgessum;
quit;
%LET I = 1;
%LET DAT = %SCAN(&LFD., &I.);
%DO %WHILE(%LENGTH(&DAT.)) ;
data iv_&DAT.;
set ivgessum;
run;
%LET I = %EVAL(&I. + 1);
%LET DAT = %SCAN(&LFD., &I.);
%END;
%mend;
Schöne Grüße
Jan Heuer
&sqlobs
Hallo zusammen,
in solchen Fällen verwende ich in der Regel die automatisch befüllte sqlobs-Variable, was den Makro-Loop etwas vereinfacht:
proc sql noprint;
select distinct(waehiso) into: LFD separated by ' '
from ivgessum;
quit;
%LET N_LFD = &SQLOBS ;
%DO I = 1 %to &N_LFD ;
%LET DAT = %SCAN(&LFD., &I.);
data iv_&DAT.;
set ivgessum;
run;
%END;
%mend;
Die Zuweisung an N_LFD kann man sich natürlich auch noch schenken. Das macht aber bei der Wahl eines aussagekräftigen Namens den Code besser interpretierbar.
Beste Grüße
Alex K.
Hallo Jan Heuer, so sieht das
Hallo Jan Heuer,
so sieht das Macro natürlich viel schöner aus! Vielen Dank!
als erstes fällt mir auf,
als erstes fällt mir auf, dass es wahrscheinlich
%let dat = %scan(&lfd, &i, ' '); heissen soll.
durch das i in dat = %scan(&lfd, i, ' ');haben Sie einen Charakter-String wo eine Zahl benötigt wird
Hallo Muschik, das stimmt,
Hallo Muschik,
das stimmt, daran lag es. Danke-Danke!