Why does Ods trace not work in SAS Macro? - macros

When I run the below code as a macro, I can not create the dataset zcorr (using ods output). What am I doing wrong?
When I run the same code not as a macro (ie for Nov 2014 and Dec 2014 separately) there is no problem.
I'd like to fix the macro because I have to run the code for many more months. Any help would be greatly appreciated,
Thanks!
%MACRO RunProgram(month, year);
data sourceh.trades2;
set sourceh.trades_&month.&year.;
if time<34200000 or time>57600000 then delete;
proc sort data=sourceh.trades2;
by symbol day month year int1;
run;
proc corr data=sourceh.trades2; by symbol day;
var zbuy zsell;
ods output pearsoncorr=sourceh.zcorr;
run;
%MEND ;
%RunProgram(Dec, 2014);
%RunProgram(Nov, 2014);

Your ODS OUTPUT statement should be within or before the proc. The ODS TRACE statement does not generate any tables/results so you can remove those statements.
You should also be careful with comments in a macro and use '%* comment;' rather than just an asterisk.

Related

SAS macros to save and list all macros in a session

I would like to save all the macros permanently defined as part of an exercise and list all the macros. I have 6 macros which I want to save and retrieve in this session:
%macro one(a,b,c)
%macro gchart(dseti,Weight,Gender)
%macro plot(dsetin,height,weight)
%macro one(a,b,c,strtpt,endpt)
%macro test
%macro name(dsetin,year,revenue)
%macro import_myfile(i=)
I have the code below and the error message follows it.
options mstored sasmstore=macross;
libname mjstore "C:\Users\komal\Desktop\Advanced SAS";
proc catalog cat=mjstore.macross;
contents;
title "Default Storage of SAS Macros";
quit
Error: Catalog "MJSTORE.MACROSS" not found
Please let me know your advice on how to solve it. Thank you for your time.
The default catalog is WORK.SASMACR
%macro one(a,b,c); %mend;
%macro gchart(dseti,Weight,Gender); %mend;
%macro plot(dsetin,height,weight); %mend;
%macro one(a,b,c,strtpt,endpt); %mend;
%macro test; %mend;
%macro name(dsetin,year,revenue); %mend;
%macro import_myfile(i=); %mend;
proc catalog cat=work.SASMACR;
contents;
title "Default Storage of SAS Macros";
quit;
The best way to find out which macros were defined during your program is to not use stored macro catalog options. Instead just let SAS default to storing them a WORK catalog. You can then use PROC CATALOG to see what macros have been compiled. Normally that will be WORK.SASMACR catalog, but if you are using alternative ways of running SAS (Enterprise Guide, SAS/Studio, stored process servers etc) it might be WORK.SASMACR1 catalog instead.
proc print data= sashelp.vcatalg width=min;
where libname='WORK' and memname='SASMACR'
and memtype='CATALOG' and objtype='MACRO'
;
var objname modified objdesc ;
run;
If you are using autocall macros newer versions of SAS will store the filename in the OBJDESC field in the metadata. Otherwise here is a link to a macro that will generate a list of the compiled macros and try to match them to a corresponding source file from the autocall library or other directories you might provide it. https://github.com/sasutils/macros/blob/master/maclist.sas

Passing SAS dataset column as macro parameter

