Makro-Schleife

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;

%probe;

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?

data zieldat;
set &nam.&dat. (keep = KTO);
run;

_____________________________________________

%macro MonatsScheiben2;
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:

&nam

ist eine Makrovariable. Die Bezeichnung

&nam.&dat

soll zu

libname.datei

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:

&nam..&dat.

.
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

&NAM.&DAT.

zu dem Inhalt der Macrovariable

&NameMMYY.

aufgelöst werden soll. Dann wäre die Syntax

&&NAM.&DAT.

Der Code

&NAM..&DAT.

würde z.B. zu

libname.0110

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

*);*/;/*'*/ /*"*/; %mend;run;quit;;;;;

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.

%macro MonatsScheiben2;
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

if put(lfdatum,mmyyn4.) = &dat.;

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:

%macro MonatsScheiben2;
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:

%macro probe;
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:

%macro probe;
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!