I have a problem with my macro. Try to create a table if the name exists.
%let tableA = Cars;
%let tableB =;
This works:
%macro CREATETABLE(name);
%if %symexist(name) = 1 %then %do;
proc sql;
Create table ....
But if the table name doesnt exists:
%else...( do nothing )
i want SAS to do nothing, but i didnt get it to work. Getting always SAS errors because the table name doenst exists.
%CREATETABLE(CARS)/%CREATETABLE(&tableA) - works, %symexist(chkTabelle) -> 1
%CREATETABEL(asfsf)/%CREATETABLE(&tableB) - error, %symexist(chkTabelle) -> 0
%symexist checks to see if a macro symbol exists. The macro symbol NAME always exists. It sounds like you want to check if a dataset exists. To do that, you use the EXIST() function.
From the docs:
http://support.sas.com/kb/24/670.html
%macro checkds(dsn);
%if %sysfunc(exist(&dsn)) %then %do;
proc print data = &dsn;
run;
%end;
%else %do;
data _null_;
file print;
put #3 #10 "Data set &dsn. does not exist";
run;
%end;
%mend checkds;
Related
If the dataset dataset_1&x._&y. exists, I want to get data from it, but if it doesn't exist i want to get data from dataset_2.
I have tried the following macro but it doesn't work:
%macro test(x,y);
%if %sysfunc(exist(dataset_1_&x._&y.)) %then %do;
data final_data;
set dataset_1_&x,_&y.;
run;
%end;
%else %do;
data final_data;
set dataset_2;
run;
%end;
%mend;
Try this - no need to define a macro:
%let exist=%sysfunc(exist(work.dataset_1&x._&y.));
%let inds=%sysfunc(ifc(&exist=1,work.dataset_1&x._&y.,work.dataset_2));
data work.final_data;
set &inds;
run;
If you did want a macro to see if a dataset (or view) exists, you could use this one: https://core.sasjs.io/mf__existds_8sas.html
I'm pretty new to doing macros on SAS so apologies in advance if my questions seems basic.
I'm looking to execute part of a macro if there are a minimum number of observations found in temporary work file.
If there are a minimum number of observations, the macro should execute a proc export of that temporary work file, otherwise it will just produce an error message on the log.
I'm not sure what I'm doing wrong, the temporary work file has more than 1 observation and I want the macro to run, however it produces the error message as if it has less than the minimum.
Below is the code that I've created so far - any help you have to offer will be greatly welcomed.
data original_data;
set data.dataset;
keep column1 column2 column3 ;
run;
%macro test_macro;
%let dsid=%sysfunc(open(work.original_data));
%let nobs=%sysfunc(attrn(&dsid,nobs));
%let dsid=%sysfunc(close(&dsid));
%if &nobs >1 %then %do;
%put ERROR: No observations counted;
%return
%end
%else %do;
proc export data=submissions
outfile='C:\Users\myusername\Desktop\test.csv'
DBMS=csv replace;
run;
%end;
%mend test_macro;
%test_macro
Missing semicolons on RETURN and END statements
Logic is reversed. You're putting the error message if you have more than one observation. Flip your code so that you export if you have more than one observation.
options mprint symbolgen;
%macro test_macro;
%let dsid=%sysfunc(open(work.original_data));
%let nobs=%sysfunc(attrn(&dsid, nobs));
%let dsid=%sysfunc(close(&dsid));
%put &nobs;
*if more than one observation;
%if &nobs > 1 %then
%do;
proc export data=sashelp.class outfile='/home/fkhurshed/test.csv' DBMS=csv
replace;
run;
%end;
%else
%do;
%put ERROR: No observations counted;
%return;
%end;
%mend test_macro;
%test_macro;
I am writing a SAS macro that takes two params, the first is the name of a dataset, the second param is a string that will actually determine one of the output columns:
%macro test(data, input_mth);
%if &comp_mth.=October %then %do;
cmp_basis=Last Fiscal End;
%end;
proc sql;
create table final as select &cmp_basis. as col1, data.col2 from data;
quit;
%mend;
%test(data, October);
basically, I pass in a dataset and if I pass the string 'October', then the output will show 'Last Fiscal End; as the first column. If I pass in January, it will show 'Calendar beginning' etc etc.
The %if block gives me error:
Statement is not valid or it is used out of proper order.
Just reading through your code in order let's identify some of the issues.
First your %IF statement is referencing a macro variable COMP_MTH that is not defined anywhere in your program. I assume you meant to refer to one of your input parameters instead.
%if &input_mth.=October %then %do;
Second you have data step statements inside your %DO/%END block but you never started a data step. I assume that you mean to create a macro variable there. So use a %let statement.
%let cmp_basis=Last Fiscal End;
But you also need to define that macro variable as local or else your macro will overwrite any macro variable with the same name in the calling program's environment.
You also need to make sure that your macro is generating valid SAS code. So in your SQL code you have
select &cmp_basis. as col1
But if we just replace the macro variable with the value you are assigning above we this gibberish statement:
select Last Fiscal End as col1
I assume you meant to create a character variable there, so add quotes so that you are generating a character constant.
select "&cmp_basis." as col1
You also have a logic problem. What value do you want for COL1 when it is not October? One way to deal with that is to set a default value to the macro variable before your logic. But perhaps you meant to use the input month? So perhaps you just need to add a %else clause?
You are also never using your other input parameter. Let's assume that you mean to pass in the name of the dataset that the SQL should query. So you want to use
from &data
But then your SQL table alias in DATA.col2 is never defined. So make sure to either assign an alias to your input table, or for this simple one table query just drop the alias when referencing the column name.
So we end up with something like this:
%macro test(data, input_mth);
%local cmp_basis;
%if &input_mth.=October %then %do;
%let cmp_basis=Last Fiscal End;
%end;
%else %let cmp_basis=&input_mth;
proc sql;
create table final as
select "&cmp_basis." as col1
, x.col2
from &data x
;
quit;
%mend test;
Of for such simple logic we could dispense with the extra macro variable and just use the macro logic to conditionally generate the constant value that you want to use as the value of COL1.
%macro test(data, input_mth);
proc sql;
create table final as
select
%if &input_mth.=October %then "Last Fiscal End";
%else "&input_mth";
as col1
, x.col2
from &data x
;
quit;
%mend test;
I figure it out, correct syntax is:
%macro test(data, input_mth);
%if &comp_mth.=prv %then %do;
%let cmp_basis=Last Fiscal End;
%end;
proc sql;
create table final as select "&cmp_basis." as col1, data.col2 from data;
quit;
%mend;
%test(data, October);
Your code have numerous errors of statement concept. If you more give me more details about you need, I help you better.
But I try understanded you problem, and I sugested two soluctions.
option I
%macro test(data, input_mth);
%if &comp_mth. = "October" %then %do;
cmp_basis = Last /*Fiscal End*/;
%end;
proc sql;
create table final as select
"&cmp_basis." as col1,
col2
from &data.;
quit;
%mend;
%test(data, October);
option II
%macro test(data, input_mth);
%if &comp_mth.=prv %then %do;
%let cmp_basis = Last Fiscal End; /* this is a Vector that contains string at Last, Fiscal and End*/
%end;
proc sql;
create table final as select /* You create a table call final */
"&cmp_basis." as col1, /* column call October */
/* data.col2 */ /* this no have sense - what is this ? */
col2 /*Correct way to call col2 if it exists on data*/
from &data.; /* Your data set, you call in macro */
quit;
%mend;
%test(data, October);
data classivar_1;
set classvar;
AnaClassVar=scan(scan(F2,1," "),2,".");
run;
proc sql;
select AnaClassVar into : MacClassVar separated by "#" from classivar_1 ;
select count(*) into: Count_classvar from classivar_1;
quit;
%put &MacClassVar.;
%put &Count_classvar.;
ods output variables=adsl_var;
proc contents data=ev.adsl;
run;
proc sql;
select variable into : AllVar separated by "#"
from adsl_var;
select count(*) into : Count_Allvar from adsl_var;
quit;
%put &Allvar.;
%put &Count_Allvar.;
**** set up Macro ClassAna to analyze the classified varialbes;
%macro ClassAna(datasets= );
%do i= 1 %to &Count_classvar.;
%do count=1 %to &Count_Allvar;
%if %sysfunc(find(%scan(&MacClassVar,&i,#),%scan(&AllVar,&count,#)))
%then %do;
%let Class_var&i.=%scan(&AllVar,&count,#);
%end;
%end;
%put &&Class_var&i..;
%end;
%Mend;
%ClassAna(datasets=sashelp.class)
When I submit the programme , the macro variable Class_var6 cannot be resolved.
But other macro variables can be resolved correctly.
The logs are in the picture.enter image description here
enter image description here
In %ClassAna you are conditionally creating the macro vars based on:
%if %sysfunc(find(%scan(&MacClassVar,&i,#),%scan(&AllVar,&count,#)))
%then %do;
That FIND is case sensitive by default. I think it will work if you make it case insensitive by adding the optional i parameter to FIND. Something like:
%if %sysfunc(find(%scan(&MacClassVar,&i,#),%scan(&AllVar,&count,#),i))
%then %do;
Or you could %upcase both variable lists and leave the FIND as is.
I have a dataset naming error_table as follows. All the variables are character
Errorno Error Resolution
001 login check
002 datacheck check
I wanted a logic that executes a sas program If the Errorno is not in 001 and 002. Else stop execution and display the error_table.
I tried the following
%macro test();
proc sql;
select trim(Error_No) into: num from error_table;
quit;
%if &num. not in ("001","002") %then %do;
%include "/path/dev/program.sas";
%end;
%else %do;
proc print data = error_table;
run;
%end;
%mend;
%test;
But, it is throwing an error.
Can anyone please correct the logic.
You need to watch out for the case when the SELECT returns zero rows. You should set a default value to the macro variable NUM.
Is your dataset variable numeric or character? Use the TRIMMED or SEPARATED BY clause instead of the TRIM() function to prevent spaces in the macro variable that is generated by the INTO clause.
%let num=NONE;
select Error_No into: num trimmed from error_table;
Remember that to the macro processor everything is a string so don't but quotes around the values you are trying to match unless they are actually part of the value.
%if NOT (&num. in (001,002)) %then %do;
Also to use the IN operator in macro code you need to make sure you have set the MINDELIMITER option.
I would sugest moving condition with error codes to proc sql.
proc sql;
select count(*) into :num_errors
from error_table
where Errorno in ("001", "002");
quit;
Then in macrovariable you have number of errors that are 001 or 002.
Next step is to check macro-condition:
%if &num_errors. > 0 %then %do;
%include "/path/dev/program.sas";
%end;
%else %do;
proc print data = error_table;
run;
%end;
%mend;