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.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.