/*-------------------------------------------------------------------\ | DDE: Normally, when we output to MS word, we will write to the most| | recent active word window, this is very easy to generate some | | errors when we have many word window open. Here is a trick to get | | avoid this problem: define the file path to be updated, use command| | to force SAS to output; | \-------------------------------------------------------------------*/ FILENAME _wsys_ dde "winword|Y:\CLINICAL\TACHY\BIOSTAT\Duo\Projects\VR-IDE\ Doc\VRIDE_report_draft 0.1 19Feb2002.doc" command lrecl=1048576; %fillup(oldbmark='PatIDImpUnVisit', indata=one, var=x, wordref=_wsys_); /*-------------------------------------------------------------------\ | Requesting more memory for interactive sessions | | xsas8 -memsize 128m & | \-------------------------------------------------------------------*/ /*-------------------------------------------------------------------\ | SAS Useful functions: | | 1) write numeric variables in word format; | | 2) just capitalize the first character of the sentence; | | 3) Capitalize the first character of each words in a setence; | | 4) replace a substring with another string: | | tranwrd (string, replace, with) | | 5) '09'x: tab (09 is hexadecimal values for '\t'); | | '0D'x: return sign (hexadecimal value for '\n'); | \-------------------------------------------------------------------*/ /* options ps=max ls=1 skip=min;*/ data one; infile datalines delimiter=',' dsd missover; /*delimiter='09'x for 'Tab' delimited data*/; input x y cpevent $21.; datalines; 1.1, 1.2, 'OneTwo', 12, 132, tHIS is AN EXAMPLE, 1.1, 2.3, 1 MONTH FOLLOW-UP, 2.1, 232, 4 MONTH FOLLOW-UP, 1.3, 4.1, 7 MONTH FOLLOW-UP, 4.2, 100, UNSCHEDULED FOLLOW-UP ; data two; set one; wordnum1=put(x, words30.); wordnum2=put(y, wordf30.); Up1low=upcase(substr(wordnum1,1,1))||lowcase(substr(wordnum1,2,(length(wordnum1)-1))); trstr=tranwrd(str,"'",'"'); drop x y str; run; %prt(two); /* Cocatenate a '\n' with the currecnt variable */ data two2; set one; length newcp $22. lastchar char $1.; lastchar=' '; newcp=' '; do i=1 to length(cpevent); char=substr(cpevent,i,1); if (lastchar=' ' or i=1) then do; char=upcase(char); newcp=compbl(newcp)||'0D'x||char; end; else do; char=lowcase(char); newcp=trim(left(newcp))||'0D'x||char; end; lastchar=char; end; cpevent=newcp; drop lastchar i char; run; %print(two2); /*-------------------------------------------------------------------\ | DDE Session: Close and Reopen a document when the memory is not | | enough; | \-------------------------------------------------------------------*/ data one; do x=1 to n; run; %sysexec 'C:\Program Files\Microsoft Office\Office\WINWORD.EXE'; data _null_; file wordsys; set one; format str $2000.; if mod(x, 3)=0 then do; str='[FileSaveAs .Name = "'||trim(left("D:\TEMP\temp.doc"))||'"]'; put str; put '[FileClose]'; str=sleep(2); call system('D:\TEMP\temp.doc'); str=sleep(2); str='[EditGoTo .Destination = "'||trim(left("t1"))||'"]'; put str; put '[TableSelectTable]'; put '[EndofLine]'; put '[TableSelectRow]'; put '[NextCell]'; end; str= '[Insert "'||trim(left(put(x, 3.)))||'"]'; put str; put '[NextCell]'; run; /*-------------------------------------------------------------------\ | 1). Input date values: | | '01jan1901'd; 01/01/1901 | | '17OCT1991:14:45:32'DT 32 seconds past 2:45 p.m., 17 October 1991| | '17OCT1991:12:5'DT 12:05 p.m., 17 October 1991 | | '17OCT1991:2:0'DT 2 AM, 17 October 1991 | | '17OCT1991:0:0'DT midnight, 17 October 1991 | | CAUTION: | | You can only compare equivalent literals against SAS date, time or | | datetime values since they each have a different unit of measure. | | For example, you cannot compare a SAS data set value that has been | | defined with a datetime format against a date literal using | | select * where hiredate = {d'1995-01-02'} | | / or | | select * where hiredate = '02jan1995'd | | Instead, use a datetime literal such as | | select * where hiredate = {ts'1995-01-02 00:00:00'} | | / or | | select * where hiredate = '02jan1995:00:00:00'dt | | | | 2). calculate the actual date, month or year difference; | | 3). Date format: mm/dd/yy -- mmddyy10.; | | mmddyy -- mmddyy6.; | | ddmonyyy -- date9.; | | time format: 14:45:32 -- time12.3.; | \-------------------------------------------------------------------*/ data three; start=mdy(1,3,1967); end=mdy(6,5, 2001); newdt='01jan1901'd; daysreal = datdif(start, end, 'actual'); /*'ACT/ACT' or 'ACTUAL' returns the actual number of days */ daysappr = datdif(start, end, '30/360'); /*'30/360' or '360' returns the number of days assuming a 30-day month and 360-day year */ yrsreal = yrdif(start, end, 'actual'); /*'ACT/ACT' or 'ACTUAL' returns the actual number of years */ mthsreal = yrsreal * 12; mthmanual=(end-start)/30.25; yrsappr = yrdif(start, end, 'act/365'); /*'ACT/365' returns the number of years as the actual number of days divided by 365*/ mthsappr = yrsappr * 12; /* a.. a numeric expression - interpreted as missing if it is ordinary missing (.) or contains special missing characters (._, .A to .Z) */ /* b.. a character expression - interpreted as missing if it contains all blank spaces */ if missing(var1) then do; /* perform corrective action when var1 missing;*/ end; run;%prt(data=three, var=mthsreal mthmanual); /********************************************************************/ /****************** User-Defined Character Classes ******************/ /*See: http://www.ncsu.edu/it/sas/help/lgref/z0331192.htm#zid-1554 */ /********************************************************************/ /*-------------------------------------------------------------------\ | 1) Select only the first and the last observations; | | | | 2) User-defined Character Classes | | If the character variable contains missing values of non-numeric | | data then the value of new_num will be missing. When the character | | variable contains non-numeric data, an 'invalid argument' note will| | be written to the log. This note can be suppressed using the ?? | | format modifier | | newc=input(b, ?? best4.); | | | | 3) Convert character variables to numeric variables when possible; | \-------------------------------------------------------------------*/ data t1; input a b $; cards; 01 A 02 b 03 c 04 d 05 -9 06 1 07 0 ; run; data t2; do i=1,n; set t1 point=i nobs=n; output; end; stop; run; %prt(t2); data temp; set t1; /** Change all quoted numeric to numeric values **/ if (rxmatch(rxparse("$d"),b)>0) then newb= b+0; /** exclude all quoted numeric values **/ if (rxmatch(rxparse("$a"),b)) then newchar=b; /** find only those which started with 1-9 numbers **/ if (rxmatch(rxparse("$d"),b)=1) then newb1=b+0; newc=input(b, ?? best4.); /* The following RXPARSE tells SAS to replace any uppercase */ /* letter with a space followed by that same letter. This will */ /* cause a leading space in the finished variable. */ if _n_=1 then rx=rxparse("<$u> TO ' ' =1"); /* The 5 in the RXCHANGE below represents the number of times we */ /* will make this change you may want to increase it....it is */ /* best not to OVER estimate by too much as it will have a */ /* negative effect on perfomance. */ call rxchange(rx,5,x); run; /* Test if a variable starts with ('Mc' 'Mac') */ data test; length y $20.; y='Mac test'; output; y='mac test'; output; y='start mactest'; output; y='start mac test'; output; run; data curt; set test END=eof; retain rx; if _n_=1 then rx=rxparse("` (mac|mc) [' ']$c*$w*"); match=rxmatch(rx,y); if(match>0) then put "Got a match, " y= match=; else put "Not a match, " y= match=; if eof then call rxfree(rx); run; %print(curt); /* Check the entire string to see if it consists of only integers */ data one; _seed_="&seed"; _seedchk_=rxparse("` ($d)$d*"); call rxsubstr(_seedchk_,_seed_,_seedpos_,_matchlen_,_score_); if (_matchlen_ < length(trimn(left(_seed_)))) then do; put '==> Alert! Please provide an integer seed!'; abort; end; call rxfree(_seedchk_); drop _seedchk_ _seedpos_ _matchlen_ _score_ _seed_; run; /*-------------------------------------------------------------------\ | 1) List the output of the procedure, and find out the name of the | | output dataset / datasets; | | 2) Output the dataset and change the name to temp1 | | 3) print a dataset withint a datastep; | | 4) User defined format; | | How to check the user defined formats; | | 5) How to change the length of a variable in a data set; | | 6) Usage of 'file print ods;' and 'put _ods_;'; | | 7) How to disregard user defined formats if these formats cannot be| | be found; | | 8) Mixed informats: characteristic and numeric together in one | | column; | \-------------------------------------------------------------------*/ ods trace on/listing; /* or ods trace on/label */ proc freq data=attest.covar; table rassign; ods output OneWayFreqs=temp1; run; ods trace off; %prt(temp1); options pagesize=60 linesize=64 nodate pageno=1; title 'Leading Grain Producers'; /* User Defined formats */ proc format; value $cntry 'BRZ'='Brazil' 'CHN'='China' 'IND'='India' 'INS'='Indonesia' 'USA'='United States'; value ridvstf 3='1 Month Follow-Up' 4='4 Month Follow-Up' 5='7 Month Follow-Up' 8='Unscheduled Follow-Up' other = 'Unknown'; run; /*How to disregard user defined formats if these formats cannot be */ libname winfd "T:\TACHY\BIOSTAT\Brady Programs\Unix\sara\4033\datasets"; options fmtsearch=(WINFD) NOFMTERR; /* How to check the user customized formats */ proc format library=work fmtlib; select @eval ridvstf; run; /* Mixed informats: characteristic and numeric together in one column; */ Proc format ; invalue mixed ‘LOW’ = -99 1-10 = 1 11-20 = 2 ‘BIG’ = 99 other = 0 ; Run ; data _null_; length Country $ 3 Type $ 5; input Year country $ type $ Kilotons; format country $cntry.; label type='Grain'; file print ods; put _ods_; datalines; 1995 BRZ Wheat 1516 1995 BRZ Rice 11236 1995 BRZ Corn 36276 1995 CHN Wheat 102207 1995 CHN Rice 185226 1995 CHN Corn 112331 1995 IND Wheat 63007 1995 IND Rice 122372 1995 IND Corn 9800 1995 INS Wheat . 1995 INS Rice 49860 1995 INS Corn 8223 1995 USA Wheat 59494 1995 USA Rice 7888 1995 USA Corn 187300 1996 BRZ Wheat 3302 1996 BRZ Rice 10035 1996 BRZ Corn 31975 1996 CHN Wheat 109000 1996 CHN Rice 190100 1996 CHN Corn 119350 1996 IND Wheat 62620 1996 IND Rice 120012 1996 IND Corn 8660 1996 INS Wheat . 1996 INS Rice 51165 1996 INS Corn 8925 1996 USA Wheat 62099 1996 USA Rice 7771 1996 USA Corn 236064 ; run; /*-------------------------------------------------------------------\ | How to read in multiple records from one line of observations | \-------------------------------------------------------------------*/ data one; VTVF_start=5; VTVF_end=8; INDUCED='NO'; run; data two; set one; do vtvfid=vtvf_start to vtvf_end; output; end; run;%prt(two); /*-------------------------------------------------------------------\ | How to read in plain text file | \-------------------------------------------------------------------*/ filename testdata 'testdata.txt'; data test; length recd $ 200 ; infile testdata missover; input @1 recd ; recd = upcase(recd); /*** convert to upper case ***/ recd=tranwrd( recd, '=' , ' ' ); /*** convert = to blanks ***/ recd=tranwrd( recd, '&' , ' ' ); /*** convert & to blanks ***/ recd=tranwrd( recd, 'Q1', ' ' ); /*** convert Q1 to blanks ***/ recd=tranwrd( recd, 'Q2', ' ' ); /*** convert Q2 to blanks ***/ recd=tranwrd( recd, 'Q3', ' ' ); /*** convert Q3 to blanks ***/ q1 = input( scan( recd, 1), best.); /*** get 1st word and input ***/ q2 = input( scan( recd, 2), best.); /*** get 2nd word and input ***/ q3 = input( scan( recd, 3), best.); /*** get 3rd word and input ***/ run; /*==================================================================*/ /* Create keys in a data step */ data serialinfo; set lots; set db2sys.disc_stat_history (dbkey=lot keep=lot trdate trtime resource) key=dbkey; run; /* concatenate */ %macro sqlconcat(indata=, var=, outvar=); %global &outvar; %local localv1 localv2; ods listing close; proc sql; select distinct &var into :localv1 separated by '", "' from &indata; select distinct &var into :localv2 separated by '", "0' from &indata; quit; %let localv1="&localv1"; %let localv2="0&localv2"; %let &outvar=(&localv1, "IJF200758S", "IJF200854S", "0IJF200758S", "0IJF200854S", &localv2); %put &outvar is &&&outvar; ods listing; %mend sqlconcat; %sqlconcat(indata=attest.pcsat500,var=serialno, outvar=allserial); /*-------------------------------------------------------------------\ | Create a Error Free Monitor dataset, if there is an error, you can | | delete this file, so that you can track the errors of your program.| \-------------------------------------------------------------------*/ DATA _ErrFree%EVAL(1*&SYSJOBID); RUN; %let crtldir=%SYSFUNC(PATHNAME(work)); filename crtlref "&crtldir.\_ErrFree%EVAL(1*&SYSJOBID).sas7bdat"; data one; crtl=fdelete('crtlref'); run; /*-------------------------------------------------------------------\ | 1) Search SAS files from a catalog; | | 2) Save 27% of time in regular sorting; | | 3) Combining a datastep and sql by utilizing sas views, which can | | save 40% of time; | \-------------------------------------------------------------------*/ /* Search SAS files from a catalog; */ %macro catscan(cat,file) ; proc build catalog=&cat batch ; print source prtfile="&file" ; run ; dm 'fslist "&file"' fslist ; %mend catscan ; /*Combining datastep and proc sql */ data out / view=out ; set sasuser.houses ; if style='CONDO' then put 'obs=' _n_ price= ; run ; proc sql ; create table more as select * from out where price > 100000; quit; /* Efficient Way of Sorting */ Data test/view=test; if … flag=1 ; run; Proc sort data=test; by flag; run; /*-------------------------------------------------------------------\ | make SAS print the current time and date, rather than the | | time and date when SAS was last started? | \-------------------------------------------------------------------*/ %put Current system time is %sysfunc(datetime(), datetime.).;