BookmarkSubscribeRSS Feed
bhca60
Quartz | Level 8

I have an admit date variable (admitdt) that needs to be brought in to define a few month and week variables but these have to be done in a separate step.  Is there a way to create a macro in one data step that can be used in several? Do I just do a LET statement  The admitdt format is mmddyy10.

12 REPLIES 12
PaigeMiller
Diamond | Level 26

Example:

 

data _null_;
    set dataset1;
    call symputx('admitdt',admitdt);
run;

data use_macro_var;
    set dataset2;
    if date<&admitdt then do ... ;
    end;
run;

 

You have provided such a vague description of the problem that all I can do is provide a vague solution, above. Please be more specific and give actual examples of how you would want to use the macro variable.

--
Paige Miller
bhca60
Quartz | Level 8

I was just about to edit my message but here is an example:

 

if year="2024" then do;
wk1=(compress('wk'||put(week(AdmitDt) + 1,z2.)));
wk2=compress(substr(year,3,2)||'_'||wk1);
end;

I want to be able to call the macro where it says AdmitDt in the above. 

PaigeMiller
Diamond | Level 26

@bhca60 wrote:

I was just about to edit my message but here is an example:

 

if year="2024" then do;
wk1=(compress('wk'||put(week(AdmitDt) + 1,z2.)));
wk2=compress(substr(year,3,2)||'_'||wk1);
end;

I want to be able to call the macro where it says AdmitDt in the above. 


If I am understanding you properly, you could use &admitdt in place of AdmitDt. But I still get the feeling there are things I don't understand about your request, and if this suggestion doesn't work, please explain the whole thing in detail, instead of details for part of the problem.

 

Let's also see if we can get the terminology correct. We are not talking about macros. We are talking about macro variables, which are different than macros.

--
Paige Miller
bhca60
Quartz | Level 8

What you provided looks like it kinda worked but for some reason it's just bringing in the same dates for the columns that are using it (for ex, for wbeg: 26JAN20 filled the column ; wend: 01FEB20 filled the column).   Basically, in the end, I am trying to join a summarized data set to a detailed data set. I can't bring in AdmitDt as a field because it wont match onto the summarized data set.  In the end, I will need variables that are using AdmitDt in their calculation (such as mend, wk1,wk2..) and using "&admitdt" instead of bringing the AdmitDt into the data is the only solution I can think of.  Here is my code where the macro variable is being used:

data table2;
set table1;

format wbeg wend mbeg mend date8.;
AdmitDt = admitdt_1;
format AdmitDt mmddyy10.;

/* created macro to use in other steps without bringing in admitdt downstream*/
call symputx('admitdt',admitdt);

if &admitdt. >= '03sep2017'd and &admitdt. <= intnx('week',today(),-1,'e'); 

*Determine if a week shared between two months belongs to present month or the previous one;
mbeg= intnx('month',&admitdt.,0,'b');
mend= intnx('month',&admitdt.,0,'e');

wbeg = intnx('week',&admitdt.,0,'b');
wend = intnx('week',&admitdt.,0,'e');
madm = month(&admitdt.);
mwbeg = month(wbeg);
mwend = month(wend);
if month(wbeg) = month(wend) then do;
                                  month3 = put(year(&admitdt.),4.)||put(month(&admitdt.),z2.);
                                  end;
else if mend - wbeg < 7 then do;
                                if mend - wbeg < 3 then do;
							                            if month(&admitdt.) = 12 then month3 = put(year(&admitdt.)+1,4.)||"01";
													    else month3 = put(year(&admitdt.),4.)||put(month(&admitdt.)+1,z2.);
													    end;
							    else month3 = put(year(&admitdt.),4.)||put(month(&admitdt.),z2.);
							    end;
else if wend - mbeg < 7 then do;
                             if wend - mbeg < 3 then do;
                                                     if month(&admitdt.) = 1 then month3 = put(year(&admitdt.) - 1,4.) || "12";
                                                        else month3 = put(year(&admitdt.),4.)||put(month(&admitdt.)-1,z2.);
													 end;
							 else month3 = put(year(&admitdt.),4.)||put(month(&admitdt.),z2.);
							 end;


 

Quentin
Super User

Is your real code like you showed it, with all of the code in one DATA step? 

 

If that's the case, the approach won't work, because you can't use CALL SYMPUTX to create a macro variable and then use the macro variable in the same DATA step.  The timing doesn't work out.

 

