SAS Grid Enabling - sas

I have to pull a lot of data and I am trying to grid enable it to run faster. Unfortunately, I am not a SAS coder so I am trying to modify existing code. I keep getting a 'no matching %DO statement for the %END' error in the waitfor all section of the log. I am not even sure this would work otherwise.
Does someone have grid experience to help me out?
%let _sdtm=%sysfunc(datetime());
%macro splitmonths(begmonth=,endmonth=);
%let rc=%sysfunc(grdsvc_enable(_all_,server=SASApp));
options autosignon;
%do imth=&begmonth %to &endmonth;
signon t&imth;
%syslput imth=&imth/remote=t&imth;
rsubmit t&imth wait=no;
PROC SQL;
CREATE TABLE WORK.QUERY_FOR_VW_HOUPOSSW_FACT_&imth AS
SELECT t1.outletfamily,
t1.ppmonth,
t1.itemnumber,
/* Dollars */
(SUM(t1.totalvalue)) FORMAT=DOLLAR20. AS Dollars
FROM HOUPWP7.vw_houpossw_fact t1
WHERE t1.ppmonth = &imth;
GROUP BY t1.outletfamily,
t1.ppmonth,
t1.itemnumber;
QUIT;
endrsubmit;
%end
waitfor _all_
%do imth=&begmonth %to &endmonth;
t&imth
%end;
;
signoff _all_;
data newdata;
set
%do imth=&begmonth %to &endmonth;
newdata&imth
%end;
;
run;
proc datasets lib=work;
%do imth=&begmonth %to &endmonth;
delete newdata&imth;
%end
quit;
%mend splitmonths
%splitmonths (begmonth=541, endmonth=588)
%let _edtm=%sysfunc(datetime());
%let _runtm=%sysfunc(putn(&_edtm - &_sdtm, 12.4));
%put It took &_runtm second to run the program;enter code here

Trying adding semi-colon to end the %end macro statement just before the start of the waitfor statement.
%end;
waitfor _all_

Related

Conditional Formatting in SAS with Macros

Hi I'm trying to apply conditional formatting to a table in SAS. The conditional formatting will be highlighting data in columns (variables). If the field is "Y" then highlight green, else if the field is "N" then red.
The input table looks like this:
My goal is to have it looks something like this
I currently have this code in my macro:
%LET NVARS= 6;
%LET to_date= '01SEP2022'd;
%macro cf();
PROC REPORT DATA=work.process /*the data set input */ OUT=work.test1;
COLUMN SKU HIGH PRI COST_CTR
%DO i = 1 %TO &NVARS.;
SUPPORT&i.
%END;
%DO i =1 %TO &NVARS.;
DEFINE SUPPORT&i. / DISPLAY
STYLE (column)={just=center};
%END;
%DO i =1 %TO &NVARS.;
COMPUTE SUPPORT&i.;
IF SUPPORT&i. ='Y' THEN CALL DEFINE (_col_,'style','style={background=vilg}');
IF SUPPORT&i. ='N' THEN CALL DEFINE (_col_,'style','style={background=viypk}');
ENDCOMP;
%END;
RENAME
%DO i =1 %TO &NVARS.;
SUPPORT&i. = %SYSFUNC(INTNX(month,&to_date.,&I-1),monyy7)
%END;
RUN;
%MEND;
%cf();
For some reason it's erroring out and not doing the conditional formatting. I then want to export the output in excel. Any help is greatly appreciates from SAS gurus.
Personally, I would use PROC PRINT to do this instead of PROC REPORT.
Create a format to format Y as green, N as red
Use PROC PRINT to display information
Create labels dynamically instead of rename to display the months name dynamically.
Use ODS EXCEL to pipe the formatted output including colours directly to Excel (tested and it works).
proc format;
value $ support_fmt
'Y' = 'vilg'
'N' = 'viypk';
run;
ods excel file = '/home/fkhurshed/Demo1/demo.xlsx';
%macro cf;
%LET NVARS= 6;
%LET to_date= '01SEP2022'd;
proc print data=have label noobs;
var sku high_pri cost_ctr ;
var support1-support6 / style={background=$support_fmt.};
%do i=1 %to &nvars;
label support&i. = %sysfunc(intnx(month, &to_date, %eval(&i-1)), monyy7.);;
%end;
run;
%mend;
%cf;
ods excel close;

How to trigger a macro for every data set containing a keyword

