%macro readdir(indir=, outdsn=);
data &outdsn (keep=name infoname infoval);
rc=filename("mydir", "&indir");
did=dopen("mydir");
if did > 0 then do;
memcnt = dnum(did);
do i=1 to memcnt;
name = dread(did, i);
rc = filename("myfile", catx("/", "&indir", name));
fid = fopen("myfile");
if fid > 0 then do;
infonum=foptnum(fid);
do j=1 to infonum;
infoname=foptname(fid, j);
infoval=finfo(fid, infoname);
output;
end;
end;
else do;
msg = sysmsg();
put msg;
end;
rc = fclose(fid);
end;
end;
else do;
msg=sysmsg();
put msg;
end;
rc = dclose(did);
rc = filename("mydir");
run;
%mend;
%readdir(indir=C:\test, outdsn=out)
Showing posts with label tip. Show all posts
Showing posts with label tip. Show all posts
Tuesday, August 18, 2015
Listing all files that are located in a specific directory (update)
I prefer the codes independent on OS. It may save a lot of time to maintain. Based on SAS Note 25074, I have created the codes at below:
Monday, September 15, 2014
How to read CSV using PROC IMPORT
I believe you have read a lot paper for how to read CSV file. Here I want to add some helpful tips:
#1.
We can control the TERMSTR, ENCODING and LRECL using fileref, which may affect how PROC IMPORT handle the file.
For example, we can read UNIX format file in Win SAS.
#2.
CSV file may not be read correctly when null value is using two double-quote. To fix this, please set the macro variable EFI_NOQUOTED_DELIMITER as follows:
#3.
I always add the option GUESSINGROWS with maximum value to make sure all data are read. The option does not exist when I blog first CSV tip on 2009. :)
#1.
We can control the TERMSTR, ENCODING and LRECL using fileref, which may affect how PROC IMPORT handle the file.
For example, we can read UNIX format file in Win SAS.
filename in "&incsvfile" termstr=lf encoding=utf8 lrecl=32767;
proc cimport in=in out=work.test dbms=csv;
getnames = yes;
datarow = 2;
guessingrows = 2147483647;
run;
#2.
CSV file may not be read correctly when null value is using two double-quote. To fix this, please set the macro variable EFI_NOQUOTED_DELIMITER as follows:
%let EFI_NOQUOTED_DELIMITER = yes;
#3.
I always add the option GUESSINGROWS with maximum value to make sure all data are read. The option does not exist when I blog first CSV tip on 2009. :)
guessingrows = 2147483647;
Thursday, April 11, 2013
Calculating leap year
SAS support give out one way to identify leap year:
Sample 44233: Calculating leap year using PROC FCMP and user-defined function
Below is another simple method:
Sample 44233: Calculating leap year using PROC FCMP and user-defined function
Below is another simple method:
/* check if Febuary has 28 or 29 days in the year */ data _null_; do year = 1997 to 2005; days = datdif(mdy(2,1,year), mdy(3,1,year), 'act/act'); if days=29 then leap='Yes'; else leap='No'; put year= leap=; end; run;
Friday, February 25, 2011
Search at one click
I always search something as follows:
1. go to http://support.sas.com/
2. input keyword in blank search box, e.g. proc format
3. select Documentation in "Search support.sas.com"
4. Click search button
It becomes boring when I always do the same steps.
Here is a tip:
1. install CleverKeys for Windows at http://www.cleverkeys.com/ck.html?p=home&os=windows
2. Right click CleverKeys -> Preference -> Web links -> Add new link at below
Description: SAS Document
URL before: http://support.sas.com/dsearch?Find=Search&ct=5210&qt=
URL after: &col=suppprd&nh=10&qp=&qc=suppsas&ws=1&qm=1&st=1&lk=1&rf=0&oq=&rq=0
Of course, you can add any other useful search engines.
My favorite links are Wikipedia, Google and SAS Document.
Now you can search the SAS at one click. :)
1. go to http://support.sas.com/
2. input keyword in blank search box, e.g. proc format
3. select Documentation in "Search support.sas.com"
4. Click search button
It becomes boring when I always do the same steps.
Here is a tip:
1. install CleverKeys for Windows at http://www.cleverkeys.com/ck.html?p=home&os=windows
2. Right click CleverKeys -> Preference -> Web links -> Add new link at below
Description: SAS Document
URL before: http://support.sas.com/dsearch?Find=Search&ct=5210&qt=
URL after: &col=suppprd&nh=10&qp=&qc=suppsas&ws=1&qm=1&st=1&lk=1&rf=0&oq=&rq=0
Of course, you can add any other useful search engines.
My favorite links are Wikipedia, Google and SAS Document.
Now you can search the SAS at one click. :)
Thursday, April 1, 2010
Special permanent libraries: USER/LIBRARY
We all know that SAS has two kinds of library: permanent library and temporary WORK library. However, do you know that there are still two special permanent libraries?
USER:
When it exists, all datasets reference with a one level name will be written to the the permanent USER library instead of the temporary WORK library.
For the convenience of debugging, I suggest we can miss "WORK." when reference dataset.
Note: system option USER has the same effect.
LIBRARY:
In FMTSEARCH, there are ALWAYS two implicit format catalogs: WORK.FORMATS and LIBRARY.FORMATS. If they do not appear in FMTSEARCH= list, they will be searched at first.
USER:
When it exists, all datasets reference with a one level name will be written to the the permanent USER library instead of the temporary WORK library.
For the convenience of debugging, I suggest we can miss "WORK." when reference dataset.
Note: system option USER has the same effect.
LIBRARY:
In FMTSEARCH, there are ALWAYS two implicit format catalogs: WORK.FORMATS and LIBRARY.FORMATS. If they do not appear in FMTSEARCH= list, they will be searched at first.
Friday, March 19, 2010
Regex search in enhanced editor
Every one has its own habit.
I always edit text in Ultraedit. I like the Regex search/replace functionality in Ultraedit so much as I maintain a list of common Ultraedit-style Regex string.
I know that SAS enhanced editor must have this functionality. However, I got no information for Regex grammar from SAS online doc.
Today, I find the Regex magic box incidentally. :)
I always edit text in Ultraedit. I like the Regex search/replace functionality in Ultraedit so much as I maintain a list of common Ultraedit-style Regex string.
I know that SAS enhanced editor must have this functionality. However, I got no information for Regex grammar from SAS online doc.
Today, I find the Regex magic box incidentally. :)
Wednesday, March 17, 2010
NOTE: MERGE statement has more than one data set with repeats of BY values
First, the message reminds the user that it is MANY-to-MANY merge in DATA step.
Most SAS progammers are used to ONE-to-ONE or ONE-to-MANY merge since it is easy to understand. When MANY-to-MANY merge occur, the programmer should pay more attention on the data itself.
To perform MANY-to-MANY merge, there are two popular SAS techniques: DATA step and PROC SQL. It should be noted that PROC SQL do not issue the reminder message in MANY-to-MANY merge. Furthermore, it will create a different dataset with the result of DATA step.
Therefore, I suggest that we should perform merge using DATA step.
Most SAS progammers are used to ONE-to-ONE or ONE-to-MANY merge since it is easy to understand. When MANY-to-MANY merge occur, the programmer should pay more attention on the data itself.
To perform MANY-to-MANY merge, there are two popular SAS techniques: DATA step and PROC SQL. It should be noted that PROC SQL do not issue the reminder message in MANY-to-MANY merge. Furthermore, it will create a different dataset with the result of DATA step.
Therefore, I suggest that we should perform merge using DATA step.
Thursday, February 4, 2010
Scheduler for asynchronous script processing
As a IT programmer, we have to handle scripts on many platforms, e.g. DOS, ksh.
Due to limited functionality of script language, it is not easy to schedule many scripts to let them run step by step.
With SAS, we can take it easily.
I strongly recommended SAS programmer should use SYSTASK and WAITFOR to control the script processing.
By contrast, X is suitable for interactive task.
Below are codes from SAS online doc:
Due to limited functionality of script language, it is not easy to schedule many scripts to let them run step by step.
With SAS, we can take it easily.
I strongly recommended SAS programmer should use SYSTASK and WAITFOR to control the script processing.
By contrast, X is suitable for interactive task.
Below are codes from SAS online doc:
systask command "sas myprog1.sas" taskname=sas1;
systask command "sas myprog2.sas" taskname=sas2;
systask command "sas myprog3.sas" taskname=sas3;
waitfor _all_ sas1 sas2 sas3;
Thursday, November 5, 2009
Get nth value of a variable
It is another idea to get nth value of a variable.
proc sort data=sashelp.class out=tmp(keep=weight)
nodupkey;
by descending weight;
run;
data _null_;
set tmp end=end;
retain weight_10th .;
if _n_ <= 10 then do;
weight_10th = weight;
end;
if end then put "The 10th weight is " weight_10th=;
run;
Thursday, October 8, 2009
undocumented routine: CALL SOUND
I always keep an eye closely on SAS Samples, where I can get many interesting tips.
From this new sample, we can infer that CALL SOUND is another undocumented routine.
It will be a great way for reminder, not just in EG.
From this new sample, we can infer that CALL SOUND is another undocumented routine.
It will be a great way for reminder, not just in EG.
Monday, September 14, 2009
ANYDT* informats: Key to date/time values
Before SAS 9, we have to handle date/time values conditionaly if they are not in uniform style. Now, it becomes easy to input many different variations of date/time values using ANYDT* informats.
It is mainly used in PROC IMPORT, the Import Wizard, raw file input which have different styles of date/time values.
As to ANYDT* informats, notice the two points at below:
#1: There is no INVALID DATA message or set _ERROR_ to 1 if the input text cannot be interpreted. (SAS Note)
#2: A new system option DATESTYLE is introduced to determine the sequence of month, day, and year
It is mainly used in PROC IMPORT, the Import Wizard, raw file input which have different styles of date/time values.
As to ANYDT* informats, notice the two points at below:
#1: There is no INVALID DATA message or set _ERROR_ to 1 if the input text cannot be interpreted. (SAS Note)
#2: A new system option DATESTYLE is introduced to determine the sequence of month, day, and year
Thursday, September 10, 2009
Check variable exist in DATA step run time
First off, there is NO way to know exactly which variable exist in DATA step run time.
We can check the variable existence before DATA step run time. The popular method is Macro technology with File I/O functions or Dictionary table.
How to avoid creating this variable if it does not exist and to get the formatted value of the variable if it exist.
Here ia another way:
We can check the variable existence before DATA step run time. The popular method is Macro technology with File I/O functions or Dictionary table.
How to avoid creating this variable if it does not exist and to get the formatted value of the variable if it exist.
Here ia another way:
* Sample;
data dummy;
set sashelp.class (obs=0);
run;
data test;
set sashelp.class;
if _n_ = 1 then do;
drop varexist dsid rc;
retain varexist;
dsid = open('dummy');
varexist = varnum(dsid, "name");
rc = close(dsid);
end;
length tmp $ 20;
if varexist then do;
tmp = vvaluex("name");
end;
else tmp = '';
run;
Tuesday, August 11, 2009
What ODS templates are in use?
Generally, procedure output will use table template and style template.
Below are the methods to identify them:
#1:
ODS TRACE statement can print what table template is in use.
#2:
Default style information is in SAS registry.
command "regedit" -> ODS -> DESTINATION -> "Selected Style" entry in specified destination
Below are the methods to identify them:
#1:
ODS TRACE statement can print what table template is in use.
#2:
Default style information is in SAS registry.
command "regedit" -> ODS -> DESTINATION -> "Selected Style" entry in specified destination
Thursday, July 9, 2009
Close many VIEWTABLES at one time
In SAS DMS, I always view the dataset using Viewtable.
It is boring to close many viewtables before rerun the pgm.
I ever asked for help on comp.soft-sys.sas newsgroup. However, I am not satisfied with the answers.
Today, an idea rushed my mind. I have tried and believe it is a wonderful tip. :)
Here are the steps:
1. Define command style macro %closevts and save as closevts.sas
2. Update configuration file
-cmdmac
-set sasautos (
.......
macro-%closevts-path
)
3. Issue %closevts in command line
It is boring to close many viewtables before rerun the pgm.
I ever asked for help on comp.soft-sys.sas newsgroup. However, I am not satisfied with the answers.
Today, an idea rushed my mind. I have tried and believe it is a wonderful tip. :)
Here are the steps:
1. Define command style macro %closevts and save as closevts.sas
%macro closevts / cmd;
%local i;
%do i=1 %to 20;
next "viewtable:";end;
%end;
%mend;
2. Update configuration file
-cmdmac
-set sasautos (
.......
macro-%closevts-path
)
3. Issue %closevts in command line
Sunday, June 21, 2009
How to position the macro problem at runtime
Macro programming is error-prone. It is easy to debug the Macro compile error.
However, it is not intuitive to debug Macro runtime error since we can not get correct postion information from SAS log.
For example:
SAS log:
NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column).
1:51
Although SAS log give out the postion "1:51", we can not trace the issue in Macro.
Here is one key to the issue. We can save the Macro output as SAS program, position the issue in SAS program and track back to Macro.
Please see the sample code at below:
However, it is not intuitive to debug Macro runtime error since we can not get correct postion information from SAS log.
For example:
%macro test;
data a;
a=1;
b="1";
if a=b then put "Here!";
run;
%mend;
%test
SAS log:
NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column).
1:51
Although SAS log give out the postion "1:51", we can not trace the issue in Macro.
Here is one key to the issue. We can save the Macro output as SAS program, position the issue in SAS program and track back to Macro.
Please see the sample code at below:
filename mprint temp;
options mprint mfile;
%test
%include mprint / source2;
options nomprint nomfile;
filename mprint clear;
CSV with newline
In CSV, fields with embedded newline must be enclosed within double-quote characters.
However, PROC CIMPORT fail to import this kind of CSV.
To conform to the input standard, we can convert the embedded newline into " \par " (see RTF specification), import CSV in SAS dataset using PROC CIMPORT and then convert " \par " back to newline.
However, PROC CIMPORT fail to import this kind of CSV.
To conform to the input standard, we can convert the embedded newline into " \par " (see RTF specification), import CSV in SAS dataset using PROC CIMPORT and then convert " \par " back to newline.
Sunday, May 24, 2009
Truncate issue when importing CSV file
CSV file is an old common format of information distribution. However, when we read CSV into SAS dataset using PROC IMPORT, the string is truncated sometimes.
The reason is that PROC IMPORT scan only 20 records by default to determine variable attributes. SAS Notes has detailed the steps to solve the issue.
For more information, please see http://support.sas.com/kb/1/075.html.
The reason is that PROC IMPORT scan only 20 records by default to determine variable attributes. SAS Notes has detailed the steps to solve the issue.
For more information, please see http://support.sas.com/kb/1/075.html.
*Sample code to read CSV;
PROC IMPORT OUT= WORK.DATA
DATAFILE= "csv.txt"
DBMS=DLM REPLACE;
DELIMITER='2C'x;
GETNAMES=YES;
DATAROW=2;
RUN;
Monday, March 30, 2009
Wonderful paper: Don't Be a SAS Dinosaur
As a SAS programmer, I strongly recommend that you should read this paper.
Warren Repole has summarized many SAS tips systematically.
For more information, please read http://www.repole.com/dinosaur/.
Warren Repole has summarized many SAS tips systematically.
For more information, please read http://www.repole.com/dinosaur/.
Monday, March 16, 2009
LOCF by using only PROC SORT
LOCF is short for Last Observation Carried Forward. It is a common method in longitudinal studies. And there are many ways to handle this. Here is one tip of using NODUPKEY option.
/* Classical way */
proc sort data=inds;
by subjid DESCENDING visitnum;
run;
data locf;
set inds (where=(visitnum <=3));
by subjid visitnum;
retain base;
if first.subjid then base=.;
if not missing(value) then base=value;
if last.subjid;
run;
/* Use NODUPKEY option in PROC SORT. */
proc sort data=inds;
by subjid DESCENDING visitnum;
run;
proc sort data=inds(where=(visitnum <=3 and not missing(value))) out=locf NODUPKEY;
by subjid;
run;
Thursday, March 12, 2009
Useful keyboard macros
As a programmer, I always use Ultraedit and VI as editor. So I am familiar with the keyboard shortcut in Ultraedit and VI. After immigrating some useful shortcuts into SAS enhanced editor using keyboard macros, my coding efficiency has been improved dramatically.
It should be noted to avoid shortcut conflict with old ones before assign new shortcut key.
Here are two useful keyboard macros:
Mark matching DO/END:
* Move cursor to matching DO/END keyword
* Mark the current line
* Move cursor to matching DO/END keyword
* Mark the current line
* Move cursor to matching DO/END keyword
Unmark matching DO/END:
* Move cursor to matching DO/END keyword
* Unmark the current line
* Move cursor to matching DO/END keyword
* Unmark the current line
* Move cursor to matching DO/END keyword
Below is a paper for keyboard macros in SAS enhanced editor.
http://www.sascommunity.org/wiki/Tip:_Useful_Enhanced_Editor_macros
It should be noted to avoid shortcut conflict with old ones before assign new shortcut key.
Here are two useful keyboard macros:
Mark matching DO/END:
* Move cursor to matching DO/END keyword
* Mark the current line
* Move cursor to matching DO/END keyword
* Mark the current line
* Move cursor to matching DO/END keyword
Unmark matching DO/END:
* Move cursor to matching DO/END keyword
* Unmark the current line
* Move cursor to matching DO/END keyword
* Unmark the current line
* Move cursor to matching DO/END keyword
Below is a paper for keyboard macros in SAS enhanced editor.
http://www.sascommunity.org/wiki/Tip:_Useful_Enhanced_Editor_macros
Subscribe to:
Posts (Atom)