But if it's all in one step, then you shouldn't need a macro variable at all.

 

Also, it's a bad idea to write a DATA step that over-writes the data  set it reads in, i.e.:

data table1;
set table1;

Every time the step runs, it over writes the input data.  When something goes wrong, and you need to de-bug it, you can't, because you don't have the input data anymore.  It's better to write a new data set with each DATA step, e.g.:

data table1b;
set table1;
The Boston Area SAS Users Group is hosting free webinars!
Next up: Joe Madden & Joseph Henry present Putting Power into the Hands of the Programmer with SAS Viya Workbench on Wednesday Nov 6.
Register now at https://www.basug.org/events.
bhca60
Quartz | Level 8

Ok so in Paige's example he creates a data_null to do the call symputx.  I will try that and see if that works.

bhca60
Quartz | Level 8

Ok I tried it and it still filled columns with the same week numbers and dates. This is what I did:

data _null_;
set table4;
format AdmitDt mmddyy10.;
call symputx('admitdt',admitdt);
run;

%put &admitdt.;
Patrick
Opal | Level 21

@bhca60 Looking at the code you shared I believe you are overcomplicating things. I'm even not sure that you need a macro variable at all.

Why don't you explain us what you've got and what you're trying to achieve. Ideally share some sample data with us and show us the desired outcome.

 

Below some sample code that demonstrates how you could figure out if the days of a week (starting on Sundays) span over two months.

data demo;
  length week_num 8;
  format week_begin_dt dt week_end_dt weekdatx.;
  do dt='01jan2024'd to '31dec2024'd;
    week_num=week(dt);
    week_begin_dt =intnx('week',dt,0,'b');
    week_end_dt   =intnx('week',dt,0,'e');
    week_two_month_flg        =intck('month',intnx('week',dt,0,'b'),intnx('week',dt,0,'e'));
    weekday_in_diff_month_flg =intck('month',intnx('week',dt,0,'b'),dt);
    output;
  end;
run;

proc print data=demo;
  where week_two_month_flg = 1;
run;

Patrick_0-1715649632587.png

If you don't want to use the defaults then you also need to tell us when for you a new year and a new week starts.

 

bhca60
Quartz | Level 8

 

This is what I wrote up top: 

Basically, in the end, I am trying to join a summarized data set to a detailed data set. I can't bring in AdmitDt as a field because it wont match onto the summarized data set.  In the end, I will need variables that are using AdmitDt in their calculation (such as mend, wk1,wk2..) and using "&admitdt" instead of bringing the AdmitDt into the data is the only solution I can think of.  I think doing a call symputx is the right track for what I'm looking to do.  I want to call admitdt throughout the program so as to not have to include admitdt in the data steps.

Patrick
Opal | Level 21

...and using "&admitdt" instead of bringing the AdmitDt into the data is the only solution I can think of.

Which is why I proposed that you share some representative sample data, show the desired result based on this sample data and explain the logic to get from have to want. Someone else can eventually think of a different solution.

 

If using a SAS macro variable in SAS data step code the macro variable will resolve before the data step gets compiled and executes. It's therefore on the data step level a constant value. 

 

The macro variable will only ever have a single value. In below based on what you've posted...

data table4;
  do AdmitDt='01jan2024'd to '31jan2024'd;
    output;
  end;
run;

data _null_;
  set table4;
  call symputx('admitdt',admitdt);
run;

%put AdminDT: %sysfunc(putn(&admitdt.,date9.));

 

...the value of macro variable &admitdt is the last value written to it (=last row from table4).

39         %put AdminDT: %sysfunc(putn(&admitdt.,date9.));
AdminDT: 31JAN2024

 

Below code leads to the exactly same outcome.

data _null_;
  set table4 end=last;
  if last then call symputx('admitdt',admitdt);
run;

 

PaigeMiller
Diamond | Level 26

@bhca60 wrote:

Ok I tried it and it still filled columns with the same week numbers and dates. This is what I did:


Describe the entire problem in detail. Do not make us guess, that doesn't work.

--
Paige Miller
TonyMayo
Calcite | Level 5
Maybe this will create a unique macro var containing your dates mmddyy10.

Proc Sql;
Select Distinct admiddt into :M_admitdt1-M_admitdt365 format = mmddyy10.
separated by ' '
From here;

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!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

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
  • 12 replies
  • 1496 views
  • 1 like
  • 5 in conversation