SAS Programming

DATA Step, Macro, Functions and more
BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
djbateman
Lapis Lazuli | Level 10

I have a macro variable that I split up into X number of macro variables, each macro variable storing a number.  I want to sum up those number.  I cannot get the code below to work properly.  Can anyone help me figure out how to use the SUM() function with macro variables?

%macro enrollment(rampdata=);

     %let rampmo=%sysfunc(countw(&rampdata.,'|'));

     %put &rampmo.;

     %do i=1 %to &rampmo.;

          %let ramp&i.=%scan(&rampdata.,&i.,'|');

          %let ramp&i.=%sysfunc(compress(&&ramp&i.));

          %put &&ramp&i.;

     %end;

     %let rampsum=%eval(sum(OF ramp1-ramp&rampmo.));     /* I know this is wrong, and I tried different way here.  Can't figure it out. */

     %put &steadymo.;

%mend enrollment;

%enrollment(rampdata=0|1|2|2|4|4|5|6|8|8|13|10|10);

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

The SUM function doesn't exist in macro language.  In general, to use DATA step functions in macro language, you have to apply %SYSFUNC:

%let rampsum = %eval(%sysfunc(sum(of ramp1 - ramp&rampmo.)));

Even this is not a working statement, as the word OF causes trouble for macro language.

Better yet, skip most of the code and shift to:

%let rampsum = %eval(%sysfunc(translate(&rampdata, +, |)));

This will convert all the "|" to "+", then perform the math.

Good luck.

View solution in original post

5 REPLIES 5
Astounding
PROC Star

The SUM function doesn't exist in macro language.  In general, to use DATA step functions in macro language, you have to apply %SYSFUNC:

%let rampsum = %eval(%sysfunc(sum(of ramp1 - ramp&rampmo.)));

Even this is not a working statement, as the word OF causes trouble for macro language.

Better yet, skip most of the code and shift to:

%let rampsum = %eval(%sysfunc(translate(&rampdata, +, |)));

This will convert all the "|" to "+", then perform the math.

Good luck.

Patrick
Opal | Level 21

2 more alternatives:

/* alternative 1 */
%macro enrollment(rampdata=);
  %let rampmo=%sysfunc(countw(&rampdata.,'|'));
  %put &rampmo.;
  %let rampsum=;
  %do i=1 %to &rampmo.;
    %let rampsum=%sysevalf(&rampsum + %scan(&rampdata.,&i.,'|'));
  %end;
  %put rampsum= &rampsum.;
%mend enrollment;

%enrollment(rampdata=0|1|2|2|4|4|5|6|8|8|13|9.5|10.5);


/* alternative 2 */
%let rampdata=0|1|2|2|4|4|5|6|8|8|13|9.5|10.5;
%let rampsum2=%sysfunc(sum(%sysfunc(translate(&rampdata,+,|))));
%put rampsum2= &rampsum2;

data_null__
Jade | Level 19

Looks like you are on the road to ruin with a macro like that.  It just seems wrong to me on many levels.  What are you trying to do?

Having said that Patrick almost has it but instead of + is should be comma to accommodate missing values.

 

39 %macro enrollment(rampdata=);

40 %let sum = %sysfunc(sum(%sysfunc(translate(%superQ(rampdata),%str(,),|))));

41 %put NOTE: SUM=∑

42 %mend;

43 %enrollment(rampdata=0|1|2|2|4|4|.|5|6|8|8|13|10|10);

NOTE: SUM=73

Tom
Super User Tom
Super User

I prefer to use spaces as delimiters in strings.  They are easy to type, read and pass as parameters to macros.

Using a space also makes it easy to handle empty strings by adding a default value inside of the call to translate() to prevent syntax errors when the list in the macro variable is empty.

%let list= 1 2 3;

%let sum=%sysfunc(sum(%sysfunc(translate(. &list,%str(,),%str( )))));

%put sum(&list)=∑

sum(1 2 3)=6

%let list= ;

%let sum=%sysfunc(sum(%sysfunc(translate(. &list,%str(,),%str( )))));

%put sum(&list)=∑

sum()=.

Ksharp
Super User

The following is inherited from your code. If you like, but I recommend to use Astounding's code.

%macro enrollment(rampdata=);
     %let rampmo=%sysfunc(countw(&rampdata.,|));
     %put &rampmo.;
     %do i=1 %to &rampmo.;
          %let ramp&i.=%scan(&rampdata.,&i.,|);
          %let ramp&i.=%sysfunc(compress(&&ramp&i.));
        %if &i=1 %then %let list=&ramp1 ;
         %else %let list= &list , &&ramp&i   ;
          %put &&ramp&i.;
     %end;
     %put &list ;
     %let rampsum=%sysfunc(sum( &list ));     /* I know this is wrong, and I tried different way here.  Can't figure it out. */
     %put &rampsum ;
%mend enrollment;

 

%enrollment(rampdata=0|1|2|2|4|4|5|6|8|8|13|10|10);













0
1
2
2
4
4
5
6
8
8
13
10
10
0 , 1 , 2 , 2 , 4 , 4 , 5 , 6 , 8 , 8 , 13 , 10 , 10




Ksharp

sas-innovate-white.png

Special offer for SAS Communities members

Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.

 

View the full agenda.

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
  • 5 replies
  • 22575 views
  • 6 likes
  • 6 in conversation