SAS names with prefix not working - sas

I was trying to get all of the fname variables with the prefix TIME_INTERVAL. However, it seems that the following put statement outputs nothing. I was wondering what is the reason?
%LET TIME_INTERVAL='MINUTE15';
data _null_;
set filenames;
by fname;
if fname =: "&TIME_INTERVAL";
put fname;
run;
If I put the put statement above the if statement, however, it can output correctly:
%LET TIME_INTERVAL='MINUTE15';
data _null_;
set filenames;
by fname;
put fname;
if fname =: "&TIME_INTERVAL";
run;
Update:
The content of the dataset filenames:
MINUTE15_group0.csv
MINUTE15_group1.csv
MINUTE15_group2.csv
MINUTE15_group3.csv
MINUTE15_group4.csv
MINUTE15_group5.csv
MINUTE15_group6.csv
MINUTE15_group7.csv
MINUTE15_group8.csv
MINUTE5_group0.csv
MINUTE5_group1.csv
MINUTE5_group2.csv
MINUTE5_group3.csv
MINUTE5_group4.csv
MINUTE5_group5.csv
MINUTE5_group6.csv
MINUTE5_group7.csv
MINUTE5_group8.csv
SECOND5_group0.csv
SECOND5_group1.csv
SECOND5_group2.csv
SECOND5_group3.csv
SECOND5_group4.csv
SECOND5_group5.csv
SECOND5_group6.csv
SECOND5_group7.csv
SECOND5_group8.csv

You asked SAS to look for filenames that start with 'MINUTE15', but I think that you actually wanted to look for filenames that start with MINUTE15 instead.
Everything is a string to the macro processor so there is no need to add quotes around constant text in macro code. If you add them they become part of the code that is being generated and passed to SAS to run. So your program generated this IF statement.
if fname =: "'MINUTE15'";
You could remove the single quotes.
%LET TIME_INTERVAL=MINUTE15;
data _null_;
set filenames;
if fname =: "&TIME_INTERVAL";
put fname;
run;
Or remove the double quotes.
%LET TIME_INTERVAL='MINUTE15';
data _null_;
set filenames;
if fname =: &TIME_INTERVAL;
put fname;
run;

Related

set a dataset by dereferencing a variable

I would like to set a dataset by using a reference to dataset name however Iam getting error message: ERROR: File dataset_name123 does not exist(work.dataset123 does exist) What is wrong?
data _null_;
%let product = 'dataset_name123';
set work.&product nobs = row_no;
put row_no;
put &product;
run;
Member names are not quoted. Remove the quotes from your macro variable. In macro code everything is character so there is no need to add quotes around string literals. The quotes become part of the value of the macro variable.
%let product = dataset_name123;
%put &=product;
data _null_;
set work.&product nobs = row_no;
put row_no;
put "&product";
stop;
run;
If you do include quotes in a dataset reference then SAS will interpret it as the physical name of the dataset file itself. So code like:
data want;
set 'dataset_name123';
run;
would look for a filename 'dataset_name123.sas7bdat' in the current working directory.
It is not a great idea to do a %let statement in a data step. Macrovariables and SAS variables are created differently.
There are two problems in this code. First one is quotes around macrovariable, which after resolution will be used for table name and hence your query fails as table names cannot be in quotes .
second one is put statement for macro variable for macro variable to resolve you need %put.
below is modified code.
data class;
set sashelp.class;
run;
data _null_;
%let product = class;
set work.&product nobs = row_no;
put row_no;
%put &product;
run;

Append string to text file in SAS

