DATA Step, Macro, Functions and more

Sum Values Stored in Macro Variables

Accepted Solution Solved
Reply
Regular Contributor
Posts: 220
Accepted Solution

Sum Values Stored in Macro Variables

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);


Accepted Solutions
Solution
‎04-26-2012 05:03 PM
Super User
Posts: 5,096

Re: Sum Values Stored in Macro Variables

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


All Replies
Solution
‎04-26-2012 05:03 PM
Super User
Posts: 5,096

Re: Sum Values Stored in Macro Variables

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.

Respected Advisor
Posts: 3,902

Re: Sum Values Stored in Macro Variables

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;

Respected Advisor
Posts: 3,777

Re: Sum Values Stored in Macro Variables

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

Super User
Super User
Posts: 6,502

Re: Sum Values Stored in Macro Variables

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()=.

Super User
Posts: 9,691

Re: Sum Values Stored in Macro Variables

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

🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

Discussion stats
  • 5 replies
  • 8318 views
  • 6 likes
  • 6 in conversation