BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Pandu2
Obsidian | Level 7

Hi All, I created a looping macro and passing date variable as parameter to loop the process but the isn't taking those date values as-is instead. For instance,

06JUN2022 - Supposed to take but taking this value 22802. I need my macro loop to take the date values as-is.

%macro loop(date1=);
Code to work repeatedly
%mend loop;

Data _null_;
Set work.have;   * this input table has date values for date1 variable;
If _n_>=1 then call execute(%nrstr(%loop(
date1=' || strip(date1) ||'))');
run;

This is my loop code; 
Please help me on this, Thanks!.

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Change the macro to actually use the parameter value to generate the code.

Use the DATE9. format to convert the values of the variable DATE1 into the style you need to construct the variable name.

%macro loop(date1=);
%local date2;
%let date2=%sysfunc(putn("&date1"d-1,date9.));
data want;
  set xyz.abc_&date1; 
  pd = catx(" - ","price_&date2",of id count price_&date2);
run;
%mend loop;

data _null_;
  set work.have; 
  call execute('%nrstr(%loop)(date1=',put(date1,date9.),')'));
run;

 

Later you can work on changing how you create those datasets so that the DATE is not part of either the name of the dataset or the name of the variable.  You should keep the date values in a variable where they are easier to work with.

View solution in original post

14 REPLIES 14
PaigeMiller
Diamond | Level 26

SAS date values are the number of days since 01JAN1960, so 22802 is fine.

 

The comparison DATE1=22802 ought to work properly, testing to see if DATE1 is equal to 06JUN2022, if DATE1 is numeric (and if it is not numeric, it should be). No need to format macro variables to be human readable (such as 06JUN2022) for arithmetic or logical operations.

 

I think you have other syntax issues, such as having a loop in side of CALL EXECUTE, I have no idea what that is supposed to do, but I don't think it will work.

 

Please explain further what this code is trying to do, as it seems to me there are simpler ways of doing whatever you are trying to do. Please do not ignore this request.

--
Paige Miller
Pandu2
Obsidian | Level 7

Thanks for replying me, the code which I posted was working for my previous projects but when comes to this project the date1 value should as-is cuz under the macro loop code I've a bunch of tables which takes that date1 variable value as input cuz those tables has date embedded at the end. 

Patrick
Opal | Level 21

You don't show us enough to really know but... first issue: You have unbalanced quotation marks.

Patrick_0-1665578655786.png

Based on your code variable date1 in data set have is a character variable. I assume it's a string like 01jan2022?

 

Does below work for you?

data _null_;
  set work.have;   * this input table has date values for date1 variable;
  if _n_>=1 then call execute( cats('%loop(date1=',date1,')') );
run;

If date1 in your have dataset it a numerical variable with a SAS date value then you might need code similar to below:

data _null_;
  set work.have;   * this input table has date values for date1 variable;
  if _n_>=1 then call execute( cats('%loop(date1=',put(date1,date9.),')') );
run;

 

Quentin
Super User

Hi,

 

If your macro expects the text value 06JUN2022 you can use PUT to convert your numeric date to that value:

 

%macro loop(date1=);
%put >>&=date1<< ;
%mend loop;

Data _null_;
date1="06Jun2022"d ;
If _n_>=1 then call execute('%nrstr(%loop(date1=' || strip(date1) ||'))');
If _n_>=1 then call execute('%nrstr(%loop(date1=' || put(date1,date9.) ||'))');
run;

Without the PUT, SAS is doing an implicit numeric to character conversion for you, and converting the number 22802 to '22802'.  That creates the NOTE in your log, "NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).".  Many people think that NOTE should be considered an error.

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.
Pandu2
Obsidian | Level 7

Thanks for the code. My date1 variable in that table is of date type.  And the code inside the macro loop has some tables which has dates embedded in it and some columns as well. Lemme show you my code.

Data want;
Set xyz.abc_06jun2022;
array values id count price_05jun2022;
Pd= catx(" - ", vname(values(whichn(price_05jun2022, of values (*)))), price_05jun2022);
run;

Here the column name for price_05jun2022 keeps on changes on daily basis. For instance for today's date the column name will be price_110ct2022.

