I tried to call macro using parameter which is variables, so I cannot write it directly in macro call. I want pass the value of the variable memname...
154 options mprint;
155 %macro readdata(mname);
156 filename datafile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\&mname..xml" ;
157 filename mapfile
157! "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
158
159 libname datafile xmlv2 xmlmap=mapfile automap=replace;
160
161 proc copy in=datafile out=work;
162 run;
163 %mend;
164
165 data _null_;
166 memname = compress (memname, ".xml");
167 call symput('mname',memname);
168 do i = 1 to &mcount;
169 %readdata(&&mname)
WARNING: Apparent symbolic reference MNAME not resolved.
ERROR: The text expression &MNAME contains a recursive reference to the macro variable MNAME.
The macro variable will be assigned the null value.
MPRINT(READDATA): filename datafile
"e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\.xml" ;
MPRINT(READDATA): filename mapfile
"e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
MPRINT(READDATA): libname datafile xmlv2 xmlmap=mapfile automap=replace;
ERROR: With the AUTOMAP= option, the specified XML document must exist.
ERROR: Error in the LIBNAME statement.
NOTE: Line generated by the invoked macro "READDATA".
1 filename datafile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\&mname..xml"
1 ! ; filename mapfile
1 ! "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ; libname
1 ! datafile xmlv2 xmlmap=mapfile automap=replace; proc
-
117
ERROR 117-185: There was 1 unclosed DO block.
NOTE: Numeric values have been converted to character values at the places given by:
(Line):(Column).
166:21 167:21
NOTE: Character values have been converted to numeric values at the places given by:
(Line):(Column).
166:11
NOTE: The SAS System stopped processing this step because of errors.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds
MPRINT(READDATA): proc copy in=datafile out=work;
MPRINT(READDATA): run;
ERROR: Libref DATAFILE is not assigned.
NOTE: Statements not processed because of errors noted above.
NOTE: PROCEDURE COPY used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: The SAS System stopped processing this step because of errors.
170 end;
171 run;
That missing part of the program turns out to be important. Try replacing this DATA step:
data _null_;
set contents;
call symput('mname',memname);
do i = 1 to &mcount;
%readdata(&&mname)
end;
run;
Instead, use:
data _null_;
set contents;
call execute('%nrstr(%readdata(' || memname || '))' ) ;
run;
It's untested (obviously?), but I think I got the quotes in the proper place.
The error message is very clear about what the problem is:
ERROR 117-185: There was 1 unclosed DO block.
thank you for your quick reply.
I cannot find unclosed do loop anywhere.
17 options mprint;
18 %macro readdata(mname);
19 filename datafile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\&mname..xml" ;
20 filename mapfile
20 ! "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
21
22 libname datafile xmlv2 xmlmap=mapfile automap=replace;
23
24 proc copy in=datafile out=work;
25 run;
26 %mend;
27 data _null_;
28 set contents;
29 memname = compress (memname, ".xml");
30 call symput('mname',memname);
31 do i = 1 to &mcount;
32 %readdata(&&mname)
WARNING: Apparent symbolic reference MNAME not resolved.
ERROR: The text expression &MNAME contains a recursive reference to the macro variable MNAME.
The macro variable will be assigned the null value.
MPRINT(READDATA): filename datafile
"e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\.xml" ;
MPRINT(READDATA): filename mapfile
"e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
MPRINT(READDATA): libname datafile xmlv2 xmlmap=mapfile automap=replace;
ERROR: With the AUTOMAP= option, the specified XML document must exist.
ERROR: Error in the LIBNAME statement.
NOTE: Line generated by the invoked macro "READDATA".
1 filename datafile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\&mname..xml"
1 ! ; filename mapfile
1 ! "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ; libname
1 ! datafile xmlv2 xmlmap=mapfile automap=replace; proc
-
117
ERROR 117-185: There was 1 unclosed DO block.
NOTE: The SAS System stopped processing this step because of errors.
NOTE: DATA statement used (Total process time):
real time 0.12 seconds
cpu time 0.06 seconds
NOTE: Writing HTML Body file: sashtml.htm
MPRINT(READDATA): proc copy in=datafile out=work;
MPRINT(READDATA): run;
ERROR: Libref DATAFILE is not assigned.
NOTE: Statements not processed because of errors noted above.
NOTE: PROCEDURE COPY used (Total process time):
real time 0.30 seconds
cpu time 0.18 seconds
NOTE: The SAS System stopped processing this step because of errors.
33 end;
34 run;
Post your code as well. Reading it with the line numbers is problematic.
At a minimum, you have two issues to fix.
Where does &MCOUNT come from?
The DATA step that uses CALL SYMPUT to create &MNAME ... it has to execute CALL SYMPUT in order to create &MNAME. But the DATA step has not yet executed by the time &MNAME is needed. This actually requires some in-depth knowledge about the timing of actions in the DATA step vs. macro language.
The other issue is that COMPRESS does not work the way you hope. It does not look for the word ".xml" and remove it. It looks for all instances of "." and all instances of "x" and all instances of "m" and all instances of "l" and removes any and all of them. You need a better way to remove ".xml" from the end of your file names, assuming that is your intention.
thank you for your reply.
the first step of the program is like this and the memname and memcount has been created in this step.
1 filename inzip ZIP "e:\Users\mhollifi\Desktop\Jotikasthira\USA_FO_Active_2016-04.zip";
2 data contents;
3 length memname $200;
4 fid=dopen("inzip");
5 PUT 'fid: ' fid=;
6 if fid=0 then
7 stop;
8 memcount=dnum(fid);
9 PUT 'Memcount: ' memcount=;
10 do i=1 to memcount;
11 memname=dread(fid,i);
12 output;
13 end;
14 rc=dclose(fid);
15 call symput('mcount',memcount);
16 run;
NOTE: Numeric values have been converted to character values at the places given by:
(Line):(Column).
15:23
fid: fid=1
Memcount: memcount=4172
my code is
filename inzip ZIP "e:\Users\mhollifi\Desktop\Jotikasthira\USA_FO_Active_2016-04.zip";
data contents;
length memname $200;
fid=dopen("inzip");
PUT 'fid: ' fid=;
if fid=0 then
stop;
memcount=dnum(fid);
PUT 'Memcount: ' memcount=;
do i=1 to memcount;
memname=dread(fid,i);
output;
end;
rc=dclose(fid);
call symput('mcount',memcount);
run;
options mprint;
%macro readdata(mname);
filename datafile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\&mname" ;
filename mapfile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
libname datafile xmlv2 xmlmap=mapfile automap=replace;
proc copy in=datafile out=work;
run;
%mend;
data _null_;
set contents;
call symput('mname',memname);
do i = 1 to &mcount;
%readdata(&&mname)
end;
run;
thank you all for your help.
When I put run after call symput statement, it reads only the last observation. I want go through variables after variables.
So the solution with symput doesn't work...How to use variable name as macro parameter?
126 options mprint;
127 %macro readdata(mname);
128 filename datafile "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\&mname" ;
129 filename mapfile
129! "e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
130
131 libname datafile xmlv2 xmlmap=mapfile automap=replace;
132
133 proc copy in=datafile out=work;
134 run;
135 %mend;
136
137 data _null_;
138 set contents;
139 call symput('mname',memname); run;
NOTE: There were 4172 observations read from the data set WORK.CONTENTS.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
ERROR: The %DO statement is not valid in open code.
140 %do i = 1 %to &mcount;
141 %readdata(&&mname)
MPRINT(READDATA): filename datafile
"e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\999845-2016-04-30.xml" ;
MPRINT(READDATA): filename mapfile
"e:\Users\mhollifi\Desktop\Chotibhak\USA_FO_Active_2016-04\5-2016-04-30.map" ;
MPRINT(READDATA): libname datafile xmlv2 xmlmap=mapfile automap=replace;
ERROR: With the AUTOMAP= option, the specified XML document must exist.
ERROR: Error in the LIBNAME statement.
MPRINT(READDATA): proc copy in=datafile out=work;
MPRINT(READDATA): run;
ERROR: Libref DATAFILE is not assigned.
NOTE: Statements not processed because of errors noted above.
NOTE: PROCEDURE COPY used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
NOTE: The SAS System stopped processing this step because of errors.
ERROR: The %END statement is not valid in open code.
142 %end;
143 run;
That missing part of the program turns out to be important. Try replacing this DATA step:
data _null_;
set contents;
call symput('mname',memname);
do i = 1 to &mcount;
%readdata(&&mname)
end;
run;
Instead, use:
data _null_;
set contents;
call execute('%nrstr(%readdata(' || memname || '))' ) ;
run;
It's untested (obviously?), but I think I got the quotes in the proper place.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.