I wanna append string to a text file at beginning and end of proc sql statment, I tried like below
libname DXZ 'libpath';
%macro processlogger(msg);
filename logfile '../Processlog/processlog.txt';
data _null_;
file logfile;
put "%superq(message)";
run;
%mend;
%processlogger ('Begin');
proc sql;
select * from DZ.NoofDaysin_Reje /* Mispelled name */
run;
%processlogger('End');
I seems to messing up in macro variable, is there any other way I can do this, Thanks
If you want to use a data step to append to a text file then you need to add the MOD keyword to the FILE statement.
If you want to print the value of a macro variable that might have quotes and other strange characters in a data step then it is probably best to use symget() to retrieve the value into a datastep variable and print that.
Make sure to reference the macro variable that you created msg and not some other macro variable message.
If you don't want quotes to be included in the value of a macro variable then do not add them.
%macro processlogger(msg);
data _null_;
file '../Processlog/processlog.txt' mod;
length message $32767 ;
message=symget('msg');
put message ;
run;
%mend;
%processlogger(Starting at %sysfunc(datetime(),datetime24.3));
%processlogger(Ending at %sysfunc(datetime(),datetime24.3));
You can also use PRINTTO to redirect your log to a text file. And you have the option to either append to the original file or replace. Example here.
/*Redirect your log file*/
proc printto log='../Processlog/processlog.txt';
run;
/* Your Code Here */
/* Reset log path to default */
proc printto;
run;

ERROR: No logical assign for filename FNAME

I was running the following code:
%LET TIME_INTERVAL='MINUTE15';
/*
* Get the file names of a specific location
*/
%MACRO get_filenames(location,filenames);
filename _dir_ "%bquote(&location.)";
data &filenames(keep=fname);
handle=dopen( '_dir_' );
if handle > 0 then do;
count=dnum(handle);
do i=1 to count;
fname=dread(handle,i);
output &filenames;
end;
end;
rc=dclose(handle);
run;
filename _dir_ clear;
%MEND;
%MACRO NBBO (fname);
DATA TICKERS_NBBO;
INFILE &fname;
INPUT SYMBOL $;
RUN;
%mend;
%MACRO CALCU(DATE_VAR);
%get_filenames('./groups',filenames);
data _null_;
set filenames;
by fname;
if fname =: "&TIME_INTERVAL";
%NBBO(fname);
run;
%mend;
However, I got the error: ERROR: No logical assign for filename FNAME.
I was wondering what is the reason that caused this?
There are lots of csv files in the folder groups. I was trying to run the NBBO macro on each of the files and load each of the files into a dataset with infile statement.
You're mixing up data step code and macro code in a manner that's not permitted. You can't extract the contents of the variable fname and use it to populate a macro variable in this way. Instead you're passing the text fname to that macro variable, which then doesn't work.
You also can't run another data step inside a data step in this manner. You need to use one of the various methods for executing it after the data step terminates or during execution.
Finally, it's entirely unclear to me what you're really doing here: because you're going to end up with just one of those files in the dataset.
I think you may want something like this, which is much easier. I use the FILEVAR option in infile, which uses the value of a variable; I have to make some changes to how you calculate fname (I think you have to do this anyway, it has no directory name in it).
%MACRO get_filenames(location,filenames);
filename _dir_ "%bquote(&location.)";
data &filenames(keep=fname);
length fname $512;
handle=dopen( '_dir_' );
if handle > 0 then do;
count=dnum(handle);
do i=1 to count;
fname=catx('\',"%bquote(&location.)",dread(handle,i));
output &filenames;
end;
end;
rc=dclose(handle);
run;
filename _dir_ clear;
%MEND;
%get_filenames(location=c:\temp\cars, filenames=fnam);
data tickers_nbbo;
set fnam;
infile a filevar=fname dlm=',';
input symbol $;
run;
If you really do need to call a data step separately, you either need to use CALL EXECUTE, DOSUBL, or construct macro calls in another way (PROC SQL SELECT INTO, %INCLUDE, etc.).

Specifying file name as a variable in the infile statement

I am tying to convert a comma delimited text file to a pipe delimited file but my input file name (comma delimited file) is a variable (flname1). I am using the code below suggested by a stackoverflow member. The code works fine as long as I specify the file name in the infile statement but I don't know how to specify file name as a variable-
data _null_;
enddate=date();
flname1=compress("d:\temp\wq_" || year(enddate) || put(month(enddate),z2.) || ".txt");
length x1-x6 $200;
infile 'flname1' dsd dlm=',' truncover;
file 'C:\temp\pipe.txt' dsd dlm='|';
input x1-x6;
put x1-x6;
run;
I am new to SAS and any help will be greatly appreciated. Thank you!
You should be able to use the filevar option in the infile statement, e.g.:
data _null_;
enddate=date();
flname1=compress("d:\temp\wq_"||year(enddate)||put(month(enddate),z2.)||".txt");
length x1-x6 $200;
infile myinputfile dsd dlm=',' filevar=flname1 truncover;
file 'C:\temp\pipe.txt' dsd dlm='|';
input x1-x6;
put x1-x6;
run;
The documentation explains more about the option and has an example of its use in Example 5.
You probably want to actually do this as a macro variable - this isn't a normal usage of filevar (which you'd use if you had a dataset with a bunch of filenames in it or something).
%let filename = d:\temp\wq_%sysfunc(today(),YYMMN6.).txt;
%put &=filename;
data _null_;
length x1-x6 $200;
infile "&filename." dsd dlm=',' truncover;
file 'C:\temp\pipe.txt' dsd dlm='|';
input x1-x6;
put x1-x6;
run;
Macro variables are just text substitutions, so they can be used wherever you could type the same thing in. They also don't need concatenating functions - any more than you have to concatenate when you type a word in - so it's easier to do.
Here, I use %sysfunc to tell SAS to execute the today() function, and the second argument tells it how to format it - YYMMN6. is the format you look like you want (201506 or similar). Then just make sure to use " quotes not ' quotes as the latter doesn't let the macro variable resolve.

