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

I am trying to do the following but I can not get the location begin_date or teacher to chance when the %let crsnum changes. the location begin_date and teacher are stuck with the same info.

/**picking a course number, print out the roster for the course with:
    Location, start date and teacher's name in the title(s)
    Number paid out of total registered and outstanding fees due in the footer***/
    
    
    **Datasets used are mysas.register schedule courses**;

%let crsnum=13;    
%macro ex1;    
data revenue;
 set mysas.register end=final;
 where course_number=&crsnum;
 total+1;
 if paid='Y' then paidup+1;
    
 if final then do;
  put total= paidup=;
    
  if paidup < total then do;
    %let foot=Outstanding fees due;
  end;
  else do;
    %let foot=Number paid out of total registered;
  end;
 end;
run;

        %if &crsnum %then %do;
                data _null_;
                 set mysas.schedule;
                 call symput('loc',location);
                run;
                %put &loc;
                
                data _null_;
                 set mysas.schedule;
                 call symput('date',put(begin_date,date9.));
                run;
                %put  &date;
                
                data _null_;
                 set mysas.schedule;
                 call symput('teach',teacher);
                run;
                %put  &teach;

        %end;
Title "&loc &date &teach";
proc print data=mysas.register noobs;
    where course_number=&crsnum;
    footnote "&foot";
run;
%mend;
%ex1;

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Why is this coded as a macro?  There is no conditional logic that could not be handled via data step logic. The macro has no input parameters defined.

%let crsnum=13;    

data revenue;
  set mysas.register end=final;
  where course_number=&crsnum;
  total+1;
  if paid='Y' then paidup+1;
  if final then do;
    put total= paidup=;
    if paidup < total then call symputx('foot','Outstanding fees due');
    else call symputx('foot','Number paid out of total registered');
  end;
run;

data _null_;
  set mysas.schedule;
  if &crsnum then do;
    call symputx('loc',location);
    call symputx('date',put(begin_date,date9.));
    call symputx('teach',teacher);
  end;
run;

%put &=loc &=date &=teach;
%put &=foot;

title "&loc &date &teach";
footnote "&foot";
proc print data=mysas.register noobs;
  where course_number=&crsnum;
run;

But shouldn't the IF test in the data _null_ step really be more like the WHERE statement in the first data step?

View solution in original post

12 REPLIES 12
Reeza
Super User
Couple of quick questions to start, does your code work without macro logic? Which part specifically are you having issues with? Can you provide the sample data as well to support working on this question.
chrissowden
Obsidian | Level 7

yes my code works but the location begin date and teacher doesn't change

Reeza
Super User

In general, this is a pretty robust approach for creating a macro, but it does require working code.  

 

https://github.com/statgeek/SAS-Tutorials/blob/master/Turning%20a%20program%20into%20a%20macro.md

 

Just some quick comments on your code:

  • You should combine some of the data _null_ steps
  • Use CALL SYMPUTX() instead of CALL SYMPUT()
  • If you're not filtering the 'schedule data set' how are you sure it's the correct data since it likely has more than one value?

@chrissowden wrote:

I am trying to do the following but I can not get the location begin_date or teacher to chance when the %let crsnum changes. the location begin_date and teacher are stuck with the same info.

/**picking a course number, print out the roster for the course with:
    Location, start date and teacher's name in the title(s)
    Number paid out of total registered and outstanding fees due in the footer***/
    
    
    **Datasets used are mysas.register schedule courses**;

%let crsnum=13;    
%macro ex1;    
data revenue;
 set mysas.register end=final;
 where course_number=&crsnum;
 total+1;
 if paid='Y' then paidup+1;
    
 if final then do;
  put total= paidup=;
    
  if paidup < total then do;
    %let foot=Outstanding fees due;
  end;
  else do;
    %let foot=Number paid out of total registered;
  end;
 end;
run;

        %if &crsnum %then %do;
                data _null_;
                 set mysas.schedule;
                 call symput('loc',location);
                run;
                %put &loc;
                
                data _null_;
                 set mysas.schedule;
                 call symput('date',put(begin_date,date9.));
                run;
                %put  &date;
                
                data _null_;
                 set mysas.schedule;
                 call symput('teach',teacher);
                run;
                %put  &teach;

        %end;
Title "&loc &date &teach";
proc print data=mysas.register noobs;
    where course_number=&crsnum;
    footnote "&foot";
run;
%mend;
%ex1;


 

Astounding
PROC Star

There is nothing about your code that would ever change the value of those macro variables:  &LOC, &DATE, and &TEACH.

 

They all come from the final observation in MYSAS.SCHEDULE.  

 

That's probably not what you intended, but it's difficult to be sure.  We have to rely on you to supply that piece.

 

