data work.class; infile cards dlm = "," dsd missover ; /* */ informat name $20.; informat gender $1.; informat age 8.; informat height 8.2; informat weight 8.2; informat monthyr 8.; /* */ format name $20.; format gender $1.; format age 8.; format height 8.2; format weight 8.2; format monthyr 8.; /* */ input name gender age height weight monthyr ; cards; Alfred,M,14,69.00,112.50,12004, Alice,F,13,56.50,84.00,122005, Barbara,F,13,65.30,98.00,112002, Carol,F,14,62.80,102.50,62001, Henry,M,14,63.50,102.50,32006, James,M,12,57.30,83.00,42003, Jane,F,12,59.80,84.50,102001, Janet,F,15,62.50,112.50,102005, Jeffrey,M,13,62.50,84.00,92004, John,M,12,59.00,99.50,82006, Joyce,F,11,51.30,50.50,42004, Judy,F,14,64.30,90.00,22001, Louise,F,12,56.30,77.00,112006, Mary,F,15,66.50,112.00,52005, Philip,M,16,72.00,150.00,102002, Robert,M,12,64.80,128.00,22003, Ronald,M,15,67.00,133.00,72006, Thomas,M,11,57.50,85.00,22006, William,M,15,66.50,112.00,122001, ; run; /************************************************************/ /* From Presentation */ /************************************************************/ /*Example 1*/ %macro freq1(var); proc freq; table &var; run; %mend freq1; data one; set class; if gender='M'; run; %freq1(age); data two; set work.class; if gender='F'; run; %freq1(height); /*Example 2*/ options symbolgen mprint mlogic; %macro quarters; %do i=1 %to 6; if monthyr in (1200&i,2200&i,3200&i)then quarter=1200&i; if monthyr in (4200&i,5200&i,6200&i)then quarter=2200&i; if monthyr in (7200&i,8200&i,9200&i)then quarter=3200&i; if monthyr in (10200&i,11200&i,12200&i)then quarter=4200&i; %end; %mend; %macro halfyears; %do i=1 %to 6; if monthyr in (1200&i,2200&i,3200&i,4200&i,5200&i,6200&i)then halves=1200&i; if monthyr in (7200&i,8200&i,9200&i,10200&i,11200&i,12200&i)then halves=2200&i; %end; %mend; /*Q = Quarter, H = HalfYear*/ %macro QorH(required); data class2; set class; %if &required=Q %then %do; %quarters; %end; %else %do; %halfyears; %end; run; %mend; %QorH(Q); /*Example 3*/ data _null_; x = today(); y = intnx('month',x,-36); call symput("mydatenow",put(x,monyy5.)); call symput("mydate3yr",put(y,monyy5.)); run; %put &mydate3yr; %put &mydatenow; /*Further Examples*/ /************************************************************/ /* Parameterising SAS code with macro variables */ /************************************************************/ /************************************************************/ %macro parameterising_sas_code( source_libname, source_dsname, destination_libname, destination_dsname, proc_name, variable_name, by_variables ); /* invoke SAS proc */ proc &proc_name data = &source_libname..&source_dsname ; /* introduce BY VARIABLES if required */ %if &by_variables ne XXX %then %do; by &by_variables; %end; var &variable_name; /* introduce OUTPUT DATASET if required */ %if &destination_libname ne XXX and &destination_dsname ne XXX %then %do; output out = &destination_libname..&destination_dsname._&proc_name; %end; run; %mend parameterising_sas_code; /* proc means on variable AGE */ %parameterising_sas_code ( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class, proc_name =means, variable_name =age, by_variables =XXX ); /* pro univariate on variables HEIGHT and WEIGHT */ %parameterising_sas_code ( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class, proc_name =univariate, variable_name =height weight, by_variables =XXX ); /* proc corr on variables HEIGHT and WEIGHT */ %parameterising_sas_code ( source_libname =work, source_dsname =class, destination_libname =XXX, destination_dsname =XXX, proc_name =corr, variable_name =height weight, by_variables =XXX ); /************************************************************/ /************************************************************/ /* Object Oriented Programming */ /************************************************************/ /************************************************************/ /************************************************************/ /* OBJECT TO DO A SORT */ /************************************************************/ %macro macro_as_object_sort( source_libname, source_dsname, destination_libname, destination_dsname, proc_name, variable_name, by_variables ); /* invoke SAS proc */ proc &proc_name data = &source_libname..&source_dsname out = &destination_libname..&destination_dsname._&proc_name ; /* introduce BY VARIABLES if required */ %if &by_variables ne XXX %then %do; by &by_variables; %end; run; %mend macro_as_object_sort; /************************************************************/ /* OBJECT TO DO A TRANSPOSE */ /************************************************************/ %macro macro_as_object_tran( source_libname, source_dsname, destination_libname, destination_dsname, proc_name, variable_name, by_variables, prefix ); /* invoke SAS proc */ proc &proc_name data = &source_libname..&source_dsname out = &destination_libname..&destination_dsname._&proc_name prefix = &prefix._ ; /* introduce BY VARIABLES if required */ %if &by_variables ne XXX %then %do; by &by_variables; %end; /* VAR statement if required */ %if &variable_name ne XXX %then %do; var &variable_name; %end; run; %mend macro_as_object_tran; /* proc sort on variable AGE */ %macro_as_object_sort( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class_age, proc_name =sort, variable_name =XXX, by_variables =age ); /* proc sort on variable NAME */ %macro_as_object_sort( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class_name, proc_name =sort, variable_name =XXX, by_variables =name ); /* proc sort on variable AGE and GENDER */ %macro_as_object_sort( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class_age_gender, proc_name =sort, variable_name =XXX, by_variables =age gender ); /* proc transpose on variables AGE HEIGHT and WEIGHT - BY NAME */ %macro_as_object_tran( source_libname =work, source_dsname =class_name_sort, destination_libname =work, destination_dsname =class_name, proc_name =transpose, variable_name =age height weight, by_variables =name, prefix =value ); /************************************************************/ /************************************************************/ /* Interplay between SAS macro code and SAS data step code */ /************************************************************/ /************************************************************/ %macro interplay_macro_dstep_code( source_libname, source_dsname, destination_libname, destination_dsname, proc_name, variable_name_1, variable_name_2, variable_name_3, by_variables ); /* initialise number of variables to process */ %global number_of_variables; %let number_of_variables = 0; %if &variable_name_1 ne XXX %then %let number_of_variables = 1; %if &variable_name_2 ne XXX %then %let number_of_variables = 2; %if &variable_name_3 ne XXX %then %let number_of_variables = 3; /* sort on BY VARIABLES if required */ %if &by_variables ne XXX %then %do; /* proc sort on variable AGE and GENDER */ %macro_as_object_sort( source_libname =&source_libname, source_dsname =&source_dsname, destination_libname =&source_libname, destination_dsname =&source_dsname, proc_name =&proc_name, variable_name =XXX, by_variables =&by_variables ); %end; /************************************************************/ /* process CLASS dataset */ /************************************************************/ data &destination_libname..&destination_dsname (keep = &by_variables /* list variables to keep */ %do loop_1 = 1 %to &number_of_variables; avg_&&variable_name_&loop_1 %end; ); /* set unsorted dataset if BY VARIABLES not required */ %if &by_variables eq XXX %then %do; set &source_libname..&source_dsname; %end; /* set sorted dataset if BY VARIABLES required */ %if &by_variables ne XXX %then %do; set &source_libname..&source_dsname._sort; by &by_variables; %end; /* on first occurrence of by_variable */ if first.&by_variables then do; /* initialise variables */ %do loop_1 = 1 %to &number_of_variables; sum_&&variable_name_&loop_1 = 0; %end; ct = 0; end; /* on each occurrence of by_variable */ /* sum variables */ %do loop_1 = 1 %to &number_of_variables; sum_&&variable_name_&loop_1 + &&variable_name_&loop_1; %end; ct + 1; /* on last occurrence of by_variable */ if last.&by_variables then do; /* compute average */ %do loop_1 = 1 %to &number_of_variables; avg_&&variable_name_&loop_1 = sum_&&variable_name_&loop_1 / ct; %end; /* format average */ %do loop_1 = 1 %to &number_of_variables; format avg_&&variable_name_&loop_1 8.2; %end; output; end; run; %mend interplay_macro_dstep_code; /* run this sucker */ %interplay_macro_dstep_code( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class_gender_sum, proc_name =sort, variable_name_1 =age, variable_name_2 =height, variable_name_3 =XXX, by_variables =gender ) /* proc sort on variable AGE and GENDER */ /************************************************************/ /************************************************************/ /* Getting data out of a SAS dataset */ /************************************************************/ /************************************************************/ %macro get_data_from_datset( source_libname, source_dsname, destination_libname, destination_dsname, variable_name_1, variable_name_2, variable_name_3, variable_name_4, variable_name_5 ); /* initialise number of variables to process */ %global number_of_variables; %let number_of_variables = 0; %if &variable_name_1 ne XXX %then %let number_of_variables = 1; %if &variable_name_2 ne XXX %then %let number_of_variables = 2; %if &variable_name_3 ne XXX %then %let number_of_variables = 3; %if &variable_name_4 ne XXX %then %let number_of_variables = 4; %if &variable_name_5 ne XXX %then %let number_of_variables = 5; /* insert unique row id */ data &destination_libname..&destination_dsname; format uid 8.; set &source_libname..&source_dsname; uid = _n_; run; /* isolate number of rows in &destination_libname..&destination_dsname */ proc sql noprint; select max(uid) into :number_of_records from &destination_libname..&destination_dsname ; quit; /* esnure numeric format */ %let number_records = %eval(&number_of_records + 0); /* */ %do loop_1 = 1 %to &number_of_records; %do loop_2 = 1 %to &number_of_variables; /* isolate number of rows in &destination_libname..&destination_dsname */ proc sql noprint; select &&variable_name_&loop_2 into :cell_&loop_1._&loop_2 from &destination_libname..&destination_dsname ; quit; /* print to log */ %put cell_&loop_1._&loop_2 = &&cell_&loop_1._&loop_2; %end; /* loop_2 = 1 %to &number_of_variables */ %end; /* loop_1 = 1 %to &number_records */ %mend get_data_from_datset; /* run this sucker */ %get_data_from_datset( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class_2, variable_name_1 =name, variable_name_2 =gender, variable_name_3 =age, variable_name_4 =height, variable_name_5 =weight ) /************************************************************/ /************************************************************/ /* SAS programs that write SAS programs */ /************************************************************/ /************************************************************/ %macro sas_program_write_program( source_libname, source_dsname, destination_libname, destination_dsname, sas_code_path, sas_code_filename, source_is_cards ); options merror mlogic mautosource; /* convert macro variable contents to upcase */ %global upcase_source_libname; %global upcase_source_dsname; %let upcase_source_libname = %sysfunc(upcase(&source_libname)); %let upcase_source_dsname = %sysfunc(upcase(&source_dsname)); /* get details of target dataset */ data work.field_names (keep = libname memname name type format informat label ); set sashelp.vcolumn; where upcase(trim(left(libname))) = "&upcase_source_libname" and upcase(trim(left(memname))) = "&upcase_source_dsname" ; run; /* insert uid into intermediate dataset work.field_names */ data work.field_names; format uid 8.; set work.field_names; uid = _n_; run; /* isolate number of rows in work.field_names */ proc sql noprint; select max(uid) into :number_of_records from work.field_names ; quit; /* ensure numeric format and declare and initialise required intermediate variables */ %let number_records = %eval(&number_of_records + 0); %global number_of_variables; %let number_of_variables = 7; /* declare global variables */ %do loop_1 = 1 %to &number_of_variables; %global variable_name_&loop_1; %end; /* initialise variables */ %let variable_name_1 = libname; %let variable_name_2 = memname; %let variable_name_3 = name; %let variable_name_4 = type; %let variable_name_5 = format; %let variable_name_6 = informat; %let variable_name_7 = label; /* read values from work.field_names into macro variables */ %do loop_1 = 1 %to &number_of_records; %do loop_2 = 1 %to &number_of_variables; /* isolate number of rows in work.field_names */ proc sql noprint; select &&variable_name_&loop_2 into :cell_&loop_1._&loop_2 from work.field_names where uid = &loop_1 ; quit; /* print to log */ %put cell_&loop_1._&loop_2 = &&cell_&loop_1._&loop_2; %end; /* loop_2 = 1 %to &number_of_variables */ %end; /* loop_1 = 1 %to &number_records */ /* insert uid */ data &destination_libname..&destination_dsname; format uid 8.; set &source_libname..&source_dsname; uid = _n_; run; /* make 10 copies */ data &destination_libname..&destination_dsname; format source 8.; set &destination_libname..&destination_dsname; do source = 1 to 10; output; end; run; /* sort into order necessary for generating code */ proc sort data = &destination_libname..&destination_dsname out = &destination_libname..&destination_dsname ; by source uid ; run; /************************************************************/ /************************************************************/ /* generate SAS code */ /************************************************************/ /************************************************************/ data _null_; file "&sas_code_path./&sas_code_filename..sas"; set &destination_libname..&destination_dsname end = last_record ; by source ; /* on first record in dataset */ if _n_ = 1 then do; put @1 "/**********************************************************************/"; put @1 "/**********************************************************************/"; put @1 "/*" @5 " Import &source_dsname. dataset" @70 " */"; put @1 "/**********************************************************************/"; put @1 "/**********************************************************************/"; /* convert to upcase */ %let source_is_cards = %sysfunc(upcase(&source_is_cards)); put @1 "data" @10 "&source_libname..&source_dsname;"; /* if data source is cards statement */ %if &source_is_cards = Y %then %do; put @1 "infile" @10 "cards" ; put @10 "dlm" @30 "=" @35 ""","""; put @10 "dsd"; put @10 "missover"; put @10 ";"; %end; /* if data source is cards statement */ %if &source_is_cards = N %then %do; put @1 "infile" @10 """&path/&source_data_filename""" ; put @10 "dlm" @30 "=" @35 ""","""; put @10 "firstobs" @30 "=" @35 "1"; put @10 "lrecl" @30 "=" @35 "1000"; put @10 "dsd"; put @10 "missover"; put @10 ";"; %end; put; /************************************************************/ /* Write informat statements */ /************************************************************/ put @5 "/*" @10 "specify informat for reading data from input buffer to SAS LPDV" @80 "*/"; %do loop_1 = 1 %to &number_of_records; /* on each occurrence of source = 1 */ put @5 "informat" @20 "&&cell_&loop_1._3" @55 "&&cell_&loop_1._6" @65 ";"; %end; put; /************************************************************/ /* Write format statements */ /************************************************************/ put @5 "/*" @10 "specify format for writing data from SAS LPDV to SAS dataset" @80 "*/"; %do loop_1 = 1 %to &number_of_records; /* on each occurrence of source = 1 */ put @5 "format" @20 "&&cell_&loop_1._3" @55 "&&cell_&loop_1._5" @65 ";"; %end; put; /************************************************************/ /* Write label statements */ /************************************************************/ put @5 "/*" @10 "specify field labels" @80 "*/"; %do loop_1 = 1 %to &number_of_records; /* on each occurrence of source = 1 */ %let cell_&loop_1._7 = %trim(%left(&&cell_&loop_1._7)); put @5 "label" @20 "&&cell_&loop_1._3" @55 "=" @60 """" "&&cell_&loop_1._7 " """" ";"; %end; put; /************************************************************/ /* Write input statements */ /************************************************************/ put @5 "/*" @10 "specify variables to read from source data" @80 "*/"; put @5 "input" @@; %do loop_1 = 1 %to &number_of_records; /* on each occurrence of source = 1 */ put @5 @20 "&&cell_&loop_1._3"; %end; put @20 ";"; put; end; /* if data source is cards statement */ %if &source_is_cards = Y %then %do; /************************************************************/ /* Write data in cards statement */ /************************************************************/ if source = 1 then do; if first.source then do; put @1 "cards;"; end; /* on each occurrence of source = 4 */ put @1 name +(-1) "," gender +(-1) "," age +(-1) "," height +(-1) "," weight +(-1) ","; if not first.source and not last.source then do; end; if last.source then do; put @1 ";"; end; end; %end; /* on last record in dataset */ if last_record then do; put @1 "run;"; end; run; options nomerror nomlogic; %mend sas_program_write_program; /* run this sucker */ %sas_program_write_program( source_libname =work, source_dsname =class, destination_libname =work, destination_dsname =class_10x, sas_code_path =u:, sas_code_filename =ImportCLASSdataset, source_is_cards =Y );