Exporting to a text file in SAS with a double delimitter

I'm trying to use a double pipe delimiter "||" when I export a file from SAS to txt. Unfortunately, it only seems to correctly delimit the header row and uses the single version for the data.
The code is:
proc export data=notes3 outfile='/file_location/notes3.txt'
dbms = dlm;
delimiter = '||';
run;
Which results in:
ID||VAR1||VAR2
1|0|STRING1
2|1|STRING2
3|1|STRING3
If you want to use a two character delimiter, you need to use dlmstr instead of dlm in the file statement in data step file creation. You can't use proc export, unfortunately, as that doesn't support dlmstr.
You can create your own proc export fairly easily, by using dictionary.columns or sashelp.vcolumn to construct the put statement. Feel free to ask more specific questions on that side if you need help with it, but search around for data driven output and you'll most likely find what you need.
The reason proc export won't use a double pipe is because it generates a data step to do the export, which uses a file statement. This is a known limitation - quoting the help file:
Restriction: Even though a character string or character variable is
accepted, only the first character of the string or variable is used
as the output delimiter. This differs from INFILE DELIMITER=
processing.
The header row || works because SAS constructs it as a string constant rather than using a file statement.
So I don't think you can fix the proc export code, but here's a quick and dirty data step that will transform the output into the desired format, provided that your dataset has no missing values and doesn't contain any pipe characters:
/*Export as before to temporary file, using non-printing TAB character as delimiter*/
proc export
data=sashelp.class
outfile="%sysfunc(pathname(work))\temp.txt"
dbms = dlm;
delimiter = '09'x;
run;
/*Replace TAB with double pipe for all rows beyond the 1st*/
data _null_;
infile "%sysfunc(pathname(work))\temp.txt" lrecl = 32767;
file "%sysfunc(pathname(work))\class.txt";
input;
length text $32767;
text = _infile_;
if _n_ > 1 then text = tranwrd(text,'09'x,'||');
put text;
run;
/*View the resulting file in the log*/
data _null_;
infile "%sysfunc(pathname(work))\class.txt";
input;
put _infile_;
run;
As Joe suggested, you could alternatively write your own delimiter logic in a dynamically generated data step, e.g.
/*More efficient option - write your own delimiter logic in a data step*/
proc sql noprint;
select name into :VNAMES separated by ','
from sashelp.vcolumn
where libname = "SASHELP" and memname = "CLASS";
quit;
data _null_;
file "%sysfunc(pathname(work))\class.txt";
set sashelp.class;
length text $32767;
text = catx('||',&VNAMES);
put text;
run;