Also note, %LET statements are never part of a DATA step.  IF THEN statements do not affect whether or not they execute.  If you want &FOOT to depend on conditions in the DATA step, use CALL SYMPUTX instead of %LET:

 

if paidup < total then do;
    call symputx('foot', 'Outstanding fees due');
  end;

 

They way the code stands now, you might as well take both %LET statements:


    %let foot=Outstanding fees due;
    %let foot=Number paid out of total registered;

 

Since they're not part of the DATA step, just place them before the DATA step begins (and remove them from the DATA step itself).  That's actually the order in which the statements execute.

chrissowden
Obsidian | Level 7

That's the section of the code that I know is not working correctly. The current code will keep the &loc &date &teach the same even if the course number changes. I want the macro variables to change when I choose a different course number

Astounding
PROC Star

So how do you know which values you want to extract from MYSAS.SCHEDULE?  If there is just one observation per course number, and if you want to select the values that match, you could add a WHERE statement:

 

data _null_;
        set mysas.schedule;

        where course_number = &crsnum;
         call symput('teach',teacher);

run;

Tom
Super User Tom
Super User

Why is this coded as a macro?  There is no conditional logic that could not be handled via data step logic. The macro has no input parameters defined.

%let crsnum=13;    

data revenue;
  set mysas.register end=final;
  where course_number=&crsnum;
  total+1;
  if paid='Y' then paidup+1;
  if final then do;
    put total= paidup=;
    if paidup < total then call symputx('foot','Outstanding fees due');
    else call symputx('foot','Number paid out of total registered');
  end;
run;

data _null_;
  set mysas.schedule;
  if &crsnum then do;
    call symputx('loc',location);
    call symputx('date',put(begin_date,date9.));
    call symputx('teach',teacher);
  end;
run;

%put &=loc &=date &=teach;
%put &=foot;

title "&loc &date &teach";
footnote "&foot";
proc print data=mysas.register noobs;
  where course_number=&crsnum;
run;

But shouldn't the IF test in the data _null_ step really be more like the WHERE statement in the first data step?

Reeza
Super User

Why is this coded as a macro?  There is no conditional logic that could not be handled via data step logic. The macro has no input parameters defined.

 

Because it's homework 🙂

chrissowden
Obsidian | Level 7

it's not homework. The macro doesn't have to be there. I was just trying a few different ways. I just can't seem to get the names of the teachers and locations to change.

Reeza
Super User
>If you're not filtering the 'schedule data set' how are you sure it's the correct data since it likely has more than one value?

You were using the schedule data set and having call symput execute on every row. We can't see that data but I'm guessing it needed to be filtered, you can see that's what Tom did in his code. If his solution doesn't work, post back with the log and details.
chrissowden
Obsidian | Level 7

here is the log:

 

 
1 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
72
73 %let crsnum=6;
74
75 data revenue;
76 set mysas.register end=final;
77 where course_number=&crsnum;
78 total+1;
79 if paid='Y' then paidup+1;
80 if final then do;
81 put total= paidup=;
82 if paidup < total then call symputx('foot','Outstanding fees due');
83 else call symputx('foot','Number paid out of total registered');
84 end;
85 run;
 
total=27 paidup=17
NOTE: There were 27 observations read from the data set MYSAS.REGISTER.
WHERE course_number=6;
NOTE: The data set WORK.REVENUE has 27 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.34 seconds
cpu time 0.03 seconds
 
 
86
87 data _null_;
88 set mysas.schedule;
89 where (&crsnum );
90 call symputx('loc',location);
91 call symputx('date1',put(begin_date,date9.));
92 call symputx('teach',teacher);
93
94 run;
 
NOTE: There were 18 observations read from the data set MYSAS.SCHEDULE.
WHERE 6 /* an obviously TRUE WHERE clause */ ;
NOTE: DATA statement used (Total process time):
real time 0.18 seconds
cpu time 0.00 seconds
 
 
95
96 %put &=loc &=date1 &=teach;
LOC=Dallas DATE1=25MAR2002 TEACH=Berthan, Ms. Judy
97
98
99
100 %put &=foot;
FOOT=Outstanding fees due
101 title "&loc &date &teach";
102 footnote "&foot";
103 proc print data=mysas.register noobs;
104 where course_number=&crsnum;
105 run;
 
NOTE: There were 27 observations read from the data set MYSAS.REGISTER.
WHERE course_number=6;
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.07 seconds
cpu time 0.06 seconds
 
 
106
107 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
120
 
chrissowden
Obsidian | Level 7

THanks... it was the where clause that fixed the problem. Thank you!!

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
  • 12 replies
  • 1386 views
  • 0 likes
  • 4 in conversation