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
752 lines
30 KiB
Plaintext
8 months ago
|
*! 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
|