BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
ppinedo
Fluorite | Level 6

hello everyone,

%macro p2(datos,clase1,clase2);
    proc tabulate data=&datos format=commax10.;
class ANYO; class &clase1 &clase2/ missing preloadfmt order=data mlf;
tables &clase1*&clase2 all="Total";
%if "&clase1"=A %then .............; %if "&clase1"=B %then .............; %if "&clase1"=C %then .............; %if "&clase1"=D %then .............; %if "&clase1"=E %then .............;
..............;
%if "&clase1"=X %then .............; %if "&clase1"=Y %then .............; %if "&clase1"=Z %then .............; %if "&clase1"="SEXO" %then format &clase1 SEXO.; run; %mend; %p1(people,SEXO,EDAD);

I get this message: "WARNING: Variable RUN not found in data set WORK.people" What does it mean?? Why I get it and how I can solve it without %do; ... %end;??

 

1 ACCEPTED SOLUTION

Accepted Solutions
yabwon
Onyx | Level 15

You need a semicolon after format statement, the semicolon you have there ends %if-%then block

 

%macro p2(datos,clase1,clase2);
    proc tabulate data=&datos format=commax10.;
 class &clase1 &clase2/ missing preloadfmt order=data mlf;
tables &clase1*&clase2 all="Total";
%if "&clase1"=A %then .............;
%if "&clase1"=B %then .............;
%if "&clase1"=C %then .............;
%if "&clase1"=D %then .............;
%if "&clase1"=E %then .............;
..............;
%if "&clase1"=X %then .............;
%if "&clase1"=Y %then .............;
%if "&clase1"=Z %then .............;
%if "&clase1"="SEXO" %then
	format &clase1 SEXO.; /* <- THIS semicolon ends the %if-%then statement NOT format statement */
    run;
%mend;

%p1(people,SEXO,EDAD);

Good practice: use %do; -%end; groups

 

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



View solution in original post

6 REPLIES 6
yabwon
Onyx | Level 15

You need a semicolon after format statement, the semicolon you have there ends %if-%then block

 

%macro p2(datos,clase1,clase2);
    proc tabulate data=&datos format=commax10.;
 class &clase1 &clase2/ missing preloadfmt order=data mlf;
tables &clase1*&clase2 all="Total";
%if "&clase1"=A %then .............;
%if "&clase1"=B %then .............;
%if "&clase1"=C %then .............;
%if "&clase1"=D %then .............;
%if "&clase1"=E %then .............;
..............;
%if "&clase1"=X %then .............;
%if "&clase1"=Y %then .............;
%if "&clase1"=Z %then .............;
%if "&clase1"="SEXO" %then
	format &clase1 SEXO.; /* <- THIS semicolon ends the %if-%then statement NOT format statement */
    run;
%mend;

%p1(people,SEXO,EDAD);

Good practice: use %do; -%end; groups

 

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



ppinedo
Fluorite | Level 6

Thanks @yabwon , if there's only one sentence why I need to close %if🤔? if I use more than one sentence, can I use double semicolon ??

..................;
.................;
%if "&clase1"="SEXO_1F" %then
	format &clase1 SEXO.;;
    run;
%mend;

yabwon
Onyx | Level 15

You need a semicolon to end the macro language statement:

 

%if "&clase1"="SEXO_1F" %then
format &clase1 SEXO.;;
run;
%mend;

 

Mind the order of colours! Red semicolon and then the blue one, 

the same way you would "close" the put statement:

 

%put some text to print ; /* this semicolon ends the %put statement */

 

 

If you have a 4GL code which contains semicolons you basically have to use %do;-%end; block

 

This will fail:

 

%macro p1(datos,clase1,clase2);

data _nulL_;

%if "&clase1"="SEXO" %then
	format &clase1 dollar12.2; &clase1=17; y=42; ;

run;
%mend;

%p1(people,SEXO,EDAD);

because the semicolon after "dollar12.2" is interpreted as %if-%then statement end;

 

Log looks like this:

1    %macro p1(datos,clase1,clase2);
2
3    data _nulL_;
4
5    %if "&clase1"="SEXO" %then
6      format &clase1 dollar12.2; &clase1=17; y=42; ;
7
8    run;
9    %mend;
10
11   %p1(people,SEXO,EDAD);
NOTE: Line generated by the invoked macro "P1".
6     &clase1=17; y=42; ;  run;
             -
             85
             76

ERROR 85-322: Expecting a format name.

ERROR 76-322: Syntax error, statement will be ignored.

NOTE: The SAS System stopped processing this step because of errors.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds
      cpu time            0.01 seconds

But if you add %do;-%end; block everything works fine:

 

%macro p1(datos,clase1,clase2);

data _nulL_;

%if "&clase1"="SEXO" %then 
  %do;
	format &clase1 dollar12.2; &clase1=17; y=42; 
  %end;

run;
%mend;

%p1(people,SEXO,EDAD);

Log:

 

1    %macro p1(datos,clase1,clase2);
2
3    data _nulL_;
4
5    %if "&clase1"="SEXO" %then
6      %do;
7      format &clase1 dollar12.2; &clase1=17; y=42;
8      %end;
9
10   run;
11   %mend;
12
13   %p1(people,SEXO,EDAD);

NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

 

Remember all the "hardness" of macro programming is that your code (the macro language statements) and your data (the 4GL code) are mixed together in one place (a text file with code), so you have to have precise rules to tell SAS which is which. 

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



ballardw
Super User
%if "&clase1"=A %then

never true. The quotes are part of the comparison.

 

If all of the variables likely to be used in this macro exist in the data set, i.e. the data set always has the same structure just using different versions of the data, then just have all the format statements as part of the code. The worst that would happen is if the variable in the FORMAT statement doesn't exist is a warning in the log. If the variables are there but not used you don't have to worry about any of these conditional assignments.

If you conditions involve style elements or table structure that is a different story.

 

BTW, if you are using the macro to make multiple tables you may consider multiple table statements in Proc Tabulate and not have to make multiple calls. Many people don't realize that Proc Tabulate (and Freq) will allow multiple different table statements such as:

proc tabulate data=sashelp.class;
   class sex age;
   var height weight;

   table sex,age;
   table sex*age,
         height*(min mean max);
   table sex,
         age*weight*(mean stddev)
   ;
run;

Tabulate will require that a variable be used in the same role for all table requests though. So if you want to use a variable as a CLASS variable in one table and VAR variable in a different table then multiple calls to tabulate will be required.

ppinedo
Fluorite | Level 6

ok. you're right @ballardw, I wanted to say:

%if &clase1=A %then ..........
Tom
Super User Tom
Super User

When you have a single statement that spans multiple lines it will make the program much easier for humans to read if you place the semicolon that ends the statement on its own line.  So your %IF statement should look like:

%if "&clase1"="SEXO" %then
  format &clase1 SEXO.
;

Now it is more obvious that the FORMAT statement does not have an ending semicolon.

 

But it is better practice when a macro statement like %IF is controlling the generation of complete statements (not just fragments) to use explicit %DO/%END block.

%if "&clase1"="SEXO" %then %do;
  format &clase1 SEXO. ;
%end;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 6 replies
  • 461 views
  • 2 likes
  • 4 in conversation