BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
DavidPhillips2
Rhodochrosite | Level 12
%let firstAcademicPeriod=201810;
%let academicPeriods = %str("%eval(&firstAcademicPeriod +100)");

I'm trying to use the eval function and return it with quotes around it.  It looks like %str and %eval do not play nice with each other.  Am I missing something here? 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Why would you want to macro quote a string like:

"201910"

Remove the %STR() macro function.

View solution in original post

10 REPLIES 10
PaigeMiller
Diamond | Level 26

Generally, it is a poor idea to have the values of macro variables enclosed in quotes or double-quotes. I'd recommend you not do that, and then there's no issue.

 

%let academicPeriods = %eval(&firstAcademicPeriod +100);

If you absolutely must have the result in double-quotes (why?), then its still relatively simple to do:

 

%let academicPeriods = "%eval(&firstAcademicPeriod +100)";

 

But really, don't put numbers such as 201910, which is the output of your calculation, in quotes.

 

Just to complete everything here, the problem is NOT %eval doesn't play well with %str. 



--
Paige Miller
ChanceTGardener
SAS Employee

Try the quote function instead:

 

%let firstAcademicPeriod=201810;
%let academicPeriods = %sysfunc(quote(%sysevalf(&firstAcademicPeriod +100)));
Tom
Super User Tom
Super User

Why would you want to macro quote a string like:

"201910"

Remove the %STR() macro function.

DavidPhillips2
Rhodochrosite | Level 12

I'm creating dynamic headers for a 500 page SAS output to PDF report.  The macro is used to keep the amount of repetitive code down.

DavidPhillips2
Rhodochrosite | Level 12
/*This works*/
%let defineAnalysis1 = %str (
define _2017_18 / analysis sum '2017-18';
define _2018_19 / analysis sum '2018-19';
define _2019_20 / analysis sum '2019-20';
define _2020_21 / analysis sum '2020-21';
define _2021_22 / analysis sum '2021-22';
);

%let fAcadP=201810;
%let fAcadYS=2017;
%let fAcadYE=18;

/*earlier I used %str to execute the block as a set.  Is there something similar I can use?*/
%let defineAnalysis1 = 
define _&fAcadYS._&fAcadYE. / analysis sum "_&fAcadYS.-&fAcadYE.";
define _%eval(&fAcadYS. +1)_%eval(&fAcadYE.+1) / analysis sum "_%eval(&fAcadYS. +1)_%eval(&fAcadYE.+1)";
define _%eval(&fAcadYS. +2)_%eval(&fAcadYE.+2) / analysis sum "_%eval(&fAcadYS. +2)_%eval(&fAcadYE.+2)";
define _%eval(&fAcadYS. +3)_%eval(&fAcadYE.+3) / analysis sum "_%eval(&fAcadYS. +3)_%eval(&fAcadYE.+3)";
define _%eval(&fAcadYS. +4)_%eval(&fAcadYE.+4) / analysis sum "_%eval(&fAcadYS. +4)_%eval(&fAcadYE.+4)";

Tom
Super User Tom
Super User

Why not just put the %str() (or perhaps %nrstr() instead) around the semi-colons since those are the characters you actual need to "hide" to let the %LET work.

%let defineAnalysis1 = 
define _&fAcadYS._&fAcadYE. / analysis sum "_&fAcadYS.-&fAcadYE." %str(;)
define _%eval(&fAcadYS. +1)_%eval(&fAcadYE.+1) / analysis sum "_%eval(&fAcadYS. +1)_%eval(&fAcadYE.+1)" %str(;)
define _%eval(&fAcadYS. +2)_%eval(&fAcadYE.+2) / analysis sum "_%eval(&fAcadYS. +2)_%eval(&fAcadYE.+2)" %str(;)
define _%eval(&fAcadYS. +3)_%eval(&fAcadYE.+3) / analysis sum "_%eval(&fAcadYS. +3)_%eval(&fAcadYE.+3)" %str(;)
define _%eval(&fAcadYS. +4)_%eval(&fAcadYE.+4) / analysis sum "_%eval(&fAcadYS. +4)_%eval(&fAcadYE.+4)" %str(;)
;
DavidPhillips2
Rhodochrosite | Level 12

Placing the %str only on the; worked.

PaigeMiller
Diamond | Level 26

I'm sure all this could have been done using custom formats and PROC REPORT, rather than variables with calendar information in the variable name and macro variables and arithmetic with the macro variables. I don't have time right now to write out the code, but I think macro variables are completely unnecessary here, and makes the whole thing unnecessarily complicated..

--
Paige Miller
ballardw
Super User

Since there is a lot of DEFINE code going on, one has to assume this is Proc Report code.

Here may be a reason why all the code spent in generating variable names with data in them like _2018_19 was quite possibly unneeded and can get similar output.

The data set cntlyr makes a format for a limited number of school years, start with a lower value, like 1900 and go as large as you want up to 9998. When we get past 4 digit years something else would be needed.

Cntlyr is used to create a custom format to display single values of year such as 2018 as 2018-19.

Then make small data set with random years and a variable to sum (or other summary) and some proc report code to make the Years as column headings with the summarized value under.

This would expect to have variable in your basic data with an appropriate calendar year numeric variable. Simple change if your "year" is character to make the start value and format type character.

data cntlyr;
fmtname='SchoolYr';
type='N';
do start=2000 to 2050;
   label= catx('-',start,put(mod(start,100) +1,z2.));
   output;
end;
run;

proc format cntlin=cntlyr;
run;

/* create a data set with random years and a variable to 
summarize
*/

data example;
   do i=1 to 100;
      year= 2000+ rand('integer',21);
      value= rand('integer',25);
      output;
   end;
run;

proc report data=example;
   column  year, value;
   define year/across format=schoolyr.;
   define value/analysis sum ' ';
run;

 

 

PaigeMiller
Diamond | Level 26

Yes, I agree @ballardw, no macros needed here.

--
Paige Miller

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 10 replies
  • 2202 views
  • 4 likes
  • 5 in conversation