BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
LAYMAN_YO
Calcite | Level 5

 

33

%macro a(libname=,domain=);
%let folder=C:\Users\SAS;

filename DIR1 "&folder";
data DT1 ;
length VAR $400 ;
*** Open directory ;
did = dopen("DIR1") ;

*** Store filename and label into dataset;
do i = 1 to dnum( did ) ;
VAR = scan(dread( did , i ),1,'.') ;
call symputx(compress('fname'||trim(i)),var);
output;
end;

/*  I would like to get dnum(did) here instead of the actual number of 33 */
%do i=1 %to 33;           
proc transpose data=&libname..&&fname&i (obs=0) out=&&fname&i;
var _ALL_;
run;
data a1 ;
length domainkeys $ 400;
set &&fname&i end=eof;
retain domainkeys '';
domainkeys = trim(domainkeys) ||' '||trim(put(_name_,20.));
if eof then call symputx(compress("&&fname&i"||"KEEPSTRINGfd"),domainkeys, 'G' );
run;
%end;
%mend;

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

A couple of items to consider.

 

First, to solve the problem entirely, you need to add a RUN statement to your DATA step.  Without it, SAS tries to evaluate the %DO loop boundaries before actually running the DATA step, and &NUMFILES does not yet exist (because the DATA step has not yet executed).

 

Second, this might be a little simpler and would get rid of the annoying conversion note:

 

numfiles=dnum(did);
call symputx('numfiles', numfiles);

 

Switching to CALL SYMPUTX performs the numeric to character conversion without a note, and automatically strips out any blanks caused by the conversion. 

View solution in original post

12 REPLIES 12
SASKiwi
PROC Star

Read the output of the DNUM function into a variable as explained in the documentation:

https://documentation.sas.com/?docsetId=sclref&docsetTarget=p1j7tan0hegma8n1x7uu7cei4inb.htm&docsetV...

LAYMAN_YO
Calcite | Level 5

I mean

 %do i=1 %to dnum(did);   

does not work.

SASKiwi
PROC Star

You need to do this:

 

numfiles=dnum(did);
call symput('numfiles', strip(put(numfiles, 8.)));

....
....
%do i = 1 %to &numfiles;
LAYMAN_YO
Calcite | Level 5

Thank you for your suggestion, but it seems it does not work.

NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
2:25
NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.DT1 may be incomplete. When this step was stopped there were 0 observations and 4 variables.
WARNING: Data set WORK.DT1 was not replaced because this step was stopped.
NOTE: DATA statement used (Total process time):
real time 24.37 seconds
cpu time 1.74 seconds

 

WARNING: Apparent symbolic reference NUMFILES not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The
condition was: &numfiles
ERROR: The %TO value of the %DO I loop is invalid.
ERROR: The macro A will stop executing.

Kurt_Bremser
Super User

Depending on where you put the call symput(), it might happen that it is never executed (ie if no files are present there).

 

A better method of creating repeating code is to not use a %do loop, but to use call execute in a date _null_ step running off the dataset with dataset names.

SASKiwi
PROC Star

Please post the complete log including the source statements otherwise we have no way of working out what went wrong.

Astounding
PROC Star

A couple of items to consider.

 

First, to solve the problem entirely, you need to add a RUN statement to your DATA step.  Without it, SAS tries to evaluate the %DO loop boundaries before actually running the DATA step, and &NUMFILES does not yet exist (because the DATA step has not yet executed).

 

Second, this might be a little simpler and would get rid of the annoying conversion note:

 

numfiles=dnum(did);
call symputx('numfiles', numfiles);

 

Switching to CALL SYMPUTX performs the numeric to character conversion without a note, and automatically strips out any blanks caused by the conversion. 

Kurt_Bremser
Super User

Not using a run; is one of the little sins that people commit frequently, and that sometimes comes back and bites them in the behind.

Like the dot for macro variables, a run; (in the right place) is never wrong, and sometimes direly needed.

 

I have an inkling this will become Maxim 50.

LAYMAN_YO
Calcite | Level 5

Thank you very much for your help.

I should have added "run".

ShelleySessoms
Community Manager

@Kurt_Bremser@LAYMAN_YO@Astounding I have marked the correct solution. Thanks, all!

It's time to register for SAS Innovate! Join your SAS user peers in Las Vegas on April 16-19 2024.
Tom
Super User Tom
Super User

Why are you using the list of files found in one directory to then find the variable names in datasets from a SAS libref?  

If the libref is pointing to the same directory why not just query that metadata directly?

proc contents data=&libname.._all_ noprint out=contents; run;
proc sort data=contents;
 by memname varnum;
run;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 12 replies
  • 1585 views
  • 7 likes
  • 6 in conversation