Hi I am trying to import data (successfully) from a folder that is a date so the file path reads /year/month/date (*today's date)
I am then tweaking some of the data (again successfully). Once that is done I want to export it to a folder that is 29 days forward from the folder I took it from.
Here is my current macro:
%LET TODAY = %SYSFUNC(TODAY());
%PUT &TODAY;
%LET TODAYA = %SYSFUNC(PUTN(&TODAY,DDMMYYn8.));
%PUT &TODAYA;
%LET TWENTYNINE = %SYSFUNC(PUTN(&TODAY.+29,DDMMYYn8.));
%PUT &TWENTYNINE;
%LET T_DATE = %SYSFUNC(PUTN(&TODAY,DDMMYYn8..));
%LET T_YEAR = %SYSFUNC(YEAR(&TODAY));
%LET T_MONTH = %SYSFUNC(MONTH(&TODAY));
%LET P_DATE = %SYSFUNC(PUTN(&TWENTYNINE,DDMMYYn8..));
**%PUT &P_DATE;
%LET P_YEAR = %SYSFUNC(YEAR(&P_DATE));
%LET P_MONTH = %SYSFUNC(MONTH(&P_DATE));**
The P_Date reveals the error:
ERROR: Argument 1 to function MONTH referenced by the %SYSFUNC or %QSYSFUNC macro function is not
a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC argument list. Execution
of %SYSCALL statement or %SYSFUNC or %QSYSFUNC function reference is terminated.
But I cant get my head around it any help would be massively appreciated.
Imbricating %sysfunc's is handy:
%LET P_YEAR = %SYSFUNC(YEAR(%SYSFUNC(TODAY())+29));
%LET P_MONTH = %SYSFUNC(MONTH(%SYSFUNC(TODAY())+29));
%PUT &P_YEAR &P_MONTH;
Results in:
2016 2
EDIT
(Try solving it by yourself first, but here's a full solution...)
data _null_;
target = today() + 29;
format target YYMMDDS10.;
put target=;
call symput("target", put(target, YYMMDDS10.));
run;
%put ⌖
2016/02/24
If you want to determine the source path to use for today's date then use the TODAY() function. You can apply the YYMMDDS format to have it displayed as YYYY/MM/DD.
%let frompath=%sysfunc(today(),yymmdds10);
If you want to calculate the target path from the source path then you can use the INPUTN() function to convert it back to a date, add 29 and use PUTN() function to convert it back to a string.
%let topath=%sysfunc(putn(29+%sysfunc(inputn(&frompath,yymmdd10)),yymmdds10));
Related
I'm trying to transfer code that pulls a survey sample every month into a cronjob, but the last step I'm having an issue with in automating the code is with the file name in the proc export step.
I have the following macro variables defined at the beginning of the code:
%let today = date();
%let month = month(today);
%let year = year(today);
After I pull the data from our database and filter appropriately, I have a code that outputs the files as a pipe delimited .txt file. This file format is important to preserve:
proc export data=mkt.project_×tamp._group
outfile="/filepath/project_&year.&month._group" dbms=dlm Replace;
delimiter='|';
run;
The file output name doesn't recognize the macro variables, however, so instead of getting the year and month, it just names them as "project_&year.&month._group".
Can anybody help with this?
Thanks!
Macro variables contain text.
You have set yours to text strings that look like SAS function calls. But then you did not use the strings to generate SAS code where such a function call would make sense. Instead you put the function call into the name of a file.
440 %let today = date();
441 %let month = month(today);
442 %let year = year(today);
443 %put "/filepath/project_&year.&month._group";
"/filepath/project_year(today)month(today)_group"
One way to execute SAS functions in macro code is to use the macro function %sysfunc(). If you want to generate the 6 digit string in they style YYYYMM you can use the YYMMN6. format. So you could generate your filename like this:
"/filepath/project_%sysfunc(date(),yymmn6.)_group"
Or your other macro variables like this:
%let today = %sysfunc(date());
%let month = %sysfunc(month(&today),z2.);
%let year = %sysfunc(year(&today));
I have 10 csv files that would like to do PROC IMPORT, one at each time, depending on the value user input. For example, user will input 201801 to run January 2018 csv file(PROC IMPORT).
For that case, i tried to use substring &period(which stores the yymmn6. value which user input) and then from there, put in proc import. My code as below:
%let period=201812;
%macro convertdate();
data convertdate;
year=substr("&period",1,4);
month=substr("&period",5,2);
if month='01' then newmonth='jan';
if month='02' then newmonth='feb';
if month='03' then newmonth='mac';
if month='04' then newmonth='apr';
if month='05' then newmonth='may';
if month='06' then newmonth='jun';
if month='07' then newmonth='jul';
if month='08' then newmonth='aug';
if month='09' then newmonth='sep';
if month='10' then newmonth='oct';
if month='11' then newmonth='nov';
if month='12' then newmonth='dec';
run;
/*Assign convertdate the only distinct record into macro, then set as the data step for proc import*/
%if month='01' %then %do;
%let newmonth=jan;
%end;
/*proc import and remaining transformation from existing script*/
proc import out=rmr_raw_source
file="/sasdata/source/user_files/re_&newmonth.2018.xlsx"
dbms=xlsx replace;
sheet="re_&newmonth.2018";
getnames=no;
dbsaslabel=none;
run;
%mend;
%convertdate;
However, it wont work. I am getting warning below:
WARNING: Apparent symbolic reference NEWMONTH not resolved.
Does anyone have better solution to it?
You can try something as follows:
%let period = '201801'; /*7*/
%global month;
data test123;
period = . /*1*/
full_date = cats(period,'01'); /*2*/
format converted_date DATE10.; /*3*/
converted_date = input(full_date, yymmdd8.); /*4*/
month = put(converted_date,monname3.); /*5*/
call symput('month',month); /*6*/
run;
Create a SAS variable out of Macro.
Set to first date of the given month.
Create a new var and set the date format.
convert the TEXT date to SAS date.
get the month name out of date created above.
create a macro variable named 'month' out of SAS variable month.
Make macro variable 'month' global.
You can now use month macro variable anywhere in the code.
I have understood, and seen in other programs, that the following syntax is true.
%let variable = 'something';
statement name "&variable\othertext"; // something\othertext
However, in the code I have written I get this error message: Apparent symbolic reference not resolved. for the line LIBNAME REMOTE
%let month = 'JUN';
%let year = '18';
%let zos = ***********
signon zos ********************;
libname name "*********************************";
rsubmit;
libname remote "AAAA.BBBB.&month&year.SASLIB" access = readonly;
proc download inlib=remote outlib=name;
run;
libname remote clear;
endrsubmit;
signoff;
What am I missing?
The MONTH and YEAR macro variables are being defined in your local session, yet you're trying to resolve them in a remote session.
Use %SYSRPUT and %SYSLPUT to assign macro variables between sessions.
/* Local to remote */
%LET MONTH = 12 ;
%LET YEAR = 2018 ;
%SYSLPUT MONTH = &MONTH ;
%SYSLPUT YEAR = &YEAR ;
rsubmit ;
%PUT &MONTH &YEAR ;
/* resolves 12 and 2018 respectively */
/* remote to local */
%SYSRPUT FOO = BAR ;
endrsubmit ;
%PUT &FOO ; /* resolves to BAR */
More context would help, but most likely you are not understanding the role that period plays in resolving macro variable (symbol) references. To allow you to place letters and digits next to macro variable references SAS needs a way to tell where the name of the macro ends and the plain text starts. Period is used for that.
So if you wanted to generate this string
"AAAA.BBBB.JAN18.SASLIB"
from month and year values. First make sure to set the macro variables to the text you actually want. Quotes are just text to the macro processor.
%let month=JAN ;
%let year= 18;
Then in when you replace the values with macro variable references you will need an extra period after &YEAR so that one actually is generated. You should probably just get in the habit of always adding the period when referencing a macro variable.
"AAAA.BBBB.&month.&year..SASLIB"
what is wrong in below code
%let a='2017-01-01';
%let b='2017-12-01';
%let days = %sysfunc(intck(month,"&a"d,"&b"d));
%put days;
Below is the error
ERROR: Argument 2 to function INTCK referenced by the %SYSFUNC or %QSYSFUNC macro function is not a number.
ERROR: Argument 3 to function INTCK referenced by the %SYSFUNC or %QSYSFUNC macro function is not a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC argument list. Execution of %SYSCALL statement or %SYSFUNC
or %QSYSFUNC function reference is terminated.
67 %put days;
days
Three problems:
Your dates are not SAS date literals. SAS date literals take the format of 'DDMMMYYYY'd or 'DDMMMYY'd For example, 01JAN2018'd, or 01JAN18'd.
You have put quotes around your macro variables that declare the dates, and put double-quotes around them a second time when calling intck.
An & needs to prefix days.
The below code addresses these problems:
%let a=01JAN2017;
%let b=01DEC2017;
%let months = %sysfunc(intck(month,"&a"d,"&b"d));
%put &months;
Because you are calculating the number of months between January 2017 and December 2017, I renamed your macro variable to months.
I guess you want to do this in explicit SQL pass through. for doing that you have to something like this and you can use Teradata specific functions.
/* define date as Teradata Understands*/
%let a= '2017-01-01';
%let b= '2017-12-01';
/* use either of solutions and I do not have Teradata handy, so I did
not explicitly checked this */
SELECT CAST(&b AS DATE) - CAST(&a AS DATE) MONTH(4);
select floor(MONTHS_BETWEEN(date &b - date &a));
I have a SAS statement.
%let data = SampleData_200001_201603;
The data name is changing every time I run the code. For example:
run in 201604 then name= SampleData_200001_201603;
run in 201605 then name= SampleData_200001_201604;
run in 201606 then name= SampleData_200001_201605;
How can I write %let data = ; to make it automatic? Thanks.
If you are using the current date then you can use the YYMMN6. format to get the date in that format.
%let data = SampleData_200001_%sysfunc(date(),yymmn6);
If you need the previous month then use INTNX() function.
%let data = SampleData_200001_%sysfunc(intnx(month,%sysfunc(date()),-1),yymmn6);
%let date = 201603;
%let data = SampleData_200001_&date.;
and loop through a list of dates
I had enough of multiple %sysfunc's to get what I wanted. I wrote a macro routine that allows assignation of dates to macro variables using the format we want. No twists and turns with %sysfunc.
The code is here. And it lets you do that: assign to a macro variable named "thisMonth" the value of today(), with format YYMMn6. :
%letdate(thisMonth, today(), fmt=YYMMn6.)
log says:
*** Variable macro thisMonth = 201604 ***
And then
%let myFile = someName_&thisMonth;
%put &myFile;
log says:
someName_201604
The macro is documented in French but it should be self-explanatory for the most part.
EDIT:
Note that you can use any function normally reserved to data steps as the second parameter:
%letdate(firstDayLastMonth, intnx("MONTH", today(), -1, "BEGIN"), date9.)
log says:
*** Variable macro firstDayLastMonth = 01MAR2016 ***