I have a macro program, inside this macro program there is piece of code which is common across multiple programs. I am trying to call this piece of code by %include statement. But as I use %include it starts giving ERROR: The %DO statement is not valid in open code.
Without %INCLUDE it works fine. My understanding is %include gets code from external file into current program so ideally it should work, not sure where getting wrong.
Sample Program -
%macro test();
data test1;
set test;
CALL SYMPUT('N',_N_);
CALL SYMPUTX(CAT('CTY',_N_),ctry_code);
run;
/*Below DO loop I am putting in external file*/
/*%include "<location>/test_inc.sas";*/
%DO I=1 %TO &N.;
DATA _TMP;
SET dim.&ds.;
where &fld_nm. eq "&&cty&i.";
run;
OPTIONS VALIDVARNAME=UPCASE;
proc export data=_TMP outfile="<location>"
dbms=csv replace;
run;
%END;
%mend;
%test;
You can't do that. Here is a simplified test case.
filename code temp;
data _null_;
file code ;
put '%do i=1 %to &n; put &=i; %end;';
run;
%macro test(n);
%put &=sysmacroname &=n;
%include code / source2;
%mend;
%test(1);
The issue is that when %TEST() is compiled it does NOT include the code from the file into the macro definition. It just puts the %INCLUDE statement into the macro definition. Therefore when the %INCLUDE runs the macro compiler is not running anymore. So the code in the include file has to be code that can run as open code.
For my simplified solution the fix is to change the %INCLUDE file to define and call its own macro to wrap around the %DO loop.
%macro _code_;
%local i;
%do i=1 %to &n;
%put &=sysmacroname &=i;
%end;
%mend;
%_code_;
Results:
15 %test(1); SYSMACRONAME=TEST N=1 NOTE: %INCLUDE (level 1) file CODE is file .... 16 +%macro _code_; 17 +%local i; 18 +%do i=1 %to &n; 19 + %put &=sysmacroname &=i; 20 +%end; 21 +%mend; 22 +%_code_; SYSMACRONAME=_CODE_ I=1 MPRINT(TEST): ; NOTE: %INCLUDE (level 1) ending.
Please show us the LOG of both cases, with %include and without %include. We need to see the entire log, all of it, every single line, with nothing chopped out. Please copy the log as text and paste it into the window that appears when you click on the </> icon. DO NOT SKIP THE PART IN RED.
Failed Log - 1 The SAS System 19:52 Sunday, August 29, 2021 1 ;*';*";*/;quit;run; 2 OPTIONS PAGENO=MIN; 3 %LET _CLIENTTASKLABEL='Program (4)'; 4 %LET _CLIENTPROCESSFLOWNAME='Process Flow'; 5 %LET _CLIENTPROJECTPATH=''; 6 %LET _CLIENTPROJECTNAME=''; 7 %LET _SASPROGRAMFILE=; 8 9 ODS _ALL_ CLOSE; 10 OPTIONS DEV=ACTIVEX; 11 GOPTIONS XPIXELS=0 YPIXELS=0; 12 FILENAME EGSR TEMP; 13 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR 14 STYLE=HtmlBlue 15 STYLESHEET=(URL="file:///C:/Program%20Files/SASHome/SASEnterpriseGuide/7.1/Styles/HtmlBlue.css") 16 NOGTITLE 17 NOGFOOTNOTE 18 GPATH=&sasworklocation SYMBOLGEN: Macro variable SASWORKLOCATION resolves to "/localwork2/SAS_work29EB0000FD28_hkpa2ls0136/SAS_work57120000FD28_hkpa2ls0136/" 19 ENCODING=UTF8 20 options(rolap="on") 21 ; NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR 22 23 GOPTIONS ACCESSIBLE; 24 options symbolgen mlogic mprint; 25 26 %MACRO TEST(ds,fld_nm); 27 28 libname dim "<location>" access =r; 29 30 proc sql; 31 create table test as 32 select distinct &fld_nm. from dim.&ds.; 33 quit; 34 35 data test1; 36 set test(WHERE=(&fld_nm. EQ 'IND')); 37 CALL SYMPUT('N',_N_); 38 CALL SYMPUTX(CAT('CTY',_N_),&fld_nm.); 39 run; 40 41 %PUT &N.; 42 43 %include "location"; 44 45 %MEND; 46 47 %test(dim_product,ctry_cde); MLOGIC(TEST): Beginning execution. MLOGIC(TEST): Parameter DS has value dim_product MLOGIC(TEST): Parameter FLD_NM has value ctry_cde MPRINT(TEST): libname dim "<location>" access =r; NOTE: Libref DIM was successfully assigned as follows: Engine: V9 Physical Name: <location> MPRINT(TEST): proc sql; 2 The SAS System 19:52 Sunday, August 29, 2021 SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde SYMBOLGEN: Macro variable DS resolves to dim_product MPRINT(TEST): create table test as select distinct ctry_cde from dim.dim_product; NOTE: Compression was disabled for data set WORK.TEST because compression overhead would increase the size of the data set. NOTE: Table WORK.TEST created, with 8 rows and 1 columns. MPRINT(TEST): quit; NOTE: PROCEDURE SQL used (Total process time): real time 0.03 seconds cpu time 0.01 seconds MPRINT(TEST): data test1; SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde MPRINT(TEST): set test(WHERE=(ctry_cde EQ 'IND')); MPRINT(TEST): CALL SYMPUT('N',_N_); SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde MPRINT(TEST): CALL SYMPUTX(CAT('CTY',_N_),ctry_cde); MPRINT(TEST): run; NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column). 3998:233 NOTE: Compression was disabled for data set WORK.TEST1 because compression overhead would increase the size of the data set. NOTE: There were 1 observations read from the data set WORK.TEST. WHERE ctry_cde='IND'; NOTE: The data set WORK.TEST1 has 1 observations and 1 variables. NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.00 seconds MLOGIC(TEST): %PUT &N. SYMBOLGEN: Macro variable N resolves to 1 1 ERROR: The %DO statement is not valid in open code. MPRINT(TEST): DATA _TMP; SYMBOLGEN: Macro variable DS resolves to dim_product MPRINT(TEST): SET dim.dim_product; SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde SYMBOLGEN: && resolves to &. WARNING: Apparent symbolic reference I not resolved. SYMBOLGEN: Unable to resolve the macro variable reference &i WARNING: Apparent symbolic reference CTY not resolved. WARNING: Apparent symbolic reference I not resolved. MPRINT(TEST): where ctry_cde eq "&cty&i."; MPRINT(TEST): run; NOTE: There were 0 observations read from the data set DIM.DIM_PRODUCT. WHERE ctry_cde='&cty&i.'; NOTE: The data set WORK._TMP has 0 observations and 31 variables. NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.02 seconds MPRINT(TEST): proc print data=_tmp; MPRINT(TEST): run; 3 The SAS System 19:52 Sunday, August 29, 2021 NOTE: No observations in data set WORK._TMP. NOTE: PROCEDURE PRINT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds ERROR: The %END statement is not valid in open code. MLOGIC(TEST): Ending execution. 60 61 GOPTIONS NOACCESSIBLE; 62 %LET _CLIENTTASKLABEL=; 63 %LET _CLIENTPROCESSFLOWNAME=; 64 %LET _CLIENTPROJECTPATH=; 65 %LET _CLIENTPROJECTNAME=; 66 %LET _SASPROGRAMFILE=; 67 68 ;*';*";*/;quit;run; 69 ODS _ALL_ CLOSE; 70 71 72 QUIT; RUN; 73
Success Log (without INCLUDE) - NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR 22 23 GOPTIONS ACCESSIBLE; 24 options symbolgen mlogic mprint; 25 26 %MACRO TEST(ds,fld_nm); 27 28 libname dim "<location>" access =r; 29 30 proc sql; 31 create table test as 32 select distinct &fld_nm. from dim.&ds.; 33 quit; 34 35 data test1; 36 set test(WHERE=(&fld_nm. EQ 'IND')); 37 CALL SYMPUT('N',_N_); 38 CALL SYMPUTX(CAT('CTY',_N_),&fld_nm.); 39 run; 40 41 %PUT &N.; 42 /*%PUT &CTY1. &CTY5.;*/ 43 44 /*%include "<location>";*/ 45 46 %DO I=1 %TO &N.; 47 48 DATA _TMP; 49 SET dim.&ds.; 50 where &fld_nm. eq "&&cty&i."; 51 run; 52 53 PROC PRINT DATA=_TMP; 54 RUN; 55 2 The SAS System 19:52 Sunday, August 29, 2021 56 %END; 57 58 59 %MEND; 60 61 %test(dim_product,ctry_cde); MLOGIC(TEST): Beginning execution. MLOGIC(TEST): Parameter DS has value dim_product MLOGIC(TEST): Parameter FLD_NM has value ctry_cde MPRINT(TEST): libname dim “<Location>" access =r; NOTE: Libref DIM was successfully assigned as follows: Engine: V9 Physical Name: <Location> MPRINT(TEST): proc sql; SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde SYMBOLGEN: Macro variable DS resolves to dim_product MPRINT(TEST): create table test as select distinct ctry_cde from dim.dim_product; NOTE: Compression was disabled for data set WORK.TEST because compression overhead would increase the size of the data set. NOTE: Table WORK.TEST created, with 8 rows and 1 columns. MPRINT(TEST): quit; NOTE: PROCEDURE SQL used (Total process time): real time 0.03 seconds cpu time 0.00 seconds MPRINT(TEST): data test1; SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde MPRINT(TEST): set test(WHERE=(ctry_cde EQ 'IND')); MPRINT(TEST): CALL SYMPUT('N',_N_); SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde MPRINT(TEST): CALL SYMPUTX(CAT('CTY',_N_),ctry_cde); MPRINT(TEST): run; NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column). 3651:233 NOTE: Compression was disabled for data set WORK.TEST1 because compression overhead would increase the size of the data set. NOTE: There were 1 observations read from the data set WORK.TEST. WHERE ctry_cde='IND'; NOTE: The data set WORK.TEST1 has 1 observations and 1 variables. NOTE: DATA statement used (Total process time): real time 0.13 seconds cpu time 0.02 seconds MLOGIC(TEST): %PUT &N. SYMBOLGEN: Macro variable N resolves to 1 1 SYMBOLGEN: Macro variable N resolves to 1 MLOGIC(TEST): %DO loop beginning; index variable I; start value is 1; stop value is 1; by value is 1. MPRINT(TEST): DATA _TMP; SYMBOLGEN: Macro variable DS resolves to dim_product MPRINT(TEST): SET dim.dim_product; SYMBOLGEN: Macro variable FLD_NM resolves to ctry_cde SYMBOLGEN: && resolves to &. SYMBOLGEN: Macro variable I resolves to 1 SYMBOLGEN: Macro variable CTY1 resolves to IND MPRINT(TEST): where ctry_cde eq "IND"; 3 The SAS System 19:52 Sunday, August 29, 2021 MPRINT(TEST): run; NOTE: There were 55 observations read from the data set DIM.DIM_PRODUCT. WHERE ctry_cde='IND'; NOTE: The data set WORK._TMP has 55 observations and 31 variables. NOTE: Compressing data set WORK._TMP increased size by 100.00 percent. Compressed is 2 pages; un-compressed would require 1 pages. NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.01 seconds MPRINT(TEST): PROC PRINT DATA=_TMP; MPRINT(TEST): RUN; NOTE: There were 55 observations read from the data set WORK._TMP. NOTE: PROCEDURE PRINT used (Total process time): real time 0.15 seconds cpu time 0.16 seconds MLOGIC(TEST): %DO loop index variable I is now 2; loop will not iterate again. MLOGIC(TEST): Ending execution.
Thank you. Please run
options mprint;
and then run the failed code again, modifying the %include code to say %include "location"/source2;
Show us the complete log.
You can't do that. Here is a simplified test case.
filename code temp;
data _null_;
file code ;
put '%do i=1 %to &n; put &=i; %end;';
run;
%macro test(n);
%put &=sysmacroname &=n;
%include code / source2;
%mend;
%test(1);
The issue is that when %TEST() is compiled it does NOT include the code from the file into the macro definition. It just puts the %INCLUDE statement into the macro definition. Therefore when the %INCLUDE runs the macro compiler is not running anymore. So the code in the include file has to be code that can run as open code.
For my simplified solution the fix is to change the %INCLUDE file to define and call its own macro to wrap around the %DO loop.
%macro _code_;
%local i;
%do i=1 %to &n;
%put &=sysmacroname &=i;
%end;
%mend;
%_code_;
Results:
15 %test(1); SYSMACRONAME=TEST N=1 NOTE: %INCLUDE (level 1) file CODE is file .... 16 +%macro _code_; 17 +%local i; 18 +%do i=1 %to &n; 19 + %put &=sysmacroname &=i; 20 +%end; 21 +%mend; 22 +%_code_; SYSMACRONAME=_CODE_ I=1 MPRINT(TEST): ; NOTE: %INCLUDE (level 1) ending.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.