- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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()=.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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