I have a SAS dataset with values
yyyymm
201605
201606
201607
201608
201609
I am trying to find a way to pass these values one at a time to macro such that
do while dataset still has value
%macro passdata(yyyymm);
end
How can I do this in SAS. Can someone please help with a sample/code snippet.
As mentioned by the prior comment, a way to pass parameters is through call execute routine. Note that this must be done in datastep environment. The lines are read from the set you input.
You can input multiple variables. Just add more variables in '||' separators. Note that the variables may have a lot of whitespaces in them. (==Do comparisons with care.)
Here is a small sample code. Tested.
data start_data;
input date_var ;
datalines;
201605
201606
201607
201608
201609
;
run;
%macro Do_stuff(input_var);
%put 'Line generates value ' &input_var;
%mend do_stuff;
data _null_;
set start_data;
call execute('%do_stuff('||date_var||')' );
run;
Try this example and try modifying to meet your needs... From the "source" dataset we can use call symput() to assign a macro token to each observation (differentiated by the SAS automatic dataset variable n so My_token1, My_token2, etc.) Once you have a set of macro variables defined, just loop through them! This program will print all the individual records from source to the SAS log:
data source;
do var=1000 to 1010;
output;
end;
run;
data _null_;
set source;
call symput(compress("My_token"||_n_),var);
run;
%put &my_token1 &my_token4;
%Macro neat;
%do this=1 %to 11;
*Check the log.;
%put &&My_token&this;
%end;
%mend;
%neat;

SAS Macro operations

I need to create sum of 4 variables multiple times each time with new set of variables. For e.g. A1=sum(a1,a2,a3,a4),B1=sum(b1,b2,b3,b4) & so on. So , I am trying to write a macro that will help me do it easily. Following is the code:
%macro SUM2(VAR1,var2,var3,VAR4);
data Subs_60_new;
set Subs_60;
substr(&var1,1,10)=sum(&var1,&var2,&var3,&var4);
run;
%mend sum2;
options mprint mlogic;sum2(ADDITIONAL_INFO_Q1,ADDITIONAL_INFO_Q2,ADDITIONAL_INFO_Q3,ADDITIONAL_INFO_Q4);
I am using SAS EG for the same & when I run the macro I get the following note:
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
& obviously when I try to execute the macro it throws an error.
Can some one help me out?
when calling a macro, you need to precede the macro name with a % symbol, eg as follows:
%macro SUM2(VAR1,var2,var3,VAR4);
data Subs_60_new;
set Subs_60;
substr(&var1,1,10)=sum(&var1,&var2,&var3,&var4);
run;
%mend sum2;
options mprint mlogic;
%sum2(ADDITIONAL_INFO_Q1,ADDITIONAL_INFO_Q2,ADDITIONAL_INFO_Q3,ADDITIONAL_INFO_Q4);
The NOTE is harmless. It is ERRORs and WARNINGs in general that you should be concerned with.
I'd point out that this will probably still throw an error, as you are trying to replace characters in a variable (&var1) that appears as though it should contain a numeric field (being part of a sum function). Given your description of what you are trying to achieve, I'd suggest adding the new variable name as another macro parameter - as follows:
%macro SUM2(VAR1,var2,var3,VAR4,varname);
data Subs_60_new;
set Subs_60;
&varname=sum(&var1,&var2,&var3,&var4);
run;
%mend sum2;
options mprint mlogic;
%sum2(ADDITIONAL_INFO_Q1,ADDITIONAL_INFO_Q2
,ADDITIONAL_INFO_Q3,ADDITIONAL_INFO_Q4
,MyNewVariable);

resolve macro variables for saving/naming a dataset in SAS

I have problem saving a dataset using macro variables to a desired directory.
Basically, I want to save the dataset "_est" to library "sret" according to the values of &var and &age. I wrote the following code:
%let var=k;
%let age=2;
...
...
data sret.est_&var&age._b3;
set _est;
run;
What I want is a dataset named as "est_k2_b3.sas7bdat" in "sret". But what the code gives me is a dataset "est_k2.sas7bdat" saved in the folder I want and another dataset "_b3" in the working library. Both datasets are identical. I'm quite puzzled how to solve this.
As itzy pointed out you have a space after "2" that splits your dataset name in two.
I can replicate the issue only defining the macro variable age with a call symput:
data _null_;
age='2 ';
call symput('age',age);
run;
If this is the case you can solve it by removing the space in the data step with a strip(), using a call symputx() (to be used with numbers) or re-declaring your variable after the data step with a %let, that automatically removes spaces:
%let age= &age.;
Had a very similar problem. Somehow a space is added until you use strip(). Here's the example below.
data test;
input numdays;
datalines;
31
;
%macro monthly(months);
%let count=%sysfunc(countw(&months.));
%do i=1 %to &count.;
%let value=%qscan(&months.,&i,%str(,));
%let month=%sysfunc(strip(&value.));
%put &value.;
%put &month.;
data value_&value.;
set test;
run;
data month_&month.;
set test;
run;
%end;
%mend;
%monthly(%str(oct,jan));

SAS Macro to export to csv

I'm trying to use code from here and not sure how to adapt it correctly.
https://communities.sas.com/thread/33654?start=0&tstart=0
I'm trying to export 51 SAS datasets to CSV files so that I can import them into R. Here's the macro code I have (that's not working):
libname g 'C:\mylibrary';
%macro export(libname, numvars= &numvars.);
%do i= 1 %to &numvars.;
proc export data=&libname.StateZip&i
DBMS=CSV REPLACE
outfile= "&libname.StateZip&i.csv";
run;
%end;
%mend;
%export(&g, numvars= 51);
Here is the error message I'm getting:
NOTE: Writing TAGSETS.SASREPORT12(EGSR) Body file: EGSR
13
14 GOPTIONS ACCESSIBLE;
ERROR: Invalid macro name (. It should be a valid SAS identifier no longer than 32 characters.
ERROR: A dummy macro will be compiled.
15 %macro export(libname, numvars= &numvars.);
16 %do i= 1 %to &numvars.;
17 proc export data=&libname.StateZip&i
18 DBMS=CSV REPLACE
19 outfile= '&libname.StateZip&i.csv';
20 run;
21 %end;
22 %mend;
23
24 %export(g, numvars= 51);
24 +(libname, numvars= &numvars.);
_
10
ERROR 10-205: Expecting the name of the procedure to be executed.
24 +(libname, numvars= &numvars.);
_
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
2 The SAS System 11:38 Wednesday, September 5, 2012
180: LINE and COLUMN cannot be determined.
NOTE: NOSPOOL is on. Rerunning with OPTION SPOOL may allow recovery of the LINE and COLUMN where the
error has occurred.
Any help you can provide would be appreciated.
You have a recursive reference to &numvars, which is a problem in and of itself, but not a critical one - just means that the default value will be null, not the value you intend it to be. Otherwise your code works fine for me. I would guess you have something else going wrong just before the %macro definition; the error you post makes it look like you have a token that's incorrectly resolving, so instead of
%macro export(
you have
%macro (
Anyway, this is what works for me:
%let g=c:\temp;
libname g "&g.";
%macro export(libname, numvars=);
%do i= 1 %to &numvars.;
proc export data=sashelp.class
DBMS=CSV REPLACE
outfile= "&g.\StateZip&i.csv";
run;
%end;
%mend;
%export(&g, numvars= 51);
The things I changed:
* You need a %let g= to go along with your libname. You don't have that defined, but presumably you do elsewhere.
* Sashelp.class instead of using your library as I don't have those datasets.
The better answer, though, is probably to do it like this, using FILEVAR option and writing them out yourself. Even if you have a ton of variables, you can either programmatically determine the put statement, or just do one proc export and copy from the log. This avoids all of the macro stuff, and avoids you having to make 51 different datasets. Just make one, with an indicator variable. Pretty much no matter what you're doing, this will be faster (using BY group processing with PROCs, etc.) and less error-prone than having a bunch of different datasets and making up for it with macros.
data have_51;
set sashelp.class;
do _n = 1 to 51;
output;
end;
run;
*I assume you have have_51 already;
data want;
set have_51;
filename=cats("&g.\StateZip",_n,".csv");
run;
proc sort data=want;
by filename;
run;
data _null_;
set want;
file a filevar=filename dlm=',' lrecl=500;
put
name $
age
height
weight
;
run;