BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
shihabur
Obsidian | Level 7

Hello Everyone. I found this macro program on "counting total observation" in a SAS paper and was trying to recreate it. In a nutshell it :

  • checks if the data exists,
  • checks if sas engine knows the number of observation,
  • checks if there is an active where clause or not and
  • finally runs a loop to count the number of obs.

Whenever I am running it with " %MTCNTOBS(data = country);" there is an error:

ERROR 180-322: Statement is not valid or it is used out of proper order. Country is sample dataset I created. The error is same even for sashelp.class. Can any one please help me understand why its showing the error ?

 

 

%macro MTCNTOBS(data=_last_);
	%local dsid anobs whstmt counted rc;
	%let DSID = %sysfunc(open(&DATA., IS));
	%if &DSID = 0 %then
		%do;
		%put %sysfunc(sysmsg());
		%let counted = .;
		%goto mexit;
		%end;
	%else
		%do;
		%let anobs = %sysfunc(attrn(&DSID, ANOBS));
		%let whstmt = %sysfunc(attrn(&DSID, WHSTMT));
		%end;
	%if &anobs = 1 & &whstmt = 0 %then
		%let counted = %sysfunc(attrn(&DSID, NLOBS));
	%else
		%do;
		%if %sysfunc(getoption(msglevel)) = I %then
		%put INFO: Observations in "&DATA." must be counted by iteration.;
		%let counted = 0;
		%do %while (%sysfunc(fetch(&DSID)) = 0);
		%let counted = %eval(&counted. + 1);
		%end;
		%end;

	%let rc = %sysfunc(close(&DSID));

%MEXIT:
&COUNTED.
%mend MTCNTOBS;

NOTE: Despite the error, the code is executed and the macro variable 'counted' at the end prints the correct number of observation in the log. Just in case if someone wants to see the paper, I am attaching it.

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

The issue lies in how you call the macro.  For example:

 

%MTCNTOBS (data=mydata)

 

This is improper usage.  The macro generates a number.  If you added a number in the middle of a SAS program, SAS would give you the error message you are encountering.  Correct usage would be:

 

%let my_macro_var = %MTCNTOBS (data=mydata);

%put Number of observations is &my_macro_var..;

 

The macro still generates a number, but that number gets assigned to a macro variable by the %LET statement.  There are plenty of other places besides a %LET statement that can digest a number as part of SAS statement or a macro language statement.  This is just one example.

View solution in original post

6 REPLIES 6
RW9
Diamond | Level 26 RW9
Diamond | Level 26

What do you need the count for exactly as the simplest way is to do:

data want;
  set sashelp.vtable (where=(libname="<yourlib>" and memname="<yourds>"));
run;

Replace <yourlib> and <yourds> (note should be upcase) respectively, this will return 1 line if the dataset exists, with observation count and other information.  There are other v<table>'s in sashelp which show columns, and other metadata.

Astounding
PROC Star

The issue lies in how you call the macro.  For example:

 

%MTCNTOBS (data=mydata)

 

This is improper usage.  The macro generates a number.  If you added a number in the middle of a SAS program, SAS would give you the error message you are encountering.  Correct usage would be:

 

%let my_macro_var = %MTCNTOBS (data=mydata);

%put Number of observations is &my_macro_var..;

 

The macro still generates a number, but that number gets assigned to a macro variable by the %LET statement.  There are plenty of other places besides a %LET statement that can digest a number as part of SAS statement or a macro language statement.  This is just one example.

shihabur
Obsidian | Level 7

Thanks for the elaborate explanation. Now I got the mistake.

shihabur
Obsidian | Level 7

Just in an effort to understand more clearly: "%MTCNTOBS (data=mydata)" this is wrong BECAUSE this specific macro generates a number ? But if the goal of the macro was to create separate tables or just print a table in that case its okay to call the macro like this, right ?

Astounding
PROC Star

The goal has to be to create a valid SAS program.  Let's say the macro returns the number 25.  This would be an invalid program:

 

proc print data=sashelp.class;

run;

25

proc print data=sashelp.class;

run;

 

It doesn't matter how the 25 got there, 25 is invalid in that context, in the middle of a SAS program.  So if you coded:

 

proc print data=sashelp.class;

run;

%MTCNTOBS (data=mydata)

proc print data=sashelp.class;

run;

 

That would be an invalid SAS program, the exact same invalid SAS program.  It doesn't matter how the "25" got into the middle of the program.  It would still be invalid.  However, this would be valid:

 

proc print data=sashelp.class (obs=25);

run;

 

Therefore, this would also be valid:

 

proc print data=sashelp.class (obs=%MTCNTOBS (data=mydata));

run;

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 6 replies
  • 2011 views
  • 2 likes
  • 3 in conversation