You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

752 lines
30 KiB
Plaintext

*! saswrapper Version 1.1 dan.blanchette@duke.edu 08Jul2009
*! Center for Entrepreneurship and Innovation Duke University's Fuqua School of Business
* -removed stray carriage return characters
* saswrapper Version 1.1 dan.blanchette@duke.edu 04May2009
* -made it fail more gracefully when usesas option specified and sas code had an error in it
* saswrapper Version 1.0 dan.blanchette@duke.edu 26Feb2009
program define saswrapper, rclass
version 8
syntax [varlist] [using/ ] [if] [in] [, PRE_sas_prog(string) POST_sas_prog(string) MEssy savasas(string) ///
usesas NODATA clear QUotes CHeck float char2lab NOFORMATS rename ]
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , start type(savas) message(`"saswrapper using `using', `messy' `savasas' `usesas' `nodata' `clear' `quotes' `check' `float' `char2lab' `noformats' `rename' "')
}
if "`c(os)'" == "Windows" & "`c(mode)'" == "batch" {
di as err "{help saswrapper:saswrapper} cannot be run in batch mode on Windows"
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(8) etime
}
exit 499
}
if `c(N)' == 0 & `"`savasas'"' != "" {
di as err "no data in memory to save to SAS" _n
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(8) etime
}
exit 499
}
if "`nodata'" != "" & `"`savasas'"' != "" {
di as err "cannot specify both nodata and savasas" _n
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(8) etime
}
exit 499
}
if `c(N)' == 0 & "`nodata'" == "" {
local nodata = "nodata"
}
if `"`usesas'"' != "" & `c(N)' != 0 & "`clear'" == "" {
di "{error} no, data in memory would be lost "
di "{error} use the {res}clear {error}option"
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(1) etime
}
exit 4
}
local formats = "formats"
if "`noformats'" != "" {
local formats = ""
}
* CAPTURE USER'S LOG
* ------------------
quietly log query
local usrlog `r(filename)'
* FIGURE OUT WHERE THE SAS EXECUTABLE IS
* --------------------------------------
sasexe saswrapper
local wsas `r(wsas)'
local usas `r(usas)'
local savastata `r(savastata)'
local char2fmt `r(char2fmt)'
local rver `r(rver)' // version of sas that's being run i.e. "v8", "v9" etc
local dirsep = "`c(dirsep)'"
if "`c(os)'" == "Windows" {
local dirsep = "\"
}
local dir = "`c(pwd)'`dirsep'"
if `"`using'"' != "" {
// see if there is even one double quote in using
local subtest : subinstr local using `"""' `""' , count(local cnt)
if `cnt' != 0 {
di `"{help saswrapper:saswrapper} {error}cannot handle directory or file names that contain double quotes. "'
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(2) etime
}
exit 499
}
/* if filename is given with directory info too,
* strip to just file name and to dir location */
if "`c(os)'" == "Windows" {
if index("`using'","/") {
local using : subinstr local using "/" "\" , all
}
}
if index("`using'","`dirsep'") {
local filen=substr("`using'",index("`using'","`dirsep'")+1,length("`using'"))
while index("`filen'","`dirsep'") !=0 {
local filen = substr("`filen'",index("`filen'","`dirsep'")+1,length("`filen'"))
}
local dir = substr("`using'",1,index("`using'","`filen'")-1)
}
else if index("`using'","\\\") == 1 { /* Universal naming convention */
local filen = substr("`using'",index("`using'","\\\")+2,length("`using'"))
while index("`filen'","\") !=0 {
local filen = substr("`filen'",index("`filen'","\")+1,length("`filen'"))
}
local dir = substr("`using'",1,index("`using'","`filen'")-1)
}
else { /* no directory given */
local filen = "`using'"
local dir = "`c(pwd)'`dirsep'"
}
/** extract file extension if there is one **/
if index("`filen'",".") {
local ext=substr("`filen'",index("`filen'","."),length("`filen'"))
while index("`ext'",".") > 0 {
local ext = substr("`ext'",index("`ext'",".")+1,length("`ext'"))
}
local ext = ".`ext'"
local filen = substr("`filen'",1,index("`filen'",".")-1)
}
if lower("`ext'") == "" { // guess that the user is wanting to use a .sas file
local using1 `"`using'.sas"'
local ext ".sas"
capture confirm file `"`using1'"'
if _rc == 0 {
capture confirm file `"`using'"'
if _rc == 0 {
di `"{error}The SAS file: "`using'" does exist, but so does the SAS file: "`using1'" '"'
di as text `"SAS will choose to run "`using1'" since it has the file extension ".sas" "'
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(3) etime
}
exit 601
}
}
// only here if this file does exist
local using `"`using'.sas"'
}
else if lower("`ext'") != ".sas" {
di as error `" "`ext'" is an invalid file extension "'
di as error `"{help saswrapper:saswrapper} can only run SAS program files which have the file extension ".sas" "'
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(3) etime
}
exit 601
}
capture confirm file `"`using'"'
if _rc != 0 {
di `"{error}The SAS file: `using' does not exist."'
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(3) etime
}
exit 601
}
} // end of if "using" != ""
local usasprog "`using'"
if "`usasprog'" == "" & `"`pre_sas_prog'"' == "" & `"`post_sas_prog'"' == "" {
di as err `"no SAS code to run "' _n
/* log usage of saswrapper */
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(3) etime
}
exit 601
}
/* set where temp directory is */
tmpdir
local tmpdir `"`r(tmpdir)'"'
local tfn = subinstr("`c(current_time)'",":","",.)
local sysjobid = substr("`tfn'",length("`tfn'")-5,length("`tfn'"))
local temp `"`macval(tmpdir)'_`sysjobid'"'
if "`nodata'" == "" {
if `"`savasas'"' == "" {
local stata_data `"`c(filename)'"'
if `: length local stata_data' != 0 {
capture _getfilename `"`stata_data'"' // get error message if only dir in using
local stata_data `"`r(filename)'"' // make using just the filename
local stata_data : subinstr local stata_data ".dta" "" // drop file extension
valid_dset_name, dset(`stata_data') `rename'
local stata_data = "`r(valid_dset_name)'"
}
else if `: length local stata_data' == 0 {
local stata_data = "stata_data"
}
}
else if `"`savasas'"' != "" {
valid_dset_name, dset(`savasas') `rename'
local stata_data = "`r(valid_dset_name)'"
}
if "`stata_data'" == "" local stata_data = "stata_data"
if "`check'" != "" {
di as result _n `"Compare results with SAS output that will be printed next "'
// no reason to set more off because if user quits no temp files have been written yet
local five_n = 5
if _N < 5 {
local five_n = _N
}
summarize `varlist' `if' `in'
describe `varlist'
list `varlist' in 1/`five_n'
}
di as result _n "now running {help savasas:savasas} to save the dataset `stata_data' to the SAS WORK library "
savasas `varlist' using "`temp'_statadata.sas7bdat" `if' `in' , `formats' `rename' `messy' ///
saswrapper saswrap_data(`stata_data') sysjobid(`sysjobid')
}
* WRITE SASWPAPPER SAS PROGRAM
* ----------------------------
saswrapper_sas , dirsep("`dirsep'") dir("`dir'") tmpdir("`tmpdir'") temp("`temp'") filen(`filen') sysjobid(`sysjobid') ///
usasprog("`usasprog'") pre_sas_prog(`" `pre_sas_prog' "') post_sas_prog(`" `post_sas_prog' "') ///
rver(`rver') savastata("`savastata'") `quotes' `check' `float' `char2lab' char2fmt("`char2fmt'") ///
stata_data(`stata_data') `usesas' `nodata'
* RUN SAS
* -------
if "`c(os)'" == "Unix" /* or Linux */ {
shell "`usas'" "`temp'_saswrapper.sas" -log "`temp'_saswrapper.log" -print "`temp'_saswrapper.lst"
} /* end of if Unix */
else if "`c(os)'" == "Windows" /* Windows */ {
shell `wsas' "`temp'_saswrapper.sas" -nologo -log "`temp'_saswrapper.log" -print "`temp'_saswrapper.lst"
} /* end of if Windows */
capture confirm file `"`temp'_sascoderr.sas7bdat"'
if _rc == 0 {
tempfile saswrapper_output
copy `"`temp'_saswrapper.txt"' `"`saswrapper_output'"', text
capture confirm file `"`saswrapper_output'"'
if _rc == 0 {
di as error _n "the submitted SAS code has an error in it " _n
}
// set usesas to missing so that saswrapper will fail gracefully
local usesas
}
* LOOK AT ANY REPORT FROM SAS
* ---------------------------
capture confirm file `"`temp'_report.log"'
if _rc == 0 {
type `"`temp'_report.log"'
if "`messy'" == "" {
erase `"`temp'_report.log"'
}
}
if "`usesas'" != "" {
* CLEAR DATA OUT OF MEMORY
* ------------------------
if "`clear'" != "" {
drop _all
label drop _all
}
* LOAD STATA DATASET INTO MEMORY
* ------------------------------
capture confirm file `"`temp'_infile.do"'
if _rc == 0 {
di as result _n "now loading the most recently created SAS dataset in submitted SAS program "
di as result " savastata SAS macro saved this dataset to Stata " _n
if `"`usrlog'"' != "" {
quietly log close
}
local cwd "`c(pwd)'"
** cd to where infile.do is **
quietly cd "`tmpdir'"
run `"_`sysjobid'_infile.do"'
if `"`usrlog'"' != "" {
quietly log using `"`usrlog'"' , append
}
* SET DATASET NAME
* ----------------
if index("$S_FN","`dirsep'") == 1 {
global S_FN : subinstr global S_FN "`dirsep'" ""
}
global S_FN `"`macval(dir)'$S_FN"'
// run savastata_report to see if SAS and Stata agree how many obs and vars there are
savastata_report
di " " _n // insert a blank space
** cd back to where you were **
quietly cd "`cwd'"
} /* if infile.do file exists */
else {
di `"{error}{help saswrapper:saswrapper} failed."'
capture confirm file `"`temp'_knerror.txt"'
if _rc == 0 {
// savastata failed with a known error so just let report.log show the error
if "`c(os)'" != "Windows" {
usesasdel `"`tmpdir'"' _`sysjobid'
}
if "`c(os)'" == "Windows" {
local usesasdeldir : subinstr local tmpdir `":"' `"\\\`= char(58)'"', all
usesasdel `"`usesasdeldir'"' _`sysjobid'
}
}
else {
di `"{error}If no error message above this one, then check out the SAS log file to see why. "'
di `" {view "`temp'_saswrapper.log"} "'
di `" and {view "`temp'_saswrapper.txt"} "'
di `"{inp}Erase these temporary files created by {help saswrapper:saswrapper} when done with them:"'
di `"{res}(files located in "`tmpdir'") "'
ls "`temp'_*"
if "`c(console)'" != "console" {
if "`c(os)'" != "Windows" {
di `"{res} {stata usesasdel `"`tmpdir'"' _`sysjobid':Click here to erase them all.} "'
}
if "`c(os)'" == "Windows" {
local usesasdeldir : subinstr local tmpdir `":"' `"\\\`= char(58)'"', all
di `"{res} {stata usesasdel `"`usesasdeldir'"' _`sysjobid':Click here to erase them all.} "'
}
}
}
if "`usasprog'" != "" {
di `""'
if "`c(console)'" != "console" {
di `"{inp}Click here to edit your SAS program and try it again. "'
di `" {stata `"doedit "`usasprog'""':`usasprog'} "'
}
else di `"Edit your SAS program: "`usasprog'" and try it again."' _n
}
capture which usagelog
if _rc == 0 {
usagelog , type(savas) uerror(6) etime
}
exit 499
}
} //end of if usesas
capture confirm file `"`temp'_saswrapper.txt"'
if _rc == 0 {
tempfile saswrapper_output
copy `"`temp'_saswrapper.txt"' `"`saswrapper_output'"', text
}
* CLEAN UP TEMP FILES
* -------------------
if "`messy'"=="" {
if "`c(os)'" != "Windows" {
usesasdel `"`tmpdir'"' _`sysjobid'
}
if "`c(os)'" == "Windows" {
local usesasdeldir : subinstr local tmpdir `":"' `"\\\`= char(58)'"', all
usesasdel `"`usesasdeldir'"' _`sysjobid'
}
} /* end of messy */
else {
di "{res}You have requested {help saswrapper:saswrapper} not to delete the intermediary files" ///
" created by {help saswrapper:saswrapper}:"
dir "`temp'_*"
di "{input}Files located here: "
di `"{input}"`tmpdir'" "'
if "`c(console)'" != "console" {
if "`c(os)'" != "Windows" {
di `"{res} {stata usesasdel `"`tmpdir'"' _`sysjobid':Click here to erase them all.} "'
}
if "`c(os)'" == "Windows" {
local usesasdeldir : subinstr local tmpdir `":"' `"\\\`= char(58)'"', all
di `"{res} {stata usesasdel `"`usesasdeldir'"' _`sysjobid':Click here to erase them all.} "'
}
}
} // of if else if messy
// this is 2nd to last since user may break -more- which cancels saswrapper
capture confirm file `"`saswrapper_output'"'
if _rc == 0 {
di as result "the following is the results of the SAS program: " _n
type `"`saswrapper_output'"'
}
// this is last since user may break -more- which cancels saswrapper
if "`usesas'" != "" {
if "`check'" != "" {
local gsfn : subinstr global S_FN ".dta" ""
display as res _n " Compare these results with the results provided by SAS "
display as res " in the file `gsfn'_SAScheck.lst. " _n
local five_n = 5
if _N < 5 {
local five_n = _N
}
summarize
describe
list in 1/`five_n'
di _n "You have requested to have savastata provide a check file:"
di `""`gsfn'_SAScheck.lst" "' _n
}
}
end /* end of saswrapper */
program define saswrapper_sas, nclass
syntax [, dirsep(string) dir(string) tmpdir(string) temp(string) filen(string) sysjobid(string) ///
usasprog(string) pre_sas_prog(string) post_sas_prog(string) ///
rver(string) savastata(string) quotes check float char2lab char2fmt(string) ///
stata_data(string) usesas NODATA]
version 8
quietly {
file open sasfile using `"`temp'_saswrapper.sas"', replace text write
file write sasfile `"* saswrapper SAS program *; "' _n _n ///
`" options nonotes nofmterr nocenter linesize=`c(linesize)' source2;"' _n _n ///
`" ** need to create this file now as may only be able to *"' _n ///
`" * erase it later. **; "' _n ///
`" libname _saswrap "`tmpdir'"; "'
file write sasfile `"* sas error test *; "' _n _n ///
`" data _saswrap._`sysjobid'_sascoderr; "' _n ///
`" do i = 1 to 1; "' _n ///
`" message="submitted SAS code has an error"; "' _n ///
`" end; "' _n ///
`" run; "' _n ///
`" %let syslast=; "' _n
if "`stata_data'" != "" { // put data (and formats catalog file) into WORK library
capture confirm file `"`temp'_statadata.sas7bdat"'
if _rc == 0 {
file write sasfile `" proc datasets library= _saswrap; "' _n ///
`" copy in= _saswrap out= work move; "' _n ///
`" select _`sysjobid'_statadata (memtype= data); "' _n ///
`" run; "' _n _n
file write sasfile `" proc datasets library= work; "' _n ///
`" change _`sysjobid'_statadata = `stata_data' / memtype= data; "' _n ///
`" run; "' _n ///
`" quit; "' _n _n ///
`" %let syslast=work.`stata_data'; "' _n _n
}
capture confirm file `"`temp'_statadata.sas7bcat"'
if _rc == 0 {
file write sasfile `" proc datasets library= _saswrap; "' _n ///
`" copy in= _saswrap out= work move; "' _n ///
`" select _`sysjobid'_statadata (memtype= catalog); "' _n ///
`" run; "' _n _n
file write sasfile `" proc datasets library= work; "' _n ///
`" change _`sysjobid'_statadata = formats / memtype= catalog; "' _n ///
`" run; "' _n ///
`" quit; "' _n _n
}
}
file write sasfile `" proc printto print="`temp'_saswrapper.txt" log="`temp'_saswrapper.txt"; "' _n ///
`" run; "' _n _n ///
`" options notes; "' _n _n
if "`check'" != "" & "`nodata'" == "" {
file write sasfile `" "' _n ///
`" /****** THE FOLLOWING IS THE DATA CHECK YOU REQUESTED ******/ "' _n
file write sasfile `" "' _n ///
`" proc means data=work.`stata_data'; "' _n ///
`" run; "' _n _n ///
`" proc contents data=work.`stata_data'; "' _n ///
`" run; "' _n _n ///
`" proc print data=work.`stata_data' (obs=5); "' _n ///
`" run; "' _n
file write sasfile `" "' _n ///
`" /************ END OF THE DATA CHECK YOU REQUESTED **********/ "' _n
}
if `"`pre_sas_prog'"' != " " { // two spaces because pre_sas_prog(`" `pre_sas_prog' "')
file write sasfile `" "' _n _n ///
`" /********* THE FOLLOWING IS YOUR pre_sas_prog CODE *********/ "' _n _n
local len_pre_sas_prog : length local pre_sas_prog
if `len_pre_sas_prog' < 256 { // 256 is the max but there is a space at beginning and end
file write sasfile `" `pre_sas_prog' "' _n _n
}
else {
tokenize `" `pre_sas_prog' "', parse(";")
local orig_length : length local pre_sas_prog
local nosemis : subinstr local pre_sas_prog ";" "", all
local s_length : length local nosemis
// tokenize puts the semicolons in the even numbered macro vars
local n_semis = (`orig_length' - `s_length' ) * 2
local odd = 1
forval line = 1/`n_semis' {
if `odd' == 3 {
local odd = 1
}
if `odd' == 1 { // tokenize puts the semicolons in the even numbered macro vars
file write sasfile `" ``line''; "' _n _n
}
local odd = `odd' + 1
}
}
// the following semi-colon is there in case user forgot to end their code with one.
file write sasfile `" ; "' _n _n ///
`" /************** END OF YOUR pre_sas_prog CODE **************/ "' _n _n
}
if "`usasprog'" != "" { /* user submitted a SAS program */
file write sasfile `" "' _n _n ///
`" /********* THE FOLLOWING IS YOUR SAS PROGRAM *********/ "' _n _n ///
`" %include"`usasprog'"; "' _n _n ///
`" /************** END OF YOUR SAS PROGRAM **************/ "' _n _n
}
if `"`post_sas_prog'"' != " " { // two spaces because pre_sas_prog(`" `post_sas_prog' "')
file write sasfile `" "' _n _n ///
`" /********* THE FOLLOWING IS YOUR post_sas_prog CODE *********/ "' _n _n
local len_post_sas_prog : length local post_sas_prog
if `len_post_sas_prog' < 256 { // 256 is the max but there is a space at beginning and end
file write sasfile `" `post_sas_prog' "' _n _n
}
else {
tokenize `" `post_sas_prog' "', parse(";")
local orig_length : length local post_sas_prog
local nosemis : subinstr local post_sas_prog ";" "", all
local s_length : length local nosemis
// tokenize puts the semicolons in the even numbered macro vars
local n_semis = (`orig_length' - `s_length' ) * 2
local odd = 1
forval line = 1/`n_semis' {
if `odd' == 3 {
local odd = 1
}
if `odd' == 1 { // tokenize puts the semicolons in the even numbered macro vars
file write sasfile `" ``line''; "' _n _n
}
local odd = `odd' + 1
}
}
file write sasfile `" "' _n _n ///
`" /************** END OF YOUR post_sas_prog CODE **************/ "' _n _n
}
// the following semi-colon is there in case user forgot to end their code with one.
file write sasfile `" ; proc printto; "' _n ///
`" run; "' _n ///
`" quit; ** close up anything they might have left going **; "' _n _n
if `"`usesas'"' != "" {
file write sasfile `" %let sortedby=; ** leave in for now **; "' _n _n ///
`"%macro makework; "' _n ///
`" run; "' _n ///
`" %let nobs=%sysfunc(getoption(obs)); "' _n ///
`" %if &syserr.^=0 or &nobs.=0 or "&syslast."="_NULL_" %then %do;"' _n ///
`" %goto nevrmind; "' _n ///
`" %end; "' _n ///
`" %let syslast1=&syslast.; "' _n _n
file write sasfile `" proc datasets library= _saswrap; "' _n ///
`" copy in= _saswrap out= work move; "' _n ///
`" select _`sysjobid'_sascoderr (memtype= data); "' _n ///
`" run; "' _n _n ///
`" quit; "' _n _n ///
`" %let syslast=&syslast1.; "' _n _n
file write sasfile `"%if "&syslast." ^= "_NULL_" %then %do; "' _n ///
`" %let ldset=%length(&syslast.); "' _n ///
`" %let decpos=%index(&syslast.,.); "' _n ///
`" %let llib=%substr(&syslast.,1,&decpos.-1); "' _n ///
`" %let dset=%substr(&syslast.,&decpos.+1,&ldset.-&decpos.); "' _n ///
`" %let dset=%sysfunc(lowcase(%nrbquote(&dset.))); "' _n _n
file write sasfile `" data _null_; "' _n ///
`" dsid=open("&syslast.",'i');"' _n `" sortedby=attrc(dsid,'SORTEDBY'); "' _n ///
`" call symput('sortedby',trim(sortedby));"' _n `" rc=close(dsid);"' _n `" run;"' _n _n
file write sasfile `" %if %index(%upcase(&sortedby.),DESCENDING) %then %do; "' _n ///
`" %* this is how Stata treats descending sortedby *; "' _n ///
`" %let sortedby= %substr(&sortedby.,1,%index(%upcase(&sortedby.),DESCENDING)-1); "' _n ///
`" %end;"' _n _n
file write sasfile `" ** if not in work make it be in work **; "' _n ///
`" %if %index(%upcase(&syslast.),WORK)^=1 %then %do; "' _n ///
`" data work.&dset.; "' _n ///
`" set &syslast.;"' _n `" run; "' _n ///
`" %end; ** end of if syslast is not in WORK **; "' _n _n ///
`" %end; ** end of if syslast is _NULL_ **; "' _n _n
file write sasfile `" %nevrmind: ; "' _n ///
`"%mend makework; "' _n ///
`"%makework; "'
if `c(stata_version)' < 9 & "`char2lab'" != "" {
noisily {
di as error `"option char2lab is not allowed prior to Stata 9."'
di as error `"option will be ignored."'
local char2lab ""
}
}
file write sasfile _n _n ///
`"%macro runit; "' _n _n ///
`" %let nobs=%sysfunc(getoption(obs)); "' _n ///
`" %if &syserr.^=0 or &nobs.=0 or "&syslast." = "_NULL_" %then %do;"' _n ///
`" proc printto log="`temp'_saswrapper.txt"; "' _n ///
`" run; "' _n ///
`" %put %upcase(error:) no dataset in SAS to load into Stata; "' _n ///
`" %goto nevrmind; "' _n ///
`" %end; "' _n
// need to put c(SE) and c(MP) in quotes since c(MP) doesn't exist in Stata 8
// need to pass a zero or a one to savastata for SE or MP
file write sasfile `" options nomprint nosource2; "' _n _n
file write sasfile `" %include "`savastata'"; "' _n ///
`" libname ___dir__ "`dir'" ; %* directory where _SAScheck.lst is saved to *; "' _n ///
`" %let _dir=%nrbquote(%sysfunc(pathname(___dir__))); "' _n ///
`" /* &sortedby. is global because of: call symput creates it */ "' _n ///
`" %savastata("`tmpdir'",`quotes' `char2lab' `check' messy `float',&sortedby., "' ///
`" `sysjobid',nosave,"&_dir.`dirsep'",`= ("`c(SE)'" == "1") + ("`c(MP)'" == "1")', "' ///
`" version=`c(stata_version)'); "' _n ///
`" %nevrmind: ; "' _n ///
`"%mend runit;"' _n `"%runit;"' _n
} // end of if usesas
file close sasfile
} /* end of quietly */
end
program valid_dset_name, rclass
syntax , dset(string) [rename]
version 8
local filen `dset'
local fc = substr("`filen'",1,1)
local swn = "0"
local hsc = "0"
if inlist("`fc'","0","1","2","3","4") | ///
inlist("`fc'","5","6","7","8","9") { // name starts with a number
local swn = "1"
}
if index("`filen'","~") | /// Has a bad character in name
index("`filen'","!") | ///
index("`filen'","@") | ///
index("`filen'","#") | ///
index("`filen'","$") | ///
index("`filen'","%") | ///
index("`filen'","^") | ///
index("`filen'","&") | ///
index("`filen'","*") | ///
index("`filen'","(") | ///
index("`filen'",")") | ///
index("`filen'","-") | ///
index("`filen'","+") | ///
index("`filen'","=") | ///
index("`filen'","[") | ///
index("`filen'","]") | ///
index("`filen'",":") | ///
index("`filen'",";") | ///
index("`filen'","'") | ///
index("`filen'","<") | ///
index("`filen'",">") | ///
index("`filen'","?") | ///
index("`filen'",",") | ///
index("`filen'","|") | ///
index("`filen'"," ") | ///
index("`filen'","{") | ///
index("`filen'","}") {
local hsc = "1"
}
if "`swn'" == "1" | "`hsc'" == "1" {
if "`rename'"=="" {
di `"{error}File name {res}"`filen'" {error}is not a valid SAS file name. *"'
if "`swn'" == "1" {
di `"{error}SAS file names cannot start with a number. *"'
}
if "`hsc'" == "1" {
di `"{error}SAS file names cannot contain special characters. *"'
}
}
if "`hsc'" == "1" {
// remove bad characters
foreach char in ~ ! @ # $ % ^ & * ( ) - + = [ ] : ; ' < > ? , | {
local filen = subinstr("`filen'","`char'","_",.)
}
local filen = subinstr("`filen'","{","_",.)
local filen = subinstr("`filen'","}","_",.)
local filen = subinstr("`filen'"," ","_",.)
if `"`: subinstr local filen "_" "" , all'"' == "" { // if nothing left, meaning, person used all bad characters
local filen= "okpopeye"
}
} // end of contains bad character
if "`swn'" == "1" { // name starts with a number
if length("`filen'") == 32 {
local filen = substr("`filen'",2,length("`filen'"))
local filen = "_`filen'"
}
else {
local filen ="_`filen'"
}
} // end of if started with number
if "`rename'" == "" {
di `"{error}The {res}rename {error}option will rename it for you to be: {res}"`filen'" "'
/* log usage of saswrapper */
capture which usagelog
if _rc==0 {
usagelog , type(savas) uerror(6) etime
}
exit 198
}
} /* if filen is not a valid SAS data file name */
return local valid_dset_name `filen'
end