I'm doing a crash course on SAS macros and I'm stuck at one exercise. I have to create a macro, that will create a proc contents tables for every data set, that contains a keyword. I know how to do that using call execute, but I need this using proc sql and %do loop.
My attempt:
%macro contents(data=&syslast);
proc contents data=&data;
title "&data";
run;
%mend contents;
%macro ContentsAll(keyword);
select libname||'.'||memname
into :dsn1-
from sashelp.vstabvw
where upcase(memname) like %upcase("%quote(%)&&keyword%")
;
quit;
%do i=1 %to &sqlobs;
%contents(data=&&dsn&i);
%end;
%mend ContentsAll;
options mlogic mprint;
%ContentsAll(class);
options nomlogic nomprint;
I know there is some issue with a select statement, but I have no idea how to fix it. And where statement has an unprotected variable (my attempts at fixing it just break the where clause alltogether.
First of all, good job. It's so good that I'm almost sorry you're only missing the Proc SQL Statement :-)
%macro contents(data=&syslast);
proc contents data=&data;
title "&data";
run;
%mend contents;
%macro ContentsAll(keyword);
proc sql noprint;
select libname||'.'||memname
into :dsn1-
from sashelp.vstabvw
where upcase(memname) like %upcase("%quote(%)&&keyword%")
;
quit;
%do i=1 %to &sqlobs;
%contents(data=&&dsn&i);
%end;
%mend ContentsAll;
options mlogic mprint;
%ContentsAll(class);
options nomlogic nomprint;
There is no need to create all of those macro variables. Just keep the list of names in actual data. You can use CALL EXECUTE() to generate the code you want to run for each member in the list.
Note that the variables LIBNAME and MEMNAME will already be in uppercase when pulled from the DICTIONARY.MEMBERS metadata that the view SASHELP.VSTABVW uses. But the user passing in a value for the KEYWORD parameter might not have entered uppercase letters.
%macro ContentsAll(keyword);
data _null_;
set sashelp.vstabvw ;
where memname contains "%qupcase(&keyword)" ;
call execute(cats('%nrstr(%contents)(data=',libname,'.',memname,')'));
run;
%mend ContentsAll;

How to run part of macro based on number of observations in work file in SAS

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;

Some problems appear when i use Macro variable

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.

List only the column names of a dataset

I am working on SAS in UNIX env and I want to view only the column name of a dataset. I have tried proc contents and proc print but both of them list a lot of other irrevelant information that I do not want as it fills up my putty screen and the information ultimately is lost.
I also tried to get this thing frm the sas metadata but that is not working either.
I tried :
2? proc sql;
select *
from dictionary.tables
where libname='test' and memname='sweden_elig_file_jul';
quit;
5?
NOTE: No rows were selected.
6?
NOTE: PROCEDURE SQL used (Total process time):
real time 0.27 seconds
cpu time 0.11 seconds
You're using the wrong dictionary table to get column names...
proc sql ;
select name
from dictionary.columns
where memname = 'mydata'
;
quit ;
Or using PROC CONTENTS
proc contents data=mydata out=meta (keep=NAME) ;
run ;
proc print data=meta ; run ;
Here's one I've used before to get a list of columns with a little bit more information, you can add the keep option as in the previous answer. This just demonstrates how to create a connection to the metadata server, in case that is useful to anyone viewing this post.
libname fetchlib meta
library="libraryName" metaserver="metaDataServerAddress"
password="yourPassword" port=1234
repname="yourRepositoryName" user="yourUserName";
proc contents data=fetchlib.YouDataSetName
memtype=DATA
out=outputDataSet
nodetails
noprint;
run;
For a pure macro approach, try the following:
%macro mf_getvarlist(libds
,dlm=%str( )
)/*/STORE SOURCE*/;
/* declare local vars */
%local outvar dsid nvars x rc dlm;
/* open dataset in macro */
%let dsid=%sysfunc(open(&libds));
%if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NVARS));
%if &nvars>0 %then %do;
/* add first dataset variable to global macro variable */
%let outvar=%sysfunc(varname(&dsid,1));
/* add remaining variables with supplied delimeter */
%do x=2 %to &nvars;
%let outvar=&outvar.&dlm%sysfunc(varname(&dsid,&x));
%end;
%End;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put unable to open &libds (rc=&dsid);
%let rc=%sysfunc(close(&dsid));
%end;
&outvar
%mend;
Usage:
%put List of Variables=%mf_getvarlist(sashelp.class);
Returns:
List of Variables=Name Sex Age Height Weight
source: https://github.com/sasjs/core/blob/main/base/mf_getvarlist.sas
proc sql;
select *
from dictionary.tables
where libname="TEST" and memname="SWEDEN_ELIG_FILE_JUL";
quit;