This is the code which should loop in that loop macro. When comes to your code it's working fine for the input table name of the above code but not working for the column name i.e price_date2.

Pandu2
Obsidian | Level 7

Please look at the newly added reply for Tom.  

Tom
Super User Tom
Super User

You are missing a quote.

You can use CATS() function to simplify the data step code.

You can limit the %NRSTR() macro quoting to just the macro name.

data _null_;
  set work.have; 
  call execute(cats('%nrstr(%loop)(date1=',date1,')'));
run;

If you need to values of DATE1 in some particular style then you can use PUT() to apply some date format to the values in DATE1.  For example you mentioned that you where appending the date value to then end of filenames. In that case you would want to use a format like YYMMDDN8. so that the names will sort in chronological order.

  call execute(cats('%nrstr(%loop)(date1=',put(date1,yymmddn8.),')'));
Pandu2
Obsidian | Level 7

I've added another parameter in this macro loop for the below code.

%macro loop(date1=, date2=);

Data want;
Set xyz.abc_06jun2022; ( date1 parameter goes to table name ) 
array values id count price_05jun2022; ( date2 parameter goes to column name)
Pd= catx(" - ", vname(values(whichn(price_05jun2022, of values (*)))), price_05jun2022);
run;

%mend loop;

 

Data _null_;

Set work.have; * this input table has date values for date1 variable;

If _n_>=1 then call execute(%nrstr(%loop(

date1=' || strip(date1) ||'))');

run;

Tom
Super User Tom
Super User

Change the macro to actually use the parameter value to generate the code.

Use the DATE9. format to convert the values of the variable DATE1 into the style you need to construct the variable name.

%macro loop(date1=);
%local date2;
%let date2=%sysfunc(putn("&date1"d-1,date9.));
data want;
  set xyz.abc_&date1; 
  pd = catx(" - ","price_&date2",of id count price_&date2);
run;
%mend loop;

data _null_;
  set work.have; 
  call execute('%nrstr(%loop)(date1=',put(date1,date9.),')'));
run;

 

Later you can work on changing how you create those datasets so that the DATE is not part of either the name of the dataset or the name of the variable.  You should keep the date values in a variable where they are easier to work with.

Pandu2
Obsidian | Level 7

Thanks for the code. The date1 & date2 variables has numerous records n the date2 value shouldn't be constant.

Tom
Super User Tom
Super User

@Pandu2 wrote:

Thanks for the code. The date1 & date2 variables has numerous records n the date2 value shouldn't be constant.


That is as clear as mud.

Assuming that you mean the dataset you are using to generate the macro calls has two variables you want to use to call the macro the adaptation of the code to generate the string to pass to CALL EXECUTE is trivial.  

Similarly the macro will need to be modified to accept both DATE1 and DATE2 as inputs instead of deriving DATE2 from DATE1.

 

Try it and see how it works.  If it does not work then post the code you tried and the SAS log with any errors that are generated. 

 

As always get a working version of the code you want the macro to generate before trying to convert the code into a macro.   For example the code you posted using the WHICHN() function made no sense.  You searched a series of variables for one with the value in the PRICE_&DATE2 variable,  but the only variable in the list that would have had values like that was the PRICE_&DATE2 variable itself. The others where ID values.

Pandu2
Obsidian | Level 7

Yeah, your assumption is so right.

Pandu2
Obsidian | Level 7

Thanks Tom, your code is working for me. 

Kurt_Bremser
Super User

This is useless:

If _n_>=1 then

If there is at least one observation in the dataset, this condition will always be true; if there are no observations in the dataset, this statement will never be reached.

 

You miss a single quote here before the %NRSTR:

call execute(%nrstr(%loop(date1=' || strip(date1) ||'))');

so the macro processor will resolve

%nrstr(%loop(date1=' || strip(date1) ||'))

once before the data step even runs, resulting in syntax errors.

The code should be

call execute('%nrstr(%loop(date1=' || strip(date1) ||'))');

Finally, it is always easier to use raw values as parameters, so your macro should accept the number of days, as you then do not need to wrap it in quotes followed by a d wherever you use it. See Maxim 28.

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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.

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
  • 14 replies
  • 1784 views
  • 1 like
  • 6 in conversation