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

Hi,

I would like to know how to create date constants in the format  '01Jan2000'd whcih I can then pass to macros for evaluation. As an example the following code

%let t1 = '01jan2000'd;

%let t2 = '31dec2000'd;

%mymacro(&t1);

%mymacro(&t2);

proc append base = want_1 data = want_2;

run;

%mymacro(&t);

data want;

     set have(where=( targetdate = &t));

     /* do something */

run;

%mend mymacro;

This works perfectly fine for literal date constants in the format specified. EventualIy I want to append data sets for a large number of days and thus repeating these steps must be done in a loop.

However, I cannot figure out how to assign a new value for &t.

I tried the following :

data _null_;
nDays = intck( 'day', &t_s, &t_e );
date_zero = &t_s;

do i=1 to nDays;
  date = intnx('day',date_zero,1);
  startdate = cats("'",put(date,date9.),"'","d");
  put startdate;
  date_zero = date;
end;
run;

This puts the startdate in the correct format into the log, i.e., '02Jan2000'd , but I cannot then put startdate as input argument to %mymacro:

%let t_new = startdate;

%mymacro(&t_new);

This will give an error because startdate will be resolved as startdate not '02Jan2000'd.

In other words, how can I pass the value of startdate to the macrovariable &t ?

Thanks for helping out!

-Alexander

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Why not just generate the dates as the internal values.  You can always apply a format later to convert the date to another format for use in titles or table names.

For example to call your trivial example macro you can just pass in the number of days, no need to format it as a date string.

data _null_;

   do dt = '01jan2000'd to '31dec2000'd;

      call execute(cats('%mymacro(',dt,')'));

   end;

run;


Now if your macro needed to use the value of DT to build a string then it can apply the format.

%macro mymacro(dt);

....

%let fname=Transactions_%sysfunc(put(&dt,yymmdd10.)).txt ;

...

%mend ;

View solution in original post

8 REPLIES 8
PaigeMiller
Diamond | Level 26

You want a macro %Do loop (instead of a datastep do loop) which loops through all dates, creates a macro variable called &startdate; and then once startdate is computed, calls %mymacro(&startdate)

--
Paige Miller
Kurt_Bremser
Super User

You are confusing data step variables (startdate) and macro variables (%let t_new=startdate).

You actually assign the _value_ startdate to macro variable t_new. %put &t_new would then render the string startdate, instead of the value of the variable startdate.

Once you have created startdate in the data step, use call symput('t_new',startdate); to assign the value of startdate to the macro variable t_new. Be aware that only the last assignment done in the last iteration of the do loop will have effect.

To execute the macro repeatedly, use call execute inside the data step to call the macro with the correct values. The data step will "feed" your macro calls to the SAS interpreter input queue, so they will be executed in order after the data step has finished.

PaigeMiller
Diamond | Level 26

Since you don't really specify what "do something" means, you might be able to avoid all of this looping and macro variables and simply use a BY statement in a PROC

--
Paige Miller
blablabla
Calcite | Level 5

First off, thanks for replying. Although I will only be able to check your suggestions tomorrow, I can provide a couple of more details regarding what happens in the data step.

I basically construct a table of aggregated data for a given day. As the source records are saved based on transaction start and end dates, I cannot easily get a per day aggregate to begin with. Doing so would at some point likely involve the same kind of issues I am having now. A simple BY grouping certainly does not solve (unfortunately). Conceptually the problem is extremely straightforward.

1) Get a table for each day in a range

2) Concatenate the data sets.

Also I am quite new to SAS so my solutions are probably not yet very efficient and I just started looking into macro variables (frustrating, as I could solve this easily in another environment, alas my employer switched to SAS...). As soon as I can give it a try, I'll let you know.

Thanks again!

data_null__
Jade | Level 19

Can you define the process using the "have/need" scenario?  This is where you show an example of the data you have and an example of the data(s) you want and whatever explanation is needed to understand how to get from a to b.

PaigeMiller
Diamond | Level 26

I basically construct a table of aggregated data for a given day. As the source records are saved based on transaction start and end dates, I cannot easily get a per day aggregate to begin with. Doing so would at some point likely involve the same kind of issues I am having now. A simple BY grouping certainly does not solve (unfortunately). Conceptually the problem is extremely straightforward.

1) Get a table for each day in a range

2) Concatenate the data sets.

The paragraph you wrote, which contains the statement "A simple BY Grouping does not solve", seems to be contradicted by the two steps you are describing below, where it seems that a BY statement would handle whatever analysis is needed.

However, the paragraph I quoted from you is extremely vague (what issues? why can't you easily get a per day aggregate?), and I agree with the others, more detail is needed.

Or, in the absence of such detail, the macro solution would certainly work.

--
Paige Miller
Tom
Super User Tom
Super User

Why not just generate the dates as the internal values.  You can always apply a format later to convert the date to another format for use in titles or table names.

For example to call your trivial example macro you can just pass in the number of days, no need to format it as a date string.

data _null_;

   do dt = '01jan2000'd to '31dec2000'd;

      call execute(cats('%mymacro(',dt,')'));

   end;

run;


Now if your macro needed to use the value of DT to build a string then it can apply the format.

%macro mymacro(dt);

....

%let fname=Transactions_%sysfunc(put(&dt,yymmdd10.)).txt ;

...

%mend ;

blablabla
Calcite | Level 5

Hi Tom,

Your solution worked like a charm! Took me a while to understand things, but that's part of the learning experience. Thank you all so much!

-Alexander

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 8 replies
  • 2605 views
  • 6 likes
  • 5 in conversation