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.
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));
Good afternoon,
I am decent with SAS but I've never written macros.
I have a DB where I need to break out in separate datasets ID's where the date in a field occurs. E.g. All ID's with a date in Jan 2018 would be one dataset, All ID's with a date in Feb 2018 would be another data set, so on and so forth. Field name is ZDate.
I found this which seems to do exactly what I want. However I think my date isn't in the correct format. The date I'm pulling is in a timestamp in snowflake and I'm converting it to a date with to_date. It's showing as formatted date (16FEB2020) in the original vintagedata data set but the subsequent data sets are completely blank.
%macro month;
%local mindate maxdate i date month ;
proc sql noprint;
select min(ZDate),max(ZDate)
into :mindate , :maxdate
from vintagedata
;
quit;
data
%do i=0 %to %sysfunc(intck(month,&mindate,&maxdate));
%let date=%sysfunc(intnx(month,&mindate,&i));
%let month=%sysfunc(putn(&date,monyy7.));
&month
%end;
;
set vintagedata;
%do i=0 %to %sysfunc(intck(month,&mindate,&maxdate));
%let date=%sysfunc(intnx(month,&mindate,&i));
%let month=%sysfunc(putn(&date,monyy7.));
if intnx('month',date,0)=&date then output &month ;
%end;
run;
%mend;
%month;
I am building code that imports a daily file of sales from last 30 days, then replaces last 30 days of records in a main table. I want to only replace the last 30 days if the imported daily file has enough records:
proc sql;
select min(sale_date) into :oldestSale from daily_sales;
quit;
Here's a logic that I want to build in SAS:
IF oldestSale < (today() - 30) THEN
PROC SQL to replace
ELSE
do nothing
END
What would be the best solution? This is trivial in Python which I'm translating this from, but I'm stuck on SAS syntax for doing anything similar...
The 'logic' is quite vague in specifics, but the gist seems to be
import daily sales
presume daily sales is complete and every daily sale is represented
if daily sales info starting date is more than 30 days ago
remove all sales from main table from starting date
append current daily sales
One approach would be to have a macro that peforms the conditional remove/append as a 'replace' action.
%macro process_daily_sales;
proc import … out=daily_sales;
run;
%local oldestSale;
%let oldestSale = %sysfunc(today()); %* sentinel value just in case;
proc sql;
select min(sale_date) into :oldestSale from daily_sales;
quit;
%local gap;
%let gap = %eval ( %sysfunc(today()) - &oldestSale );
%if &gap > 30 %then %do;
proc sql;
delete from main_sales where sales_date >= &oldestSale;
quit;
proc append base=main_sales data=daily_sales;
run;
%end;
%mend;
I need to export a data set from SAS to Excel 2013 as a .csv file. However, I need the file name to be dynamic. In this instance, I need it to appear as:
in_C000000_013117_65201.csv
where the string, "in_C000000_" will remain constant, the string "013117_" will be the current day's date, and the string "65201" will be the row count of the data set itself.
Any help that you can provide would be much appreciated!
Thanks!
Here's a modified macro I wrote in the past that does almost exactly what you're asking for. If you want to replace sysdate with a date in your desired format, that's easy to do as well:
%let path = [[desired destination]];
%macro exporter(dataset);
proc sql noprint;
select count(*) into: obs
from &dataset.;
quit;
data temp;
format date mmddyy6.;
date = today();
run;
proc sql noprint;
select date format mmddyy6. into: date_formatted
from temp;
quit;
proc export data = &dataset.
file = "&path.in_C000000_&date_formatted._%sysfunc(compress(&obs.)).csv"
dbms = csv replace;
run;
%mend exporter;
%exporter(your_dataset_here);
Produces datasets in the format: in_C000000_020117_50000.csv
I have a column with name total transaction. I want to add a date 4 days back from now in its name .
For example if today is 20161220 so I want my variable to be renamed as total_transaction_20161216.
Please suggest me a way out of my problem.
Just create a macro variable that stores the required date format and then use that in a rename statement within proc datasets.
%let datevar = %sysfunc(intnx(day,%sysfunc(today()),-4),yymmddn8.);
%put &=datevar.;
data have;
total_transaction=1;
run;
proc datasets lib=work nolist nodetails;
modify have;
rename total_transaction = total_transaction_&datevar.;
quit;