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.
2827 lines
126 KiB
SAS
2827 lines
126 KiB
SAS
10 months ago
|
/**************************************************************
|
||
|
* SAVASTATA should work for you as is, but you may need
|
||
|
* to edit this file to set the values for the macro variables:
|
||
|
* ustata -- if you are using SAVASTATA in a UNIX or Linux environment
|
||
|
* wstata -- if you are using SAVASTATA in a Windows environment
|
||
|
*
|
||
|
* There are instructions further down in this file explaining where
|
||
|
* and how to edit the settings of these macro variables.
|
||
|
* Do a find for "let ustata" or "let wstata".
|
||
|
**************************************************************/
|
||
|
|
||
|
run; ** Because the world needs more run statements. **;
|
||
|
|
||
|
|
||
|
%MACRO savastata(out_dir,options,sortedby,tfns,nosave,u_dir,U_SE,version=0);
|
||
|
run; %** Because the world needs more run statements. **;
|
||
|
%** If an error has occurred before call to SAVASTATA then fail immediately. **;
|
||
|
%if &syserr.^=0 %then %goto nevrmind;
|
||
|
|
||
|
/*********************************************************************************************
|
||
|
** Macro: SAVASTATA
|
||
|
** Input: Most recently created SAS work dataset, directory path of where to save the output
|
||
|
** Stata dataset file, and any options.
|
||
|
** Output: A Stata 6, 7, 7-SE, 8, or 8-SE dataset, or an ASCII data file with
|
||
|
** other files created by SAVASTATA to input the data into Stata.
|
||
|
**
|
||
|
**
|
||
|
** Programmer: Dan Blanchette dan.blanchette@duke.edu
|
||
|
** Center for Entrepreneurship and Innovation Duke University's Fuqua School of Business
|
||
|
** Developed at:
|
||
|
** The Carolina Population Center at The University of North Carolina at Chapel Hill,
|
||
|
** Research Computing, UNC-CH, and
|
||
|
** Center for Entrepreneurship and Innovation Duke University's Fuqua School of Business
|
||
|
** Date: 20October2003
|
||
|
** Modified: 06Nov2009 - Added search for up to Stata 14 and made Stata 11 also use -saveold-
|
||
|
** Now use %sysfunc(lowcase()) instead of %lowcase since that is what %lowcase is.
|
||
|
** Modified: 16Apr2009 - Fixed situations where long variable labels were attempting to be made into
|
||
|
** Stata variable notes and the macro variable &llabvars. messing things up.
|
||
|
** Modified: 13Mar2009 - Now variable labels that are longer than 80 characters are stored as
|
||
|
** variable notes (the truncated label is still the variable label)
|
||
|
** - renamed file to savastata.sas
|
||
|
** - fixed issue when -ascii option specified with no version number.
|
||
|
** - fixed issue when new dataset name submitted and it's name also existed in
|
||
|
** the directory path, like a dataset named with a single letter: d.dta
|
||
|
** Modified: 01Apr2008 - Made it Stata 10 and Stata MP compatible.
|
||
|
** - Made it so that double quotes in string variables can be transferred
|
||
|
** to Stata by replacing them with the cent sybmol and having Stata replace
|
||
|
** the cent signs back to double quotes. This only happens if no string
|
||
|
** variables contain a cent symbol and if saving to Stata 7+. If that is the case,
|
||
|
** the -quotes option still works to replace double quotes with single quotes.
|
||
|
** - Only saves to Stata 9 when using Stata 10 since no benefit to a Stata 10 file.
|
||
|
** - Fixed situtation when -usesas- calls SAVASTATA with char2lab option
|
||
|
** and no other vars have user-defined formats converted vars did not
|
||
|
** get value labels assigned.
|
||
|
** - Added the version of Stata to be used in the -ascii option.
|
||
|
** - Fixed it so when a variable has formats for special missing values and
|
||
|
** use OTHER, LOW or HIGH also, SAVASTATA handles that.
|
||
|
** - Made it so that if a SAS dataset has more than 32,767 vars savastata
|
||
|
** fails with that message rather than dataset is too wide message.
|
||
|
** - Fixed situations where really long user-defined formats (32,000+
|
||
|
** characters) were being processed.
|
||
|
** - Made help url dynamic so that it is the savastata page when run by
|
||
|
** savastata, or it's the savas or usesas page when run by them.
|
||
|
** - set local macro vars to be local.
|
||
|
** - stopped having Stata sort data after read into Stata since DESCENDING sorts
|
||
|
** and missing values in sorts mess up sorts between SAS and Stata
|
||
|
** Modified: 17Apr2007 - Fixed ability to handle ranges in formats like: 1-3 "first 3"
|
||
|
** - Added restraint of min and max value a format can have since Stata
|
||
|
** cannot make value labels for numbers less than -2,147,483,200 or
|
||
|
** greater than 2,147,483,200
|
||
|
** - Added check that one format does not exceed 65,536 values which is
|
||
|
** the max for Stata
|
||
|
** - Fixed it so that the there is not added space added to value labels.
|
||
|
** Modified: 07Aug2006 - Added ability to handle non-alphanumeric characters in directory names.
|
||
|
** - Added ability for batch invocation of SAS to set location of ustata
|
||
|
** with the sysparm macro variable.
|
||
|
** - Added checking HOSTNAME when discerning where to log usage.
|
||
|
** Modified: 29May2006 - Fixed char2lab option problem with -usesas- & savas when
|
||
|
** formats were stored in formats.sas7bcat
|
||
|
** Modified: 04Apr2006 - Fixed it so that locations of the Stata executable file
|
||
|
** that have spaces in the directory name no longer crash
|
||
|
** savastata. The %sysexec macro is not supposed to require
|
||
|
** double quotes in such situations but adding double quotes
|
||
|
** fixed the problem.
|
||
|
** Modified: 14Mar2006 - no longer searches for stata.exe when run by -usesas-
|
||
|
** Modified: 13Feb2006 - fixed formatting of special missings issues.
|
||
|
** Modified: 10Nov2005 - fixed when usagelog not set issues.
|
||
|
** Modified: 29Sep2005 - fixed situation where -usesas- calls savastata and savastata closed user's log
|
||
|
** - added max str var length to 244 if Stata version is >= 9.1
|
||
|
** since Stata 9.1 does not allow you to save as Stata 8 or 9.0 any special missing
|
||
|
** will be lost since -saveold- saves as Stata 7.
|
||
|
** Modified: 09Aug2005 - If using/saving to Stata 9 and using SAS 9, then SAS user-defined formats
|
||
|
** that have a max length of 32,767 characters can have up to the first
|
||
|
** 32,000 (Stata 9's limit) saved as Stata value labels.
|
||
|
** - new option char2lab which runs the SAS macro char2fmt is only helpful
|
||
|
** if using Stata 9 and only allowed if savastata is being run by savas
|
||
|
** or -usesas- since it changes data dramatically
|
||
|
** - check users path for Stata executable, For *nix, "stata" or "stata-se"
|
||
|
** seem to just work so no need to go hunting.
|
||
|
** - does not save data if Stata does not report same number of obs and vars
|
||
|
** - no longer searches for stata.exe when run by -usesas-
|
||
|
** - spaces in directory names (where intermediary files put) in *nix seems to be fixed.
|
||
|
** - for when -usesas- runs savastata, the maxvar setting is not changed if
|
||
|
** savastata suggests a number lower than the user has already specified.
|
||
|
** otherwise savastata sets maxvar to about 10% of the difference of
|
||
|
** (32,766 - (all variables))
|
||
|
** savastata has successfully worked with 32,766 variables!
|
||
|
** Modified: 24Jun2005 - made sure that if unix/linux directory names had spaces all is still fine
|
||
|
** Modified: 14Jun2005 - fixed it so that directory names with commas in them are okay and problem
|
||
|
** with changing back to pwd that was introduced in 15May2005 version.
|
||
|
** Modified: 15May2005 - fixed it so that directory names with commas in them or
|
||
|
** start with forward slashes (universal filenaming convention)
|
||
|
** are okay.
|
||
|
** - if user has a profile.do that cd's to another directory
|
||
|
** that that is okay.
|
||
|
** Modified: 10May2005 - updated search for Windows Stata executable file to find up to
|
||
|
** version 12 Stata (if directory naming conventions stay predictable)
|
||
|
** - made work when user does not have Stata and wants to save to ascii file
|
||
|
** - made work when user has profile.do changing directories on savastata
|
||
|
** This introduces problems when Unix/Linux directory contains a double quote...
|
||
|
** but what good Unix/Linux user would name a directory containing a double quote?!
|
||
|
** Modified: 22Mar2005 - fixed problems related to when a new dataset name provided
|
||
|
** Modified: 08Dec2004 - The new name of the Stata datafile can be upper case or mix case.
|
||
|
** Modified: 09Nov2004 - User can now specify the name of the Stata datafile they want.
|
||
|
** %savastata("C:\MyProject\My{98}Stata!Data.dta", replace );
|
||
|
** This is helpful if they want to use an invalid SAS filename but valid Stata file name.
|
||
|
** !The Stata dataset name must end in ".dta"!
|
||
|
** - Thanks to West, bug fixed that was related formats using the "Other" category.
|
||
|
** Modified: 26Oct2004 - Stopped allowing user to set what version of Stata they are using. SAVASTATA will always figure it out.
|
||
|
** - also changed note in log to report Stata version as integer instead of 8.2 since the version of
|
||
|
** a dataset is not that specific.
|
||
|
** Modified: 22Jul2004 - fixed bug with numeric variables that had both positive and negative
|
||
|
** formatted values, and made a few tweaks, one of which is that the raw
|
||
|
** ascii data file in the work
|
||
|
** directory is deleted when savastata successfully completes.
|
||
|
** Modified: 27Apr2004 - fixed macro so that setting use8SE=1 does not generate error messages
|
||
|
** about macro variable VER.
|
||
|
** - fixed warning message about script macro var when usagelog not used.
|
||
|
** - added more locations to find the windows Stata executable.
|
||
|
** Modified: 26Feb2004 - memory setting fix for -usesas-
|
||
|
** Modified: 03Feb2004 1) when -usesas- calls macro memory will not be reset if not needed.
|
||
|
** 2) no longer closes existing logs when called by -usesas- .
|
||
|
**
|
||
|
** Disclaimer: This program is free to use and to distribute as long as credit is given to
|
||
|
** Dan Blanchette
|
||
|
** Center for Entrepreneurship and Innovation
|
||
|
** Duke University's Fuqua School of Business.
|
||
|
**
|
||
|
** There is no warranty on this software either expressed or implied. This program
|
||
|
** is released under the terms and conditions of GNU General Public License.
|
||
|
**
|
||
|
** Comments:
|
||
|
** SAVASTATA SAS macro when implemented by the SAS System saves the most recently created
|
||
|
** SAS dataset in the WORK library to a Stata dataset. SAVASTATA requires that you have a
|
||
|
** working copy of SAS and a working copy of Stata Intercooled or SE on your computer to run
|
||
|
** successfully. If your SAS dataset is small enough SAVASTATA may work on Stata Small
|
||
|
** (Student Version).
|
||
|
** If your SAS dataset is using formats that are in a formats catalog (work.formats or
|
||
|
** library.formats), SAVASTATA will make an attempt to preserve them as value labels in
|
||
|
** Stata. Stata does not allow all the variations of user-defined formats that SAS offers.
|
||
|
**
|
||
|
** SAVASTATA may take a few minutes to save your dataset.
|
||
|
**
|
||
|
** SAVASTATA will work in SAS interactive mode or in SAS batch mode.
|
||
|
** SAVASTATA will run on various operating systems including: Windows, Red Hat Linux, AIX.
|
||
|
** It may work fine on others as well.
|
||
|
**
|
||
|
** SAVASTATA uses the most recently created dataset in the work directory,
|
||
|
** figures out how best to store the data as a Stata dataset, keeps most date
|
||
|
** formats and other basic formats for numeric variables, checks for invalid
|
||
|
** Stata variable names, if using or outputting to Stata6: checks to see if long variable
|
||
|
** names need to be shortened, prints them to the SAS log and shortens them, writes out
|
||
|
** the SAS dataset to an ASCII data file, attempts to preserve all user-defined formats for
|
||
|
** numeric variables, writes out Stata do-files, and submits them to Stata in batch mode
|
||
|
** in order to have Stata read the data in and save it as a Stata dataset.
|
||
|
**
|
||
|
** Restrictions of each version of Stata:
|
||
|
** 1. Variable names can be no more than 8 characters long: Stata 6
|
||
|
** 2. Variable names can be up to 32 characters long: Stata 7 and 8
|
||
|
** 3. String variables can contain a maximum of 80 characters: Stata 6, 7 and 8 Intercooled.
|
||
|
** 4. String variables can contain a maximum of 244 characters: Stata 7 and 8 SE.
|
||
|
** 5. The maximum number of variables is 2,047: Stata 6, 7, and 8 Intercooled
|
||
|
** 6. The maximum number of variables is 32,766: Stata 7
|
||
|
** 7. The maximum number of variables is 32,767: Stata 8 and 9 SE
|
||
|
** 8. Special missings (.a through .z) for numeric data are allowed: Stata 8
|
||
|
**
|
||
|
**
|
||
|
** -- SAVASTATA can run on SAS ver 7, 8 or 9
|
||
|
** -- SAVASTATA can run in the following environments: Windows, RS6000, SUN , LINUX
|
||
|
** and maybe on many others.
|
||
|
**
|
||
|
** REQUIRED INPUT TO SAVASTATA:
|
||
|
** -- SAVASTATA needs to have the most recently created dataset by SAS to be in the
|
||
|
** work directory.
|
||
|
** -- SAVASTATA needs to know what directory to put the Stata dataset and possibly
|
||
|
** the files used to input the data to Stata that are written by savastata.
|
||
|
** These are the only required input, but you may choose to make use of the
|
||
|
** following options.
|
||
|
**
|
||
|
** LIST OF OPTIONS:
|
||
|
** NOTE: Options can be used in any order. You can specify as many as you want
|
||
|
** or none at all.
|
||
|
** The following three options work as they do in Stata:
|
||
|
** -replace -- If the Stata dataset you want to output already exists, then overwrite it with
|
||
|
** the dataset generated by savastata.
|
||
|
**
|
||
|
** -old -- Outputs a Stata 6 dataset if using Stata 7 or Stata 7-SE,
|
||
|
** or a Stata 7 Intercooled dataset if using Stata 8 Intercooled
|
||
|
** or a Stata 7-SE dataset if you are using Stata 8-SE.
|
||
|
**
|
||
|
** -intercooled -- Outputs a Stata Intercooled dataset if using Stata SE or Stata MP.
|
||
|
**
|
||
|
** NOTE: If you do not specify what version of Stata to save in, Stata will save the
|
||
|
** dataset in the current version.
|
||
|
**
|
||
|
** -float -- Numeric variables that contain decimals will be stored as float instead of the
|
||
|
** default of double. This may result in a loss of precision, but float is the
|
||
|
** default storage type that Stata uses. This will help decrease your filesize.
|
||
|
**
|
||
|
** -quotes -- Replace double quotes ( " ) occurring in character variables with single quotes ( ' )
|
||
|
** and replace compound quotes ( `" or "' ) occurring in variable labels or formats
|
||
|
** with single quotes ( ' ).
|
||
|
** SAVASTATA cannot process character variables with double quotes or variable
|
||
|
** labels or formats with compound quotes.
|
||
|
**
|
||
|
** -messy -- Puts the files generated by SAVASTATA used to create the Stata dataset in the directory
|
||
|
** named in the pathname provided in the call to the SAVASTATA macro.
|
||
|
**
|
||
|
** -check -- Creates two check files for the user to compare the SAS input dataset with
|
||
|
** the Stata output dataset to make sure SAVASTATA created the files correctly.
|
||
|
** This is a comparison that should be done after any data file is converted
|
||
|
** to any other type of data file by any software. The files are
|
||
|
** created in the same directory as the output Stata data file and are named
|
||
|
** starting with the name of the data file followed by either "_SAScheck.lst"
|
||
|
** or "_STATAcheck.log", e.g. "mydata_SAScheck.lst" and "mydata_STATAcheck.log".
|
||
|
** The SAS check file contains output from proc means,
|
||
|
** proc contents (by position), and a proc print of the first 5 observations.
|
||
|
** The Stata check file contains the equivalent output by the commands summarize,
|
||
|
** describe, and a list of the first 5 observations.
|
||
|
**
|
||
|
** -ascii -- Outputs only the ASCII data file and does not save your dataset in Stata format.
|
||
|
** It also turns on "-messy" switch so that the Stata input files are
|
||
|
** not deleted after your program has run. Use this switch to make your own
|
||
|
** edits to the input of these data into Stata. Use this option if you do not
|
||
|
** have Stata on the same computer that you have SAS. The files generated by
|
||
|
** SAVASTATA can be moved to another computer that does have Stata and run there to
|
||
|
** create the Stata dataset.
|
||
|
**
|
||
|
** The default version of Stata that your ascii file will be set to be used for
|
||
|
** will be Stata 6 (only allow up to 2,047 variables).
|
||
|
**
|
||
|
** If you want to specify what version of Stata will be used to read the ascii
|
||
|
** data you can do so like so:
|
||
|
** -ascii9SE (for Stata 9 SE/MP)
|
||
|
** -ascii9 (for Stata 9 Intercooled)
|
||
|
** -ascii10MP (for Stata 10 SE/MP)
|
||
|
** -ascii8 (for Stata 8 Intercooled)
|
||
|
**
|
||
|
** Stata versions with decimal values are invalid:
|
||
|
** -ascii9.2SE IS INVALID VERSION, just specify: -ascii9SE
|
||
|
** -ascii 9.2 SE IT IS INVALID TO USE SPACES, just specify: -ascii9SE
|
||
|
**
|
||
|
** You can also use options -old and -intercooled to changed what version the data set
|
||
|
** will be saved as.
|
||
|
**
|
||
|
**
|
||
|
** -char2lab - Runs the CHAR2FMT macro but only if SAVASTATA invoked by savas script or -usesas-
|
||
|
** because CHAR2FMT changes the user's dataset in a dramatic way.
|
||
|
** CHAR2FMT converts long character variables to numeric vars and stores character data
|
||
|
** in user-defined formats which get translated into Stata value labels which have
|
||
|
** a maximum length of 32,000 characters (new feature in Stata 9).
|
||
|
**
|
||
|
** SETTING UP SAVASTATA
|
||
|
** These are instructions to edit the savastata.sas file.
|
||
|
**
|
||
|
** NOTE: If you are setting up this macro on your computer for the first time,
|
||
|
** please choose which version of Stata you are going to have SAVASTATA use.
|
||
|
** If you do not choose to set one of the following switches, SAVASTATA will
|
||
|
** figure out what version of Stata you are running for you. This may
|
||
|
** add a noticeable amount of time to processing so you may want to set these
|
||
|
** switches to the correct version of Stata. You can easily figure out what
|
||
|
** version of Stata you are using by looking at the top of your results window
|
||
|
** in Stata or by typing in the command -about- at the Stata command line.
|
||
|
** One advantage of leaving SAVASTATA to figure out what version of Stata is
|
||
|
** being used is that when you upgrade your version of Stata you will not have to
|
||
|
** update savastata.
|
||
|
**
|
||
|
** NOTE:
|
||
|
** -- If you are running SAVASTATA on UNIX or Linux then
|
||
|
** you need to be able to start a Stata batch job by:
|
||
|
** stata -b do mydofile.do
|
||
|
** If not, then change the setting of the ustata macro variable.
|
||
|
**********************************************************************************************/
|
||
|
%local ustata;
|
||
|
/** One of these may work: **
|
||
|
%let ustata=/usr/local/stata/stata;
|
||
|
%let ustata=/usr/local/stata/stata-mp;
|
||
|
%let ustata=/usr/local/stata/stata-se; */
|
||
|
%let ustata=stata;
|
||
|
|
||
|
|
||
|
%** tfns is only submitted by savas and -usesas- and savas may set the location of Stata **;
|
||
|
%* savas may invoke SAS like so: sas -sysparm /alt_location/stata my_sas.sas **;
|
||
|
%if "&tfns."^="" and "&sysparm."^="" and %sysfunc(fileexist("&sysparm.")) %then %do;
|
||
|
%let ustata=%nrbquote(&sysparm.);
|
||
|
%end;
|
||
|
|
||
|
|
||
|
|
||
|
/**********************************************************************************************
|
||
|
**
|
||
|
** -- If you are running SAVASTATA on Windows, you need to tell SAVASTATA where the Stata
|
||
|
** executable file is located.
|
||
|
** If you do not know where your Stata executable file is located, find your Stata
|
||
|
** short-cut icon, right click on it, choose "properties", and look in the "target" field.
|
||
|
** This will show you where the Stata executable file is located on your hard drive.
|
||
|
**
|
||
|
***********************************************************************************************/
|
||
|
%local wstata;
|
||
|
%** Change what is inside the parentheses to the location of your Stata executable file **;
|
||
|
/** One of these may work: **;
|
||
|
%let wstata=%nrstr(C:\Stata\wsestata.exe);
|
||
|
%let wstata=%nrstr(C:\Stata\wmpstata.exe); */
|
||
|
%let wstata=%nrstr(C:\Stata\wstata.exe);
|
||
|
|
||
|
|
||
|
/** SAVASTATA will try the following (plus up to ver 12) if the first does not work:
|
||
|
%let wstata=%nrstr(C:\Stata9\wsestata.exe); ** Stata 9 SE **;
|
||
|
%let wstata=%nrstr(C:\Stata9\wmpstata.exe); ** Stata 9 MP **;
|
||
|
%let wstata=%nrstr(C:\Stata8\wsestata.exe); ** Stata 8 SE **;
|
||
|
%let wstata=%nrstr(C:\Program Files\Stata8\wsestata.exe); ** Stata 8 SE **;
|
||
|
%let wstata=%nrstr(D:\Stata8\wsestata.exe); ** Stata 8 SE **;
|
||
|
%let wstata=%nrstr(C:\Program Files\Stata8\wstata.exe); ** Stata 8 **;
|
||
|
%let wstata=%nrstr(D:\Stata8\wstata.exe); ** Stata 8 **;
|
||
|
%let wstata=%nrstr(C:\Stata8\wsestata.exe); ** Stata 8 SE **;
|
||
|
%let wstata=%nrstr(C:\Stata7\wstata.exe); ** Stata 7 or 7 SE **;
|
||
|
%let wstata=%nrstr(C:\Stata\wstata.exe); ** Stata 6 or 7 or 8, the catcher **;
|
||
|
** then SAVASTATA searches your path **
|
||
|
************************************************/
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*********************************************************************************************
|
||
|
**
|
||
|
** HOW TO USE THE SAVASTATA MACRO:
|
||
|
** Using the SAVASTATA macro requires that you understand how to use the "%include" statement
|
||
|
** and that you know how to call a SAS macro.
|
||
|
**
|
||
|
** %include'LOCATION AND NAME OF A FILE THAT CONTAINS SAS CODE';
|
||
|
**
|
||
|
** For example, if you have copied this file to "C:\SASmacros", then you tell SAS
|
||
|
** about this macro by adding the following line to your SAS program:
|
||
|
**
|
||
|
** %include 'C:\SASmacros\savastata.sas';
|
||
|
**
|
||
|
** This statement makes SAS aware of the SAVASTATA macro which is in the file savastata.sas.
|
||
|
** To use the macro you have to make a call to it. To do that you add a line like the
|
||
|
** following to your SAS program:
|
||
|
**
|
||
|
** %savastata(C:\mySASdir\,-old);
|
||
|
**
|
||
|
** The information inside the parentheses is passed on to the SAVASTATA macro. The first
|
||
|
** string of information is the location you want to save your SAS dataset as a Stata dataset.
|
||
|
** This is somewhat like a libname statement. The second string of information is the options
|
||
|
** you wish to pass on to the SAVASTATA macro. You can use as many options as you like or none at all.
|
||
|
**
|
||
|
**
|
||
|
** EXAMPLE USE OF THE SAVASTATA MACRO:
|
||
|
** %include 'C:\SASmacros\savastata.sas'; ** Include macro once in a SAS session and call it **;
|
||
|
** * as many times as you like in that session. **;
|
||
|
**
|
||
|
** data work.ToBeStata; ** This makes a copy of the SAS dataset in the in the WORK library. **;
|
||
|
** set in.mySASfile;
|
||
|
** run;
|
||
|
**
|
||
|
**
|
||
|
** %savastata(C:\mydata\,); ** Saves the dataset in the C:\mydata\ directory if it does not **;
|
||
|
** * already exist in that directory. **;
|
||
|
**
|
||
|
** OTHER EXAMPLE CALLS:
|
||
|
**
|
||
|
** %savastata(C:\mydata\,-replace); ** Saves the dataset C:\mydata\, overwriting it if **;
|
||
|
** * it already exists. **;
|
||
|
**
|
||
|
** %savastata(C:\data\,-old); ** Saves the dataset as the previous version of Stata **;
|
||
|
** * in C:\data\ directory **;
|
||
|
**
|
||
|
** %savastata(C:\data\,-old -replace); ** Saves the dataset as the previous version of Stata **;
|
||
|
** * in C:\data\ directory, overwriting it if it **;
|
||
|
** * already exists. **;
|
||
|
**
|
||
|
** The -intercooled option starting with Stata 10 only checks for more than 2,047 vars. It does not
|
||
|
** save the dataset as an intercooled dataset since starting with Stata 10 that is no longer
|
||
|
** an option.
|
||
|
** %savastata(C:\data\,-intercooled); ** Saves the dataset as the Intercooled version of Stata **;
|
||
|
** * in C:\data\ directory. This is only possible if **;
|
||
|
** * your version of Stata is an SE edition. **;
|
||
|
**
|
||
|
** %savastata(/project/data/,-old -intercooled); ** Saves the dataset as previous version of **;
|
||
|
** * Stata Intercooled in the /project/data/ **;
|
||
|
** * directory **;
|
||
|
**
|
||
|
**
|
||
|
***********************************************************************************************/
|
||
|
|
||
|
%local usagelog;
|
||
|
%** SET LOCATION OF USAGE LOG FILE **;
|
||
|
%let usagelog="specify what file name and location you want here";
|
||
|
%if "&sysscp."="WIN" %then %do;
|
||
|
%let usagelog="x:\software\temp\savas_usage.log"; %* windoze *;
|
||
|
%end;
|
||
|
%else %if "&sysscp."="RS6000" %then %do;
|
||
|
%let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/savas_usage.log"; %* AIX nodes *;
|
||
|
%end;
|
||
|
%else %if "&sysscp."="AIX 64" %then %do;
|
||
|
%let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/savas_usage.log"; %* AIX nodes *;
|
||
|
%end;
|
||
|
%else %if "&sysscp."="LINUX" %then %do; %* linux boxes *;
|
||
|
%if %index(%qlowcase(%qcmpres(%sysget(HOSTNAME))),"gromit") = 1
|
||
|
or %index(%qlowcase(%qcmpres(%sysget(HOSTNAME))),"sig") = 1
|
||
|
or %index(%qlowcase(%qcmpres(%sysget(HOSTNAME))),".cpc.") ^= 0 %then
|
||
|
%let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/savas_usage.log";
|
||
|
%else %let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/savas_usage.log";
|
||
|
%end;
|
||
|
%else %if %index(%qupcase(&sysscp.),SUN) %then %do;
|
||
|
%let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/savas_usage.log";
|
||
|
%end;
|
||
|
%else %do;
|
||
|
%let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/savas_usage.log";
|
||
|
%end;
|
||
|
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/****** !NO MORE EDITS TO THE MACRO SHOULD BE MADE BEYOND THIS POINT! ******/
|
||
|
/***************************************************************************/
|
||
|
|
||
|
%** local macro vars used in savastata **;
|
||
|
%local ascii avars bign bign1 bvar bytemax bytemin ch char2fmthttp char2lab
|
||
|
check cq crdate cv decpos diffhour diffmin diffsec dq dq1
|
||
|
dq_fail dq_fix dyc dy dy_and_dq_fail
|
||
|
drive dset dta_exists fail fail11 fail20 fail23 fb fe fdset
|
||
|
flavor flibr float http i ii intmax intmin intrcool isysver
|
||
|
j jj k kk labtrunc ldset librfmts llabvars ln lo longname
|
||
|
longmax longmin max_clen_count maxobs maxreclen maxstrvarlen maxvallablen maxvar messy MP
|
||
|
name newname nobs noisily notes nv ob obs old pwdir
|
||
|
pwdrive quietly quotes reclen replace s_dsn s_last s_SEver s_ver script
|
||
|
SE slash sm sprog startdat success temp_dir u_SEver u_sysrc
|
||
|
u_ver udset unix uspace var_c var_n vlabels work_dir workfmts w_sysrc;
|
||
|
|
||
|
%** make sure sas version is an integer so it can be properly evaluated **;
|
||
|
%let isysver = %sysevalf(&sysver.,integer);
|
||
|
|
||
|
%** Save option settings so they can be restored at the end of this macro. **;
|
||
|
%let notes=%sysfunc(getoption(notes));
|
||
|
|
||
|
%let obs=%sysfunc(getoption(obs));
|
||
|
|
||
|
options obs=MAX; %*** Reason for maximizing it is because user could have **;
|
||
|
%* set it lower than the number of variables in the dataset. **;
|
||
|
options nonotes; %** Shut off notes while program is running in order to reduce log size. **;
|
||
|
|
||
|
%** Time how long SAVASTATA takes to run **;
|
||
|
%let startdat=%sysfunc(datetime());
|
||
|
|
||
|
%** initialize macro vars **;
|
||
|
%let diffhour=0;
|
||
|
%let diffmin=0;
|
||
|
%let diffsec=0;
|
||
|
%let fail=0;
|
||
|
%let success=0;
|
||
|
|
||
|
%** if out_dir is surrounded by double or single quotes, remove them. **;
|
||
|
%if %nrbquote(%index(%nrbquote(&out_dir.),%str(%")))=1
|
||
|
or %nrbquote(%index(%nrbquote(&out_dir.),%str(%')))=1
|
||
|
%then %let out_dir=%nrbquote(%substr(%nrbquote(&out_dir.),2,%length(%nrbquote(&out_dir.))-2));
|
||
|
|
||
|
%if %nrbquote(%index(%nrbquote(&u_dir.),%str(%")))=1 or %nrbquote(%index(%nrbquote(&u_dir.),%str(%')))=1
|
||
|
%then %let u_dir=%nrbquote(%substr(%nrbquote(&u_dir.),2,%length(%nrbquote(&u_dir.))-2));
|
||
|
|
||
|
|
||
|
%** initialize var **;
|
||
|
%let newname=;
|
||
|
|
||
|
%** check to see if new dataset name provided in %nrbquote(&out_dir.) **;
|
||
|
%if %nrbquote(%length(&out_dir.)) > 0 %then %do;
|
||
|
%if %nrbquote(%index(%qlowcase(&out_dir.),.dta)) %then %do;
|
||
|
%** if Stata dataset name provided with directory info **;
|
||
|
%if "%qlowcase(%substr(%nrbquote(&out_dir.),%length(%nrbquote(&out_dir.))-3,4))"=".dta" %then %do;
|
||
|
%** if no backslash provided: savstata(d:mydata.dta) then add in the backslash **;
|
||
|
%if "&sysscp."="WIN"
|
||
|
and %nrbquote(%index(%nrbquote(&out_dir.),:)) = 2 and %nrbquote(%index(%nrbquote(&out_dir.),\)) ^= 3 %then
|
||
|
%let out_dir = %nrbquote(%substr(%nrbquote(&out_dir.),1,2)\%substr(%nrbquote(&out_dir.),3,%length(%nrbquote(&out_dir.))-2));
|
||
|
%let newname=%nrbquote(%substr(%nrbquote(&out_dir.),1,%length(%nrbquote(&out_dir.))-4));
|
||
|
%if %index(%nrbquote(&newname.),\) %then %do;
|
||
|
%do %while(%nrbquote(%index(%nrbquote(&newname.),\)));
|
||
|
%let newname=%nrbquote(%substr(%nrbquote(&newname.),%index(%nrbquote(&newname.),\)+1,%length(&newname.)-(%index(%nrbquote(&newname.),\))));
|
||
|
%end;
|
||
|
%let out_dir=%nrbquote(%substr(%nrbquote(&out_dir.),1,%index(%nrbquote(&out_dir.),%nrbquote(&newname.))-1));
|
||
|
%end;
|
||
|
%else %if %index(%nrbquote(&newname.),/) %then %do;
|
||
|
%do %while(%nrbquote(%index(%nrbquote(&newname.),/)));
|
||
|
%let newname=%nrbquote(%substr(%nrbquote(&newname.),%index(%nrbquote(&newname.),/)+1,%length(&newname.)-(%index(%nrbquote(&newname.),/))));
|
||
|
%end;
|
||
|
%let out_dir=%nrbquote(%substr(%nrbquote(&out_dir.),1,%eval(%length(%nrbquote(&out_dir.))-%length(%nrbquote(&newname..dta)))));
|
||
|
%end;
|
||
|
%else %let out_dir=; %** only new name provided **;
|
||
|
%end;
|
||
|
%end; %** end of if %index(%nrbquote(&out_dir.),.dta) do loop **;
|
||
|
%end; %** end of if length(%nrbquote(&out_dir.)) = 0 do loop **;
|
||
|
|
||
|
|
||
|
%let s_dsn=&sysdsn.; %** preserve these to restore after setting up usagelog **;
|
||
|
|
||
|
%** script var is definitive way to determine how savastata was called, **;
|
||
|
%* if empty then not called by either -usesas- or savas **;
|
||
|
%let script=;
|
||
|
%if "&tfns." ^= "" and "&nosave."="nosave" %then %do;
|
||
|
%let script=usesas;
|
||
|
%end;
|
||
|
%else %if "&tfns."^="" and "&nosave."="" %then %do;
|
||
|
%let script=savas;
|
||
|
%end;
|
||
|
|
||
|
%** log usage of savastata if usage log file exists **;
|
||
|
%if %sysfunc(fileexist(&usagelog.)) %then %do;
|
||
|
data _null_;
|
||
|
file &usagelog. mod;
|
||
|
%if "&script."="" %then %do;
|
||
|
put " ";
|
||
|
date=datetime() ;
|
||
|
put " savastata macro " date dateampm. ;
|
||
|
%end;
|
||
|
put " &sysuserid. savastata( &out_dir.,&options.,&sortedby.,&tfns.,&nosave.,&u_dir.,&U_SE.)";
|
||
|
%end;
|
||
|
|
||
|
%let sysdsn=&s_dsn.; %** restore after setting up usagelog **;
|
||
|
|
||
|
%let noisily = ;
|
||
|
%let quietly = ;
|
||
|
%if "&script." = "usesas" %then %do;
|
||
|
options nonotes nodate ;
|
||
|
%let noisily =noisily;
|
||
|
%let quietly =quietly;
|
||
|
%** proc printto prints any weird error messages that SAS has to this log file in a nice, *;
|
||
|
%* readable format because -usesas- looks for this file and prints it to the results window **;
|
||
|
proc printto log="&out_dir._&tfns._report.log"; run;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%** current website address for savastata, usesas, or savas help: **;
|
||
|
%* used in fail messages at end of macro **;
|
||
|
%let sprog=savastata;
|
||
|
%if "&script." ^="" %then %let sprog=&script.;
|
||
|
%let http=%nrstr(http://faculty.fuqua.duke.edu/home/blanc004/data_programming/sas_to_stata/)&sprog..html;
|
||
|
%let char2fmthttp=%nrstr(http://faculty.fuqua.duke.edu/home/blanc004/data_programming/sas_to_stata/char2fmt.html);
|
||
|
|
||
|
%** Find out what directory SAS currently is using as the present working directory **;
|
||
|
%* so that it can be restored at end of macro. **;
|
||
|
libname ________ " "; %** ________ is a very unlikely libname **;
|
||
|
%let pwdir=%nrbquote(%sysfunc(pathname(________)));
|
||
|
%let pwdrive= ;
|
||
|
%if %index(%nrbquote(&pwdir.),\) %THEN %do;
|
||
|
%let pwdrive= %qsubstr(%nrbquote(&pwdir.),1,2); %** get drive info eg. "d:" **;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%** if no temporary filenames are supplied then use sysjobid macro var **;
|
||
|
%if %length(&tfns.)=0 %then %let tfns=&sysjobid.&sysindex.;
|
||
|
%** Have macro var that will increase each time macro run for **;
|
||
|
%* times when one SAS session runs savastata macro multiple **;
|
||
|
%* times and -messy option specified. ***;
|
||
|
|
||
|
|
||
|
%*** Use the most recently created SAS work dataset. ***;
|
||
|
%let s_last=&syslast.;
|
||
|
%let ldset=%length(&syslast.);
|
||
|
%let decpos=%index(&syslast.,.);
|
||
|
%let dset=%substr(&syslast.,&decpos.+1,&ldset.-&decpos.);
|
||
|
|
||
|
%** use the work directory to store the temporary SAS files that this program creates ***;
|
||
|
%let temp_dir = %nrbquote(%sysfunc(pathname(work)));
|
||
|
%let work_dir = %nrbquote(%sysfunc(pathname(work)));
|
||
|
|
||
|
%** this is first time program goes to a fail label **;
|
||
|
%** Work directory cannot start with a back slash because savastata needs to cd to it. **;
|
||
|
%if %index(%nrbquote(&work_dir.),\)=1 %then %goto fail18;
|
||
|
|
||
|
%** Figure out whether the operating system uses forward slashes or back slashes in **;
|
||
|
%* directory paths and make sure that out_dir has the appropriate slash at the end. **;
|
||
|
%let unix=0;
|
||
|
%let drive= ;
|
||
|
%IF %index(%nrbquote(&temp_dir.),\) %THEN %do;
|
||
|
%let unix=0; %** unix=0 implies windows platform **;
|
||
|
%let drive= %qsubstr("&work_dir.",2,2); %** get drive info eg. "d:" **;
|
||
|
%let temp_dir = %nrbquote(&temp_dir.)\; %** tack on a back slash **;
|
||
|
%if "&out_dir."="" %then %goto fail4;
|
||
|
%else %if "&out_dir."=" " %then %goto fail4;
|
||
|
%else %if "&out_dir."="." %then %goto fail4;
|
||
|
%let slash= %qsubstr("&out_dir.",%length("&out_dir.")-1,1); %** check if back slash at end **;
|
||
|
%if "&slash."^="\" %THEN %do;
|
||
|
%let out_dir= %nrbquote(&out_dir.)\; %** add a back slash at end if it is not there already **;
|
||
|
%end;
|
||
|
%END;
|
||
|
%ELSE %IF %index(%nrbquote(&temp_dir.),/) %THEN %do;
|
||
|
%let unix=1; %** unix or unix-like platform **;
|
||
|
%let temp_dir = %nrbquote(&temp_dir.)/; %** tack on a forward slash **;
|
||
|
%** make sure that out_dir is not a relative directory name like: ../mydata/ **;
|
||
|
libname ________ "&out_dir."; %** ________ is a very unlikely libname **;
|
||
|
%let out_dir=%nrbquote(%sysfunc(pathname(________)));
|
||
|
%let slash= %qsubstr("&out_dir.",%length("&out_dir.")-1,1); %** check if back slash at end **;
|
||
|
%if "&slash."^="/" %THEN %do;
|
||
|
%let out_dir= %nrbquote(&out_dir.)/; %** add a forward slash at end if it is not there already **;
|
||
|
%end;
|
||
|
%END; %** ELSE IF index("temp_dir",/) THEN do loop **;
|
||
|
|
||
|
|
||
|
|
||
|
%** Make sure the dataset name and any option passed to savastata is in lower case. **;
|
||
|
%let dset=%sysfunc(lowcase(%nrbquote(&dset.)));
|
||
|
%if %length(&newname.)>0 %then %let fdset=%nrbquote(&newname.);
|
||
|
%else %let fdset=%sysfunc(lowcase(%nrbquote(&dset.)));
|
||
|
%let options=%sysfunc(lowcase(%nrbquote(&options.)));
|
||
|
|
||
|
%let udset=%qupcase(&fdset.);
|
||
|
|
||
|
%if %index(&syslast.,WORK)^=1 %then %goto fail1;
|
||
|
|
||
|
%** if obs are set to zero, error in program previous to savastata **;
|
||
|
%if &obs.=0 %then %goto fail13;
|
||
|
|
||
|
|
||
|
%if &udset.=_CONTEN
|
||
|
or &udset.=_CONTEN1
|
||
|
or &udset.=_CONTEN2
|
||
|
or &udset.=_CONTEN3 %then %goto fail3;
|
||
|
|
||
|
|
||
|
%** initialize macro var **;
|
||
|
%let workfmts=0;
|
||
|
%let librfmts=0;
|
||
|
%let vlabels=0;
|
||
|
|
||
|
%** check to see if format libraries exist **;
|
||
|
%let workfmts=%sysfunc(cexist(WORK.FORMATS));
|
||
|
%** cexist tests to see if catalog file created for current OS
|
||
|
%* if it was not, then librfmts = 0 even if library.formats does exist *;
|
||
|
%let librfmts=%sysfunc(cexist(LIBRARY.FORMATS));
|
||
|
%if &workfmts.=1 or &librfmts.=1 %then %let vlabels=1;
|
||
|
|
||
|
%** Initialize macro vars for savastata options **;
|
||
|
%let ascii=0;
|
||
|
%let float=0;
|
||
|
%let quotes=0;
|
||
|
%let messy=0;
|
||
|
%let intrcool= ;
|
||
|
%let old= ;
|
||
|
%let replace= ;
|
||
|
%let check=0;
|
||
|
%let char2lab=0;
|
||
|
|
||
|
%if %nrstr(&options.)^=%nrstr() %then %do;
|
||
|
%** Find out what options were specified **;
|
||
|
%if %index(&options.,ascii) %then %let ascii=1; %** set ascii option **;
|
||
|
%if %index(&options.,fl) %then %let float=1; %** set float option **;
|
||
|
%if %index(&options.,qu) %then %let quotes=1; %** set quote option **;
|
||
|
%if %index(&options.,mes) %then %let messy=1; %** set messy option **;
|
||
|
%if %index(&options.,old) %then %let old=old; %** set old option **;
|
||
|
%if %index(&options.,int) %then %let intrcool=intercooled; %** set intrcool option **;
|
||
|
%if %index(&options.,rep) %then %let replace=replace; %** set replace option **;
|
||
|
%if %index(&options.,rpl) %then %let replace=replace; %** set replace option **;
|
||
|
%if %index(&options.,che) %then %let check=1; %** set check option **;
|
||
|
%if %index(&options.,cha) %then %let char2lab=1; %** set char2lab option **;
|
||
|
%end;
|
||
|
|
||
|
%** initialize vars to default setting of Stata if you know you what version of Stata you have **;
|
||
|
%** Need to set all if you set any. **;
|
||
|
%let u_ver=0.0; %** version of Stata that is being used. decimal values are okay. *;
|
||
|
%* set this if you do not want Stata to be run just figure out what *;
|
||
|
%* version of Stata you are using. *;
|
||
|
%let s_ver=0.0; %** version of Stata that data will be saved as. *;
|
||
|
%* set this only if you set the u_ver variable. *;
|
||
|
%* old option will change this if used **;
|
||
|
%let u_SEver=0; %** 1 if SE/MP version of Stata that is being used. *;
|
||
|
%let s_SEver=0; %** 1 if SE/MP version of Stata that data will be saved as. *;
|
||
|
%* intercooled option will change this if used **;
|
||
|
|
||
|
%* make sure these macro vars are numbers. **;
|
||
|
%** Stata versions are multiplied by 10 so that no decimal places exist **;
|
||
|
%let u_ver=%sysevalf(&u_ver.*10,integer);
|
||
|
%let s_ver=%sysevalf(&s_ver.*10,integer);
|
||
|
|
||
|
%* test that save version is not higher than the using version *;
|
||
|
%if &s_ver. > &u_ver. %then %goto fail2;
|
||
|
%if not (&u_SEver.=0 or &u_SEver.=1) %then %goto fail2;
|
||
|
%if not (&s_SEver.=0 or &s_SEver.=1) %then %goto fail2;
|
||
|
%** cannot use Intercooled and save to SE **;
|
||
|
%if (&u_SEver.=0 and &s_SEver.=1) %then %goto fail2;
|
||
|
|
||
|
%if &ascii.=1 %then %do;
|
||
|
%** Need to save all the files if ascii specified. **;
|
||
|
%if &messy.=0 %then %let messy=1;
|
||
|
|
||
|
%let ascii_ver=%qsubstr(&options.,%index(&options.,ascii),%eval(%length(&options.)-%index(&options.,ascii)+1) );
|
||
|
%let ascii_ver=%scan(&ascii_ver.,1,%nrstr( ));
|
||
|
%if &ascii_ver. = ascii %then %do;
|
||
|
%let ascii_ver= ; %** use default settings **;
|
||
|
%end;
|
||
|
%else %do;
|
||
|
%let ascii_ver=%qsubstr(&ascii_ver.,6,%eval(%length(&ascii_ver.)-5));
|
||
|
%end;
|
||
|
%if &ascii_ver. = %then %do;
|
||
|
%* use defaults settings. **;
|
||
|
%end;
|
||
|
%else %do;
|
||
|
%* figure out what version user specified: *;
|
||
|
%let blen=%length(&ascii_ver.);
|
||
|
%** replace "se" with a blank **;
|
||
|
%let ascii_ver=%cmpres(%sysfunc(translate(&ascii_ver.,%nrstr( ), se)));
|
||
|
%let alen=%length(&ascii_ver.);
|
||
|
%if &alen. < &blen. %then %do;
|
||
|
%let u_SEver=1;
|
||
|
%if &intrcool.^=intercooled %then %let s_SEver=1;
|
||
|
%end;
|
||
|
%else %do;
|
||
|
%let blen=%length(&ascii_ver.);
|
||
|
%** replace "mp" with a blank **;
|
||
|
%let ascii_ver=%cmpres(%sysfunc(translate(&ascii_ver.,%nrstr( ), mp)));
|
||
|
%let alen=%length(&ascii_ver.);
|
||
|
%if &alen. < &blen. %then %do;
|
||
|
%let u_SEver=1;
|
||
|
%if &intrcool.^=intercooled %then %let s_SEver=1;
|
||
|
%end;
|
||
|
%end; %** end of if either SE or MP was specified **;
|
||
|
%** < 2000 is just an extremely high version of Stata **;
|
||
|
%if 0 < &ascii_ver. and &ascii_ver. < 2000 %then %do;
|
||
|
%* ascii_ver is a number *;
|
||
|
%let u_ver=&ascii_ver.;
|
||
|
%let u_ver=%sysevalf(&u_ver.*10,integer);
|
||
|
%if &old.=old %then %do;
|
||
|
%if &ascii_ver.=9 %then %do;
|
||
|
%let s_ver=%eval(&ascii_ver. - 2);
|
||
|
%let s_SEver=0; %** Stata 9 saves old only to Stata 7 IC **;
|
||
|
%let intrcool=intercooled; %** setting intrcool to intercooled makes this work **;
|
||
|
%* as s_SEver gets set to u_SEver later **;
|
||
|
%end;
|
||
|
%else %let s_ver=%eval(&ascii_ver. - 1);
|
||
|
%end;
|
||
|
%else %let s_ver=&u_ver.;
|
||
|
%let s_ver=%sysevalf(&s_ver.*10,integer);
|
||
|
%end;
|
||
|
%end;
|
||
|
%* change of default settings based on old and intercooled will be changed later **;
|
||
|
%end; %** end of if ascii=1;
|
||
|
|
||
|
|
||
|
%** check to see if user has set up Windows Stata correctly. **;
|
||
|
%** if not then check other likely places the Stata executable would be. **;
|
||
|
%let fail20=0;
|
||
|
%** do not need the stata.exe when ascii or -usesas- running it *;
|
||
|
%if not (&ascii.=1 or "&script." = "usesas") %then %do;
|
||
|
%if &unix.=0 and %sysfunc(fileexist("&wstata."))=0 %then %do %while(&fail20.=0);
|
||
|
%let drives =C D Y;
|
||
|
%let exe =wsestata wmpstata wstata;
|
||
|
%let versions =14 13 12 11 10 9 8 7 6;
|
||
|
%do i = 1 %to 3; %** one for each drive **;
|
||
|
%let ii =%scan(&drives.,&i.,%nrstr( ));
|
||
|
%do j = 1 %to 3; %** one for each exe of stata **;
|
||
|
%let jj =%scan(&exe.,&j.,%nrstr( ));
|
||
|
%do k = 1 %to 7; %** one for each version of stata **;
|
||
|
%let kk =%scan(&versions.,&k.,%nrstr( ));
|
||
|
|
||
|
%let wstata=%str(&ii.:\Stata&kk.\&jj..exe);
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%let wstata=%str(&ii.:\Program Files\Stata-&kk.\&jj..exe); %** Stata-9 **;
|
||
|
%end;
|
||
|
%else %goto exist; %** file exists **;
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%let wstata=%str(&ii.:\Program Files\Stata&kk.\&jj..exe); %** Stata9 **;
|
||
|
%end;
|
||
|
%else %goto exist; %** file exists **;
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%let wstata=%str(&ii.:\Stata-&kk.\&jj..exe); %** Stata-9 **;
|
||
|
%end;
|
||
|
%else %goto exist; %** file exists **;
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%let wstata=%str(&ii.:\Stata&kk.\&jj..exe); %** Stata9 **;
|
||
|
%end;
|
||
|
%else %goto exist; %** file exists **;
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%let wstata=%str(&ii.:\Stata\&jj..exe);
|
||
|
%end;
|
||
|
%else %goto exist; %** file exists **;
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%** nothing **;
|
||
|
%end;
|
||
|
%else %goto exist; %** file exists **;
|
||
|
%end; %** of k loop **;
|
||
|
%end; %** of j loop **;
|
||
|
%end; %** of i loop **;
|
||
|
%do; %** check path for Stata executable **;
|
||
|
%let i=1;
|
||
|
%let delim=%str(;);
|
||
|
%do %until (%qscan(%sysget(PATH),&i.,%str(&delim.)) = );
|
||
|
%let wstata="%qscan(%sysget(PATH),&i.,%str(&delim.))\wsestata.exe";
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then
|
||
|
%let wstata="%qscan(%sysget(PATH),&i.,%str(&delim.))\wmpstata.exe";
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then
|
||
|
%let wstata="%qscan(%sysget(PATH),&i.,%str(&delim.))\wstata.exe";
|
||
|
%if %sysfunc(fileexist("&wstata.")) %then %do;
|
||
|
%let fail20=2;
|
||
|
%let i=200000; %** break loop if found it **;
|
||
|
%end;
|
||
|
%let i=%eval(&i.+1);
|
||
|
%end;
|
||
|
%if fail20=2 %then %goto exist; %** file exists **;
|
||
|
%end; %** of checking path for Stata executable **;
|
||
|
%if %sysfunc(fileexist("&wstata."))=0 %then %do;
|
||
|
%let wstata=NO STATA EXECUTABLE FOUND;
|
||
|
%let fail20=1; %** give up **;
|
||
|
%end;
|
||
|
%exist: ;
|
||
|
%if &fail20.=0 %then %let fail20=2; %** found file so break while loop **;
|
||
|
%end; %** end of if unix=0 then do while loop **;
|
||
|
|
||
|
%end; %** end of if &ascii. = 0 and &script. = "usesas" **;
|
||
|
|
||
|
%if &fail20.=1 %then %goto fail20;
|
||
|
|
||
|
|
||
|
libname ________ "&out_dir."; %** ________ is a very unlikely libname **;
|
||
|
%if &syslibrc.^=0 %then %do;
|
||
|
libname ________ clear; %** do away with it now **;
|
||
|
%goto fail5; %** exit if not a valid pathname **;
|
||
|
%end;
|
||
|
|
||
|
libname ________ clear; %** do away with it now **;
|
||
|
|
||
|
%* -usesas- sets messy to on so it can contol where the files are put **;
|
||
|
%if &messy.=1 %then %do;
|
||
|
%** Use the output directory to store the SAS program files that this macro creates. ***;
|
||
|
%let temp_dir = %nrbquote(&out_dir.);
|
||
|
%let work_dir = %nrbquote(&out_dir.);
|
||
|
%if &unix.=0 %then %do;
|
||
|
%let windrive= %qsubstr("&out_dir.",2,2); %** get drive info eg. "d:" **;
|
||
|
%sysexec &windrive.; ** change to whatever drive files are going **;
|
||
|
%end;
|
||
|
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
|
||
|
%sysexec cd %nrbquote(&out_dir.) ; %** change to the drive and directory where the Stata do-files are. **;
|
||
|
%end;
|
||
|
|
||
|
%if "&u_dir."^="" %then %do; %** this happens when -usesas- or savas script call savastata **;
|
||
|
%let out_dir = %nrbquote(&u_dir.);
|
||
|
%end;
|
||
|
|
||
|
%** run Stata to find out what version of Stata is being used. **;
|
||
|
%* -usesas- passes &version. to savastata but savas needs to figure it out here **;
|
||
|
%* Stata versions are multiplied by 10 so that no decimal places exist **;
|
||
|
%if &script.=usesas %then %do;
|
||
|
%** force this since a -usesas- user could have incorrectly preset this **;
|
||
|
%let u_ver=%sysevalf(&version.*10,integer);
|
||
|
%** force this since a -usesas- user could have incorrectly preset this **;
|
||
|
%* and -usesas- needs to have s_ver = u_ver since it does not save data. **;
|
||
|
%let s_ver=&u_ver.;
|
||
|
/** U_SE should only equal either 1 or 0: `= ("`c(SE)'" == "1") + ("`c(MP)'" == "1")' **/
|
||
|
%if &U_SE.>=1 %then %let u_SEver=1;
|
||
|
%end;
|
||
|
%else %if &u_ver.=0 and &ascii.=0 %then %do;
|
||
|
data _null_;
|
||
|
file "&temp_dir._&tfns._version.do";
|
||
|
put " capture program drop stata_v";
|
||
|
put " program define stata_v, nclass";
|
||
|
put " capture log close ";
|
||
|
put " quietly log using ""&temp_dir._&tfns._ver.log"" ";
|
||
|
%** macro var version can have decimal places **;
|
||
|
put ' display "%let version=" _caller() " ; " ';
|
||
|
put ' display "%let SE=$S_StataSE ;" ';
|
||
|
put ' display "%let MP=$S_StataMP ;" ';
|
||
|
put " quietly capture log close " ;
|
||
|
put " end ";
|
||
|
put " stata_v";
|
||
|
run;
|
||
|
|
||
|
%let uspace=0; %** flag if in non-Windows and directory name has a space in it **;
|
||
|
%if "&nosave."="" %then %do; %** if not run by -usesas- **;
|
||
|
%if &unix.=1 %then %do;
|
||
|
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
|
||
|
%* change to the drive and directory where the Stata do-files are. **;
|
||
|
%sysexec cd %nrbquote(&work_dir.) ;
|
||
|
|
||
|
%** Run Stata in batch from within the directory where the temp files are. **;
|
||
|
%sysexec %nrbquote(&ustata.) -b do "_&tfns._version.do";
|
||
|
%if &sysrc.^=0 %then %goto fail21;
|
||
|
%end; %** if unix=1 do loop **;
|
||
|
|
||
|
%if &unix.=0 %then %do;
|
||
|
%sysexec &drive.;
|
||
|
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
|
||
|
%sysexec cd %nrbquote(&work_dir.) ;
|
||
|
%** Run Stata in batch. **;
|
||
|
%sysexec "&wstata." /e do "&temp_dir._&tfns._version.do";
|
||
|
%end; %** if unix=0 then do loop **;
|
||
|
|
||
|
%if %sysfunc(fileexist("_&tfns._ver.log")) %then %do;
|
||
|
%include "_&tfns._ver.log";
|
||
|
%end;
|
||
|
%else %goto fail22;
|
||
|
|
||
|
%let u_ver=%sysevalf(&version.*10,integer);
|
||
|
|
||
|
%** stata 6 cannot handle $S_StataSE or $S_StataMP *;
|
||
|
%if &SE.=E %then %let SE=;
|
||
|
%if &MP.=P %then %let MP=;
|
||
|
|
||
|
%** no difference between MP and SE to savastata **;
|
||
|
%if &SE.=SE or &MP.=MP %then %let u_SEver=1;
|
||
|
|
||
|
%end; %** end of "&nosave." ^= "" (not being run by -usesas-) **;
|
||
|
%end; %** if script=usesas, else if &u_ver.=0 and &ascii.=0 then do loop **;
|
||
|
|
||
|
%** u_ver is multiplied by 10 to make sure no decimal exists **;
|
||
|
%if 100 <= &u_ver. and &u_ver. < 120 %then %do;
|
||
|
%**if using Stata 10 or 11, no reason to save to current version so saveold **;
|
||
|
%let old=old;
|
||
|
%end;
|
||
|
|
||
|
%if &old.=old %then %do;
|
||
|
%if 90<=&u_ver. and &u_ver.<100 %then %do;
|
||
|
%let s_ver=70; %** Stata 9 -saveold- saves to version 7 IC only **;
|
||
|
%let s_SEver=0; %** Stata 9 -saveold- saves to version 7 IC only **;
|
||
|
%let intrcool=intercooled; %** setting intrcool to intercooled makes this work **;
|
||
|
%* as s_SEver gets set to u_SEver later **;
|
||
|
%end;
|
||
|
%else %let s_ver=%eval(&u_ver. - 10); %** otherwise subtract 1 (by subtracting 10) **;
|
||
|
%if &u_ver.>=100 and &u_ver.<110 %then %let s_ver=91; %** Stata 10 saves like Stata 9.1 not 9.0 **;
|
||
|
%end;
|
||
|
%else %let s_ver=&u_ver.;
|
||
|
|
||
|
%if &s_SEver.=0 %then %let s_SEver=&u_SEver.;
|
||
|
%if &s_SEver.=1 and &intrcool.=intercooled %then %let s_SEver=0;
|
||
|
|
||
|
%if &s_ver. > &u_ver. %then %goto fail2;
|
||
|
%if not (&u_SEver.=0 or &u_SEver.=1) %then %goto fail2;
|
||
|
%if not (&s_SEver.=0 or &s_SEver.=1) %then %goto fail2;
|
||
|
%** cannot use Intercooled and save to SE **;
|
||
|
%if (&u_SEver.=0 and &s_SEver.=1) %then %goto fail2;
|
||
|
|
||
|
|
||
|
%** Have to be using Stata SE to specify that you are saving a Stata Intercooled dataset. **;
|
||
|
%if &u_SEver.=0 %then %let intrcool= ;
|
||
|
|
||
|
|
||
|
%* char2lab can only be run by savas or -usesas- **;
|
||
|
%if &char2lab.=1 %then %do;
|
||
|
%** s_ver is multiplied by 10 to make sure no decimal exists **;
|
||
|
%if &s_ver. < 90 %then %do;
|
||
|
%** Stata 9 started allowing value labels to be up to 32,000 charactes long.**;
|
||
|
%** Stata 8 will ignore such value labels if dataset is read into Stata 8 **;
|
||
|
%put %upcase(warning): The option char2lab is not beneficial prior to Stata 9. *;
|
||
|
%let char2lab=0;
|
||
|
%end;
|
||
|
%if ("&script." = "" ) %then %do;
|
||
|
%** The option char2lab is not allowed when SAVASTATA is not run by the savas script **;
|
||
|
%* or the Stata command -usesas-. **;
|
||
|
%put %upcase(warning): The option char2lab is not allowed. *;
|
||
|
%if &s_ver. >= 90 %then %do;
|
||
|
%put Consider running the SAS macro CHAR2FMT before running SAVASTATA. *;
|
||
|
%put For more help check here: &char2fmthttp. ;
|
||
|
%end;
|
||
|
%let char2lab=0;
|
||
|
%end;
|
||
|
%if &char2lab.=0 %then %do;
|
||
|
%put %upcase(warning): char2lab option will be ignored. * ;
|
||
|
%end;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%* set max limits for Stata dataset **;
|
||
|
%* For SE or Intercooled the max number of obs is: 2,147,483,647 **;
|
||
|
%let maxobs=2147483647;
|
||
|
%* set max string variable length and max value label length **;
|
||
|
%if &s_ver.<70 %then %do; %** Stata 7 was first version with SE **;
|
||
|
%let maxstrvarlen=80;
|
||
|
%let maxvallablen=80;
|
||
|
%end;
|
||
|
%else %if &s_SEver.=0 and &s_ver.<=90 %then %do; %** intercooled versions 7, 8 and 9.0 **;
|
||
|
%let maxstrvarlen=80;
|
||
|
%let maxvallablen=80;
|
||
|
%end;
|
||
|
%else %if &s_SEver.=1 and &s_ver.<=90 %then %do; %** Stata 7 SE, 8 SE, and 9.0 SE **;
|
||
|
%let maxstrvarlen=244;
|
||
|
%let maxvallablen=244;
|
||
|
%end;
|
||
|
%else %if &s_ver.>=91 %then %do; %** 9.1+ SE and Intercooled are the same **;
|
||
|
%let maxstrvarlen=244;
|
||
|
%let maxvallablen=32000;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%let dta_exists=0;
|
||
|
%if "&script." ^= "usesas" %then %do;
|
||
|
%if %sysfunc(fileexist("&out_dir.&fdset..dta")) %then %do;
|
||
|
%let dta_exists=1;
|
||
|
%if &replace.^=replace and &ascii.=0 %then %do;
|
||
|
%goto fail7;
|
||
|
%end;
|
||
|
%end;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%** check for long character variables only if using Stata 9 or higher **;
|
||
|
%if &u_ver. >= 90 %then %do;
|
||
|
proc contents data=&dset. out=_conten noprint;
|
||
|
run;
|
||
|
|
||
|
proc sort data=_conten;
|
||
|
by type;
|
||
|
run;
|
||
|
|
||
|
%let max_clen_count=0;
|
||
|
data _null_;
|
||
|
set _conten (where=(type=2)) end=lastobs ;
|
||
|
retain max_clen_count 0;
|
||
|
by type;
|
||
|
if length > &maxstrvarlen. then do;
|
||
|
max_clen_count = max_clen_count + 1;
|
||
|
%if &char2lab. = 1 %then %do;
|
||
|
if max_clen_count=1 then do;
|
||
|
%** if a var has a length longer than needed then it may be needlessly converted **;
|
||
|
%* if the trailing blanks were removed first...which savastata does after char2fmt **;
|
||
|
%* is run. not worth moving length optimization to be before here as it has to **;
|
||
|
%* be done after char2fmt as well **;
|
||
|
put " This is a list of character variables that are going to be made into *";
|
||
|
put " numeric variables but have value labels containing their character contents *";
|
||
|
put " because they contain more than &maxstrvarlen. characters. *";
|
||
|
end;
|
||
|
put " " name " *";
|
||
|
%end;
|
||
|
end;
|
||
|
if last.type and type=2 then do;
|
||
|
call symput( 'max_clen_count', compress(left( put( max_clen_count, 10. ) ) ) ) ;
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
%** only do char2fmt if user asked for it and have long character vars that need **;
|
||
|
%* to be made into labels **;
|
||
|
%* char2fmt creates and deletes temporary dataset _conten2 **;
|
||
|
%if (&char2lab.=1) and (&max_clen_count. > 0 ) %then %do;
|
||
|
%char2fmt(dset=&dset. , maxlen=&maxstrvarlen. , temp_dir=%nrbquote(&temp_dir.) , tfns=&tfns. );
|
||
|
%let workfmts=%sysfunc(cexist(WORK.FORMATS));
|
||
|
%if &workfmts.=1 %then %let vlabels=1;
|
||
|
%end;
|
||
|
%** end begin char2lab process **;
|
||
|
%end; %** of if s_ver>=90 **;
|
||
|
|
||
|
%** run proc means to check data after potential change in data by char2fmt **;
|
||
|
%if &check.=1 %then %do;
|
||
|
proc printto print="&out_dir.&fdset._SAScheck.lst" new ; run;
|
||
|
proc means data=&dset.;
|
||
|
proc contents data=&dset. position;
|
||
|
proc print data=&dset. (obs=5);
|
||
|
run;
|
||
|
proc printto; %** ends printing to means.lst and returns printing to normal **;
|
||
|
run;
|
||
|
%end;
|
||
|
|
||
|
%** Here starts the processing of the dataset. **;
|
||
|
%** Create a dataset of the dataset info of the input dataset. **;
|
||
|
proc contents data=&dset. out=_conten noprint;
|
||
|
run;
|
||
|
|
||
|
%** Initialize macro vars **;
|
||
|
%let nv=0;
|
||
|
%let cv=0;
|
||
|
%let ch=0;
|
||
|
%let ln=0;
|
||
|
%let ob=0;
|
||
|
%let lo=0;
|
||
|
%let dq=0;
|
||
|
%let dq1=0;
|
||
|
%let dy=0;
|
||
|
%let dyc=0; %** initialize to 0 for now **;
|
||
|
%let bign=0;
|
||
|
%let bign1=0;
|
||
|
%let name=0;
|
||
|
%** Check for vars with names that are used in savastata like: _N and _______N. **;
|
||
|
data _null_;
|
||
|
set _conten(keep=name ) end=lastobs;
|
||
|
retain bign bign1 0;
|
||
|
name=lowcase(name);
|
||
|
if name="_n" then bign=1;
|
||
|
if name="_______N" then bign1=1;
|
||
|
if name="___nv___" then call symput("nv","1");
|
||
|
if name="___cv___" then call symput("cv","1");
|
||
|
if name="___ch___" then call symput("ch","1");
|
||
|
if name="___ln___" then call symput("ln","1");
|
||
|
if name="___ob___" then call symput("ob","1");
|
||
|
if name="___lo___" then call symput("lo","1");
|
||
|
if name="___dq___" then call symput("dq","1");
|
||
|
if name="___dq1__" then call symput("dq1","1");
|
||
|
if name="___dy___" then call symput("dy","1");
|
||
|
if name="___dyc__" then call symput("dyc","1");
|
||
|
if name="_name_" then call symput("name","1");
|
||
|
|
||
|
if lastobs then do;
|
||
|
call symput("bign",bign);
|
||
|
call symput("bign1",bign1);
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
/** DR's little fix **/
|
||
|
%let crdate=SAVASTATA created this dataset on %sysfunc(date(),date9.);
|
||
|
|
||
|
%** An attempt to rename _N to _______N will fail
|
||
|
%* because both vars exist in the dataset. **;
|
||
|
%if &bign.=1 and &bign1.=1 %then %goto fail8;
|
||
|
|
||
|
%let bvar=________;
|
||
|
%if &nv.=1 %then %do; %let bvar=___nv___; %goto fail9; %end;
|
||
|
%if &cv.=1 %then %do; %let bvar=___cv___; %goto fail9; %end;
|
||
|
%if &ch.=1 %then %do; %let bvar=___ch___; %goto fail9; %end;
|
||
|
%if &ln.=1 %then %do; %let bvar=___ln___; %goto fail9; %end;
|
||
|
%if &ob.=1 %then %do; %let bvar=___ob___; %goto fail9; %end;
|
||
|
%if &lo.=1 %then %do; %let bvar=___lo___; %goto fail9; %end;
|
||
|
%if &dq.=1 %then %do; %let bvar=___dq___; %goto fail9; %end;
|
||
|
%if &dq1.=1 %then %do; %let bvar=___dq1__; %goto fail9; %end;
|
||
|
%if &dy.=1 %then %do; %let bvar=___dy___; %goto fail9; %end;
|
||
|
%if &dyc.=1 %then %do; %let bvar=___dyc__; %goto fail9; %end;
|
||
|
%if &name.=1 %then %do; %let bvar=_name_; %goto fail9; %end;
|
||
|
|
||
|
|
||
|
|
||
|
%* invalid Stata vars *;
|
||
|
%let bstatavs='_ALL','_B','BYTE','_COEF','_CONS','DOUBLE','FLOAT','IF','IN','INT','LONG','_N','_PI','_PRED','_RC','_SE','_SKIP','_UNIFORM','USING','WITH';
|
||
|
|
||
|
%let cq=0;
|
||
|
data _conten;
|
||
|
length __strvar 8 label $200 llabvars $32000;
|
||
|
set _conten end=lastobs;
|
||
|
%** count how many variable labels need to be truncated **;
|
||
|
%* and create a list of variables that need variable labels saved as notes **;
|
||
|
retain llabcnt 0 llabvars "";
|
||
|
name=upcase(name); %** make sure all variable names are upper case **;
|
||
|
if (substr(name,1,3)='STR') then do; %** Look for variables named like "str14" which is **;
|
||
|
%* an invalid variable name in Stata if it was in **;
|
||
|
%* lower case. Leave them in upper case. **;
|
||
|
__strvar=substr(name,4,length(name));
|
||
|
_error_=0; %** SAS creates _error_=15 if _strvar evaluates to ., so clear it. **;
|
||
|
if (__strvar in(.,0)) then name=lowcase(name);
|
||
|
else call symput("bstatavs","&bstatavs.,'"||trim(name)||"'"); %** add str var to list **;
|
||
|
end;
|
||
|
%** Check for variable names that are invalid variable names in Stata if they were in **;
|
||
|
%* lower case and leave them in upper case. **;
|
||
|
else if name ~in(&bstatavs.) then name=lowcase(name);
|
||
|
|
||
|
%if &bign.=1 and &bign1.=0 %then %do;
|
||
|
if (name='_N') then do;
|
||
|
put "%upcase(warning): SAVASTATA has renamed Stata invalid variable _N to _______N * ";
|
||
|
name='_______N';
|
||
|
call symput("bstatavs","&bstatavs.,'"||trim(name)||"'"); %** add _______N var to list **;
|
||
|
end;
|
||
|
%end;
|
||
|
if label^="" then do;
|
||
|
%** this does not need to be version controlled as Stata has only ever allowed 80 characters *;
|
||
|
%* for variable labels: *;
|
||
|
llabel = label; ** store long labels in notes in Stata **;
|
||
|
if length(label)>80 then do;
|
||
|
llabcnt=llabcnt+1;
|
||
|
label=substr(label,1,80); %** need to test length before escaping $ and \ etc. **;
|
||
|
if llabcnt = 1 then do;
|
||
|
put "%upcase(warning): This is a list of variables that have had their label truncated to 80 characters * ";
|
||
|
put " and had their original label stored as a note in Stata. * ";
|
||
|
llabvars = '"' || trim(lowcase(name)) || '"';
|
||
|
end;
|
||
|
else llabvars = trim(llabvars) || ',"' || trim(name) || '"';
|
||
|
put @10 name " * ";
|
||
|
end;
|
||
|
|
||
|
%** prepare label to be written to _labels.do **;
|
||
|
%if &u_ver. < 90 or "&script." = "usesas" %then %do;
|
||
|
%** replace two back slashes with four, tranwrd is like subinstr **;
|
||
|
if index(label,"\\") then label = tranwrd(label,"\\","\\\\");
|
||
|
%* if index(llabel,"\\") then llabel = tranwrd(llabel,"\\","\\\\"); %** this does not matter to Stata, all will reduced to one **;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%** replace all left quotes with right quotes since they mess things up **;
|
||
|
if index(label,"`") then label = tranwrd(label,"`","'");
|
||
|
if index(llabel,"`") then llabel = tranwrd(llabel,"`","'");
|
||
|
%** the above can create a right compound quote **;
|
||
|
|
||
|
%** escape all dollar signs **;
|
||
|
if index(llabel,"$") then llabel = tranwrd(llabel,"$","\$");
|
||
|
%** if variable label contains a compound quote. **;
|
||
|
if index(label,"`"||'"') or index(label,'"'||"'") then do;
|
||
|
call symput("cq","1");
|
||
|
%if "es.=1 %then %do;
|
||
|
label = tranwrd(label,"`"||'"',"''"); %* replace left compound quote with two single quotes *;
|
||
|
label = tranwrd(label,'"'||"'","''"); %* replace right compound quote with two single quotes *;
|
||
|
%end;
|
||
|
end;
|
||
|
%** if variable llabel contains a compound quote. **;
|
||
|
if index(llabel,"`"||'"') or index(llabel,'"'||"'") then do;
|
||
|
call symput("cq","1");
|
||
|
%if "es.=1 %then %do;
|
||
|
llabel = tranwrd(llabel,"`"||'"',"''"); %* replace left compound quote with two single quotes *;
|
||
|
llabel = tranwrd(llabel,'"'||"'","''"); %* replace right compound quote with two single quotes *;
|
||
|
%end;
|
||
|
end;
|
||
|
end; %** if var has a label **;
|
||
|
if lastobs then call symput("llabvars",trim(llabvars));
|
||
|
|
||
|
|
||
|
length w d $5;
|
||
|
w=formatl;
|
||
|
d=formatd;
|
||
|
format=upcase(format);
|
||
|
orig_fmt=format;
|
||
|
if (format='' & formatl>0) then format = compress('%'||w||'.'||d||'f',' ');
|
||
|
else if (format='F') then format = compress('%'||w||'.'||d||'f',' ');
|
||
|
else if (format='BEST') then format = compress('%'||formatl||'.0g');
|
||
|
else if (format='DATE' & formatl<9) then format = '%d';
|
||
|
else if (format='DATE' & formatl>=9) then format = '%dDlCY';
|
||
|
else if (format='DDMMYY' & formatl<10) then format = '%dD/N/Y';
|
||
|
else if (format='DDMMYY' & formatl>=10) then format = '%dD/N/CY';
|
||
|
else if (format='MMDDYY' & formatl<10) then format = '%dN/D/Y';
|
||
|
else if (format='MMDDYY' & formatl>=10) then format = '%dN/D/CY';
|
||
|
else if (format='YYMMDD' & formatl<8) then format = '%dYND';
|
||
|
else if (format='YYMMDD' & 8<=formatl<10) then format = '%dY-N-D';
|
||
|
else if (format='YYMMDD' & formatl>=10) then format = '%dCY-N-D';
|
||
|
else if (format='DAY') then format = '%dD';
|
||
|
else if (format='MONTH') then format = '%dl';
|
||
|
else if (format='YEAR' & formatl<4) then format = '%dY';
|
||
|
else if (format='YEAR' & formatl>=4) then format = '%dCY';
|
||
|
else if (format='MONNAME') then format = '%dM';
|
||
|
else if (format='MONYY' & formatl<7) then format = '%dlY';
|
||
|
else if (format='MONYY' & formatl>=7) then format = '%dlCY';
|
||
|
else if (format='WEEKDAY') then format = '%dd';
|
||
|
else if (format='WORDDATE') then format = '%d';
|
||
|
else if (format='WORDDATX') then format = '%d';
|
||
|
else if (format='YYMM') then format = '%d';
|
||
|
else if (format='YYMON' & formatl<7) then format = '%dYl';
|
||
|
else if (format='YYMON' & formatl>=7) then format = '%dCYl';
|
||
|
else format='default';
|
||
|
|
||
|
if type=2 then format='default'; %** make all string vars be default format **;
|
||
|
run;
|
||
|
|
||
|
%if &cq.=1 and "es.=0 %then %goto fail10; %** Variable label contains a compound quote **;
|
||
|
|
||
|
|
||
|
%** initialize macro vars **;
|
||
|
%let VAR_N = 0 ; %* number of numeric variables *;
|
||
|
%let VAR_C = 0 ; %* number of character variables *;
|
||
|
%let longname=0;
|
||
|
|
||
|
%** check for varnames longer than 8 characters and rename them **;
|
||
|
%if &isysver.<7 %then %goto skip6;
|
||
|
%if &s_ver.< 70 %then %do;
|
||
|
data _conten;
|
||
|
length longname $32;
|
||
|
set _conten;
|
||
|
longname = name;
|
||
|
if (length(name)>8) then do;
|
||
|
s_name=right(substr(name,1,4)); %** renaming vars after proc means (check) done! oh, well*;
|
||
|
call symput("longname","1");
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%if &longname.=1 %then %do; %** only do if there is at least one varname > 8 **;
|
||
|
%** Check that variables have not been renamed to names that already exist in the dataset. **;
|
||
|
proc sort data=_conten;
|
||
|
by s_name name;
|
||
|
run;
|
||
|
|
||
|
data _conten;
|
||
|
set _conten;
|
||
|
by s_name;
|
||
|
retain count start 0;
|
||
|
if first.s_name then count=0;
|
||
|
if (length(name)>8) then do;
|
||
|
start=start+1;
|
||
|
count=count+1;
|
||
|
name=compress(s_name||count);
|
||
|
if start=1 then do;
|
||
|
%** print to log **;
|
||
|
put " ";
|
||
|
put "%upcase(warning): Stata 6 does not allow variable names longer than 8 characters. * ";
|
||
|
put " ";
|
||
|
put "%upcase(warning): List of long variable names that SAVASTATA has renamed: * ";
|
||
|
put " ";
|
||
|
put " Original long name" @35 " New short name * ";
|
||
|
put " ";
|
||
|
end;
|
||
|
put " " longname @33 " = " @36 name " * ";
|
||
|
end; %** end of if (length(name)>8) do loop **;
|
||
|
run;
|
||
|
|
||
|
proc sort data=_conten; by name;
|
||
|
run;
|
||
|
|
||
|
%let fail11=0; %** initialize fail11 macro var **;
|
||
|
data _null_;
|
||
|
set _conten;
|
||
|
by name;
|
||
|
if not (first.name and last.name) then do; %** means there is a repeat in varnames **;
|
||
|
call symput("fail11","1");
|
||
|
end;
|
||
|
|
||
|
run;
|
||
|
%if &fail11.=1 %then %goto fail11;
|
||
|
|
||
|
%end; %** end of if long=1 the do loop **;
|
||
|
%end; %** end of if &s_ver.< 70 do loop **;
|
||
|
%skip6: ; %** Skip fixing stuff for Stata 6 if using SAS 6 **;
|
||
|
|
||
|
proc sort data=_conten; by type;
|
||
|
run;
|
||
|
|
||
|
%let var_n=0;
|
||
|
%let var_c=0;
|
||
|
%let avars=0;
|
||
|
%** Count up number of numeric and number of character variables. **;
|
||
|
data _null_ ;
|
||
|
set _conten end=lastobs;
|
||
|
by type;
|
||
|
if first.type then do;
|
||
|
var_non=0;
|
||
|
var_noc=0;
|
||
|
end;
|
||
|
if type=1 then do; %* numeric vars **;
|
||
|
var_non + 1 ;
|
||
|
end;
|
||
|
if type=2 then do; %* character vars **;
|
||
|
var_noc + 1 ;
|
||
|
end;
|
||
|
|
||
|
%** Create macro vars containing final number of vars. **;
|
||
|
if last.type and type=1 then call symput( 'VAR_N', left( put( var_non , 5. ) ) ) ;
|
||
|
if last.type and type=2 then do;
|
||
|
call symput( 'VAR_C', left( put( var_noc, 5. ) ) ) ;
|
||
|
end;
|
||
|
|
||
|
%** AVARS is total number of variables **;
|
||
|
if lastobs then call symput( 'AVARS', compress(left( put( _n_, 5. ) ) ) ) ;
|
||
|
|
||
|
run ;
|
||
|
|
||
|
%if &AVARS.=0 %then %do ;
|
||
|
%goto fail12 ;
|
||
|
%end ;
|
||
|
|
||
|
|
||
|
%*** Figure out minimum safe storage type for each variable. ***;
|
||
|
%if &s_ver. < 80 %then %do;
|
||
|
%let bytemin = -127;
|
||
|
%let bytemax = 126;
|
||
|
%let intmin = -32767;
|
||
|
%let intmax = 32766;
|
||
|
%let longmin = -2147483647;
|
||
|
%let longmax = 2147483646;
|
||
|
%end; %** of if s_ver < 80 then do loop **;
|
||
|
%else %do; %** Starting with Stata 8 there is a smaller range due to storage of special missings **;
|
||
|
%let bytemin = -127;
|
||
|
%let bytemax = 100;
|
||
|
%let intmin = -32767;
|
||
|
%let intmax = 32740;
|
||
|
%let longmin = -2147483647;
|
||
|
%let longmax = 2147483620;
|
||
|
%end; %** of if s_ver < 80 then do loop **;
|
||
|
|
||
|
|
||
|
%** Initialize macro vars **;
|
||
|
%let nobs=0;
|
||
|
%let dq_fail=0;
|
||
|
%let dy_and_dq_fail=0;
|
||
|
%let dq_fix=;
|
||
|
%let dyc=%sysfunc(byte(162)); %** this makes cents **;
|
||
|
%let sm=0;
|
||
|
|
||
|
data _conten1;
|
||
|
set work.&dset. end=___lo___;
|
||
|
format _all_; %** remove all formats and informats **;
|
||
|
informat _all_;
|
||
|
|
||
|
%** Count up observations since using _n_ to step through arrays. **;
|
||
|
array ___ob___[1] _temporary_ (1*0);
|
||
|
|
||
|
___ob___[1]=___ob___[1]+1;
|
||
|
|
||
|
|
||
|
%if &VAR_N.>0 %then %do; %** process numeric vars *;
|
||
|
array ___nv___ [&VAR_N.] _numeric_; %** all numeric variables in dataset **;
|
||
|
array ___ln___ [&VAR_N.] _temporary_ (&VAR_N.*3);
|
||
|
|
||
|
%** use the temporary variable _n_ to step through the arrays so as **;
|
||
|
%* not to create another var (i). _n_ resets itself at next obs. **;
|
||
|
do _n_ = 1 to &VAR_N.;
|
||
|
%** check to see if any numeric var has special missing values **;
|
||
|
if .a<=___nv___[_n_]<=.z then call symput("sm","1");
|
||
|
|
||
|
if ___ln___[_n_] ne 8 and ___nv___[_n_] ne . then do ;
|
||
|
if ___nv___[_n_] ne int(___nv___[_n_]) then ___ln___(_n_)=8; %** all decimal vars length 8 *;
|
||
|
else %* check numeric variables that are integers *;
|
||
|
if &BYTEMIN.<=___nv___[_n_]<=&BYTEMAX. then ___ln___(_n_)= max( ___ln___(_n_), 3 ) ;
|
||
|
else
|
||
|
if &INTMIN.<=___nv___[_n_]<=&INTMAX. then ___ln___(_n_)= max( ___ln___(_n_), 4 ) ;
|
||
|
else
|
||
|
if &LONGMIN.<=___nv___[_n_]<=&LONGMAX. then ___ln___(_n_)= max( ___ln___(_n_), 6 ) ;
|
||
|
else
|
||
|
___ln___(_n_)=8;
|
||
|
end ;
|
||
|
end ; %*** end of _n_=1 to &VAR_N. ***;
|
||
|
%end; %** end of processing numeric vars **;
|
||
|
|
||
|
|
||
|
|
||
|
%if &VAR_C.>0 %then %do; %* now process the character variables *;
|
||
|
array ___cv___( &VAR_C. ) _character_ ; %** all character variables in dataset **;
|
||
|
%** temp array vars are retained variables **;
|
||
|
array ___ch___( &VAR_C. ) _temporary_ (&VAR_C.*1); %** var length **;
|
||
|
array ___dq___( &VAR_C. ) _temporary_ (&VAR_C.*0); %** var has dq **;
|
||
|
array ___dy___( &VAR_C. ) _temporary_ (&VAR_C.*0); %** var has dyc **;
|
||
|
array ___dq1__( 1 ) _temporary_ (1*0); %** any var has dq **;
|
||
|
array ___dyc__(1) $32766 _temporary_ ; %** all vars that have dqs and dycs **;
|
||
|
|
||
|
do _n_ = 1 to &VAR_C. ;
|
||
|
%** check for double quotes in character variables **;
|
||
|
if ___dq___[_n_]=0 then do; %** once a var is known to have a double quote **;
|
||
|
%* stop checking it for a double quote **;
|
||
|
if index(___cv___[_n_],compress(' " ')) then do;
|
||
|
___dq___[_n_]=1;
|
||
|
%** temp array vars are retained variables **;
|
||
|
___dq1__[1]=1;
|
||
|
end;
|
||
|
end;
|
||
|
%** also check for &dyc. char in character variables **;
|
||
|
if ___dy___[_n_]=0 then do; %** once a var is known to have a dyc **;
|
||
|
%* stop checking it for a dyc **;
|
||
|
if index(___cv___[_n_],"&dyc.") then ___dy___[_n_]=1;
|
||
|
%** temp array vars are retained variables **;
|
||
|
end;
|
||
|
|
||
|
%* increase character length until the maximum needed *;
|
||
|
if ___ch___[_n_] < length(___cv___[_n_]) then ___ch___[_n_]=length(___cv___[_n_]);
|
||
|
end; %** of do _n_ = 1 to &VAR_C. **;
|
||
|
%end; %* end of processing character vars *;
|
||
|
|
||
|
if ___lo___ then do ;
|
||
|
call symput("nobs",compress(___ob___[1]));
|
||
|
%if &VAR_N.>0 %then %do;
|
||
|
do _n_ = 1 to &VAR_N. ;
|
||
|
___nv___[_n_]=___ln___[_n_]; %** replace values of variables with their length **;
|
||
|
end;
|
||
|
%end;
|
||
|
|
||
|
%if &VAR_C.>0 %then %do;
|
||
|
%if &u_ver.>=70 %then %do; %** since long varnames could be renamed for Stata 6 **;
|
||
|
%* and -foreach- does not work in 6, do not do this. *;
|
||
|
do _n_ = 1 to &VAR_C.;
|
||
|
if ___dy___[_n_]=0 and ___dq___[_n_]=1 then do;
|
||
|
%** create a list of char vars that need fixing **;
|
||
|
%* do same upcasing/lowcasing as before **;
|
||
|
if upcase(trim(vname(___cv___[_n_]))) in(&bstatavs.) then
|
||
|
___dyc__[1]= trim(upcase(vname(___cv___[_n_])))||trim(" ")||trim(___dyc__[1]);
|
||
|
else
|
||
|
___dyc__[1]= trim(lowcase(vname(___cv___[_n_])))||trim(" ")||trim(___dyc__[1]);
|
||
|
if upcase(trim(vname(___cv___[_n_]))) = "_N" then
|
||
|
___dyc__[1]= trim("_______N")||trim(" ")||trim(___dyc__[1]);
|
||
|
end; %** of if var had dq but not dyc **;
|
||
|
if ___dy___[_n_]=1 and ___dq___[_n_]=1 then call symput("dy_and_dq_fail","1");
|
||
|
end; %** of do _n_ to var_c **;
|
||
|
%end; %** if u_ver>=70 loop **;
|
||
|
%else %do;
|
||
|
%** if previous to version 7 then force replacing **;
|
||
|
%* double quotes with single quotes **;
|
||
|
if ___dq1__[1]=1 then call symput("dy_and_dq_fail","1");
|
||
|
%end;
|
||
|
%** create a macro var that has char vars that have double quotes **;
|
||
|
%* and can be fixed. **;
|
||
|
if ___dq1__[1]=1 then call symput("dq_fix",trim(___dyc__[1]));
|
||
|
if ___dq1__[1]=1 then call symput("dq_fail","1");
|
||
|
|
||
|
do _n_ = 1 to &VAR_C.;
|
||
|
%** this converts the character data to numeric data *;
|
||
|
___cv___[_n_]=___ch___[_n_]; %** replace values of variables with their length **;
|
||
|
end;
|
||
|
%end; %* of if &VAR_C.>0 then do **;
|
||
|
output;
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
%if %sysfunc(fileexist(&usagelog.)) %then %do;
|
||
|
data _null_;
|
||
|
file &usagelog. mod;
|
||
|
put " Input SAS dataset has &nobs. obs and &AVARS. vars" ;
|
||
|
%end;
|
||
|
|
||
|
%if &nobs.=0 %then %goto fail13;
|
||
|
%if &nobs.>&maxobs. %then %goto fail25;
|
||
|
|
||
|
%if &u_ver.>=70 %then %do; %** since varnames could be renamed for Stata 6 **;
|
||
|
%* then do not do this. *;
|
||
|
%if &dy_and_dq_fail.=1 and "es.=0 %then %goto fail14;
|
||
|
%end;
|
||
|
%else %do;
|
||
|
%if &dq_fail.=1 and "es.=0 %then %goto fail14;
|
||
|
%end;
|
||
|
|
||
|
%** Stata 7 and earlier cannot save special missing values **;
|
||
|
%if &sm.=1 and &s_ver. < 80 %then %do;
|
||
|
%put %upcase(warning): The dataset WORK.&dset. contains special missing data that will be converted to missing (.) * ;
|
||
|
%end;
|
||
|
|
||
|
%** Since _conten1 is one obs in the dataset transpose to create variable _name_. **;
|
||
|
proc transpose data =_conten1 out=_conten1;
|
||
|
var _all_;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%** Put _conten dataset in the variable order of the original dataset. **;
|
||
|
proc sort data=_conten;
|
||
|
by varnum;
|
||
|
run;
|
||
|
|
||
|
%** Figure out the minimum required length for accurate storage of the col1 variable. **;
|
||
|
data _conten1;
|
||
|
set _conten1;
|
||
|
varnum=_n_; %** make the variable order be the order they are in dataset **;
|
||
|
run;
|
||
|
|
||
|
data _conten;
|
||
|
merge _conten(keep=name varnum type label llabel orig_fmt format)
|
||
|
_conten1(keep=_name_ varnum col1);
|
||
|
by varnum;
|
||
|
run;
|
||
|
|
||
|
|
||
|
data _conten;
|
||
|
length c_len $10 stype $10 oformat $10;
|
||
|
set _conten;
|
||
|
retain lcvarcnt 0; %** count how many variables need to be truncated **;
|
||
|
c_len=compress(col1);
|
||
|
n_len=input(c_len,8.);
|
||
|
|
||
|
%** name has been fixed if too long or left upper case **;
|
||
|
%* and _name_ is untouched **;
|
||
|
|
||
|
if type=1 /*** and format="default" ***/ then do; %** numeric variables **;
|
||
|
if c_len="3" then do; stype="byte"; oformat="best4."; end;
|
||
|
else if c_len="4" then do; stype="int"; oformat="best6."; end;
|
||
|
else if c_len="6" then do; stype="long"; oformat="best11."; end;
|
||
|
else if c_len="8" and &float.=1 then do; stype="float"; oformat="best18."; end;
|
||
|
else if c_len="8" and &float.=0 then do; stype="double"; oformat="best18."; end;
|
||
|
end;
|
||
|
/******************
|
||
|
if type=1 and format^="default" then do; %** numeric variables with formats **;
|
||
|
stype="double"; oformat="best17.";
|
||
|
end;
|
||
|
******************/
|
||
|
|
||
|
|
||
|
if type=2 then do; %** character variables **;
|
||
|
if n_len>&maxstrvarlen. then do;
|
||
|
c_len="&maxstrvarlen.";
|
||
|
if &char2lab. = 0 then do;
|
||
|
lcvarcnt = lcvarcnt + 1;
|
||
|
if lcvarcnt = 1 then do;
|
||
|
put "%upcase(warning): This is a list of variables that have been truncated to &maxstrvarlen. characters. * ";
|
||
|
if (&s_ver. >= 90) then do;
|
||
|
if ("&script." = "") then do;
|
||
|
put "Consider using the SAS macro CHAR2FMT to convert them to numeric variables with *";
|
||
|
put " SAS formats containing their character data. SAVASTATA saves formats as value labels in Stata. *";
|
||
|
end;
|
||
|
else do;
|
||
|
put "Consider using the char2lab option to encode them to numeric with value labels in Stata. *";
|
||
|
end;
|
||
|
end; %* end of if saving to Stata version 9 or higher **;
|
||
|
end;
|
||
|
put @10 name ' * ';
|
||
|
end;
|
||
|
end;
|
||
|
period='.';
|
||
|
oformat=compress("$char"||c_len);
|
||
|
oformat=compress(oformat||period);
|
||
|
stype=compress("str"||c_len);
|
||
|
stype=left(stype);
|
||
|
end; %** end of if type=2 do loop **;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%** Figure out the record length. **;
|
||
|
data _null_;
|
||
|
set _conten end=lastobs;
|
||
|
retain bpos lepos 0;
|
||
|
if type=1 then do;
|
||
|
if stype="byte" then len=1;
|
||
|
if stype="int" then len=2;
|
||
|
if stype="long" then len=4;
|
||
|
if stype="float" then len=4;
|
||
|
if stype="double" then len=8;
|
||
|
end;
|
||
|
if type=2 then len=input(c_len,8.);
|
||
|
|
||
|
bpos=lepos+1;
|
||
|
lepos=bpos+len-1;
|
||
|
|
||
|
if lastobs then do;
|
||
|
call symput("reclen",compress(lepos));
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%if &s_ver.>=80 %then %do;
|
||
|
proc format;
|
||
|
value ___mi___
|
||
|
.a=".a"
|
||
|
.b=".b"
|
||
|
.c=".c"
|
||
|
.d=".d"
|
||
|
.e=".e"
|
||
|
.f=".f"
|
||
|
.g=".g"
|
||
|
.h=".h"
|
||
|
.i=".i"
|
||
|
.j=".j"
|
||
|
.k=".k"
|
||
|
.l=".l"
|
||
|
.m=".m"
|
||
|
.n=".n"
|
||
|
.o=".o"
|
||
|
.p=".p"
|
||
|
.q=".q"
|
||
|
.r=".r"
|
||
|
.s=".s"
|
||
|
.t=".t"
|
||
|
.u=".u"
|
||
|
.v=".v"
|
||
|
.w=".w"
|
||
|
.x=".x"
|
||
|
.y=".y"
|
||
|
.z=".z"
|
||
|
;;;
|
||
|
run;
|
||
|
%end; %** end of if &s_ver.>=80 do loop **;
|
||
|
|
||
|
|
||
|
%** Write a SAS program to output the data to an ascii file. **;
|
||
|
data _null_;
|
||
|
set _conten end=lastobs;
|
||
|
%** Write to a SAS program to be inserted in this program later. **;
|
||
|
file "&temp_dir._&tfns._ascii.sas";
|
||
|
retain lvar ivar 0;
|
||
|
if _n_=1 then do;
|
||
|
%*** this fileref is used after success to delete this raw file **;
|
||
|
put "filename ________ ""&temp_dir._&tfns._.raw""; "; %** write out to an ascii file **;
|
||
|
put "data _null_; ";
|
||
|
put " set work.&dset. end=___lo___; ";
|
||
|
put " file ________ ls=2000; "; %** write out to an ascii file **;
|
||
|
end;
|
||
|
lvar=lvar+1;
|
||
|
ivar=ivar+1;
|
||
|
|
||
|
%* only here if NOT (&dy_and_dq_fail.=1 and "es.=0) **;
|
||
|
%if &dq_fail.=1 %then %do;
|
||
|
%** check for double quotes in only the character variables that need fixing **;
|
||
|
%** tranwrd makes the list of space separated char vars like: in("cvar1","cvar2")**;
|
||
|
if type=2 and _name_ in(%sysfunc(tranwrd("&dq_fix.",%nrstr( ),",")))
|
||
|
then put " if index(" _name_ ",compress(' "" ')) then ";
|
||
|
%if &dy_and_dq_fail.=0 and &u_ver.>=70 %then %do;
|
||
|
%** Make Maria happy. **;
|
||
|
%** and replace with &dyc. character which is a very unlikely character **;
|
||
|
if type=2 then put _name_ "=translate(" _name_ ",compress("" &dyc. ""),compress(' "" '));" ;
|
||
|
%end;
|
||
|
%else %if "es.=1 %then %do;
|
||
|
%** and replace with single quotes **;
|
||
|
if type=2 then put _name_ "=translate(" _name_ ",compress("" ' ""),compress(' "" '));" ;
|
||
|
%end;
|
||
|
%end; %** if dq_fail=1 then do loop **;
|
||
|
|
||
|
%if &s_ver.<80 %then %do; %** make all special missings equal to missing since pre-Stata 8 cannot handle them **;
|
||
|
if type=1 then put " if .< " _name_ "<=.z then " _name_ "=. ; ";
|
||
|
%end; %** if s_ver<80 or sm=0 then do loop **;
|
||
|
|
||
|
%if &s_ver.>=80 and &sm.=1 %then %do; %** make invalid special missings equal to missing **;
|
||
|
%** Stata can only handle special missing between .a and .z, **;
|
||
|
%* SAS also has " ._ " ***;
|
||
|
if type=1 then put " if " _name_ "<.a then " _name_ "=. ; ";
|
||
|
%end; %** if s_ver>=80 and sm=1 then do loop **;
|
||
|
|
||
|
if (lvar < 5 and ivar < &avars.) then do;
|
||
|
%** put the variable with the output format and put a space after each variable **;
|
||
|
%if &s_ver.>=80 and &sm.=1 %then %do; %** keep special missings special **;
|
||
|
if type=1 then put ' if .a<= ' _name_ '<=.z then put ' _name_ ' ___mi___. " " @;';
|
||
|
%end;
|
||
|
if type=1 then put ' if ' _name_ '<.a or ' _name_ '>.z then put ' _name_ oformat ' " " @;';
|
||
|
/** would work if Stata could infile compound quotes:
|
||
|
if type=2 then put ' put " `""" ' _name_ oformat ' """'' " " " @ ; ';
|
||
|
******/
|
||
|
if type=2 then put ' put " """ ' _name_ oformat ' """ " " " @ ; ';
|
||
|
end; %** of if (lvar < 5 and ivar < avars.) then do loop **;
|
||
|
else do;
|
||
|
%if &s_ver.>=80 and &sm.=1 %then %do; %** keep special missings special **;
|
||
|
if type=1 then put ' if .a<= ' _name_ '<=.z then put ' _name_ ' ___mi___. ;';
|
||
|
%end;
|
||
|
if type=1 then put ' if ' _name_ '<.a or ' _name_ '>.z then put ' _name_ oformat ' ;';
|
||
|
/** would work if Stata could infile compound quotes:
|
||
|
if type=2 then put ' put " `""" ' _name_ oformat ' """'' " ; ';
|
||
|
**/
|
||
|
if type=2 then put ' put " """ ' _name_ oformat ' """ " ; ';
|
||
|
lvar=0;
|
||
|
end; %** of if else (the 5th var) do loop **;
|
||
|
put " ";
|
||
|
if lastobs then do;
|
||
|
put "run; ";
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
%include "&temp_dir._&tfns._ascii.sas";
|
||
|
filename ________ clear; %** clear filename ref used in _tfns_ascii.sas **;
|
||
|
|
||
|
%** initialize maxvar **;
|
||
|
%let maxvar =0;
|
||
|
%let reclen=%eval(&reclen.);
|
||
|
%if (&s_ver.<80 or &s_SEver.=0) %then %do;
|
||
|
%if &avars.>2047 %then %goto fail15; %** &avars. is number of all variables **;
|
||
|
%else %if (&s_ver.<70) and &reclen.>8192 %then %goto fail16;
|
||
|
%else %if (&s_SEver.=0 or &s_ver.<80) and &reclen.>24564 %then %goto fail16;
|
||
|
%end;
|
||
|
%else %do; %** saving SE **;
|
||
|
%** The maximum width of a dataset in Stata SE is 12*maxvar. **;
|
||
|
%** The maximum number of variables for Stata SE is 32,767. **;
|
||
|
%** The maximum number of variables savastata can handle varies based on type of variables **;
|
||
|
%if &avars. > 32767 %then %goto fail24; %** Starting with SAS 9, SAS now allows more than 32,767 vars **;
|
||
|
%let maxreclen = %eval(&avars. * 12 );
|
||
|
%** The real max width for Stata is 393204 (=32767 * 12) not 393192 (= 32766 * 12) **;
|
||
|
%if &maxreclen. > 393204 %then %goto fail16;
|
||
|
%if &reclen. > 393204 %then %goto fail16;
|
||
|
%if &avars. < 32756 %then %do;
|
||
|
%** allow for more vars (10 percent of the difference of total amount of vars you can have) **;
|
||
|
%let maxvar = %eval(&avars. + %sysfunc(int((32766-&avars.) / 10)));
|
||
|
%end;
|
||
|
%else %if &avars. >= 32756 %then %do;
|
||
|
%let maxvar = %eval(&avars. + 1);
|
||
|
%end;
|
||
|
%if &avars.>32767 %then %goto fail24; %** This should not happen, but check it again **;
|
||
|
%if &maxvar.<=5000 %then %let maxvar=5000;
|
||
|
%if &maxvar.>32767 %then %goto fail16; %** This really means the dataset is too wide. **;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%let flavor= ; %** Initialize macro var **;
|
||
|
|
||
|
|
||
|
%* intrcool now only used for the Stata intercooled saving option which stopped being an option with Stata 10 **;
|
||
|
%if &u_ver.>=100 %then %let intrcool= ; %** make sure it is blank if Stata 10 or higher **;
|
||
|
|
||
|
|
||
|
%** Write do-file to read in data. **;
|
||
|
data _null_;
|
||
|
set _conten end=lastobs;
|
||
|
%** Write to a Stata do-file. **;
|
||
|
file "&temp_dir._&tfns._infile.do" ls=2000; %* ls=256 is default *;
|
||
|
if _n_=1 then do;
|
||
|
/****************************************************************
|
||
|
# Figure out memory requirements.
|
||
|
# Use a slightly modified version of the formula Stata suggests to figure
|
||
|
# out how much memory is needed.
|
||
|
# STATA_s formula: N*V*W + 4*N
|
||
|
# M = --------------
|
||
|
# 1024 * 1024
|
||
|
# N = number observations
|
||
|
# V = number of variables
|
||
|
# W = average width in bytes of a variable
|
||
|
# M = number of megabytes
|
||
|
# savastata_s formula:
|
||
|
****************************************************************/
|
||
|
%** record length is number of variables times average variable width **;
|
||
|
statamem= &nobs.*(&reclen. + (&reclen./4)) + (4*&nobs.) ; %** "+ (&reclen./4)" adds about 25 percent for good measure **;
|
||
|
%if &u_ver.>=80 %then %do;
|
||
|
put " if `c(memory)' < " statamem " { "; %** c(memory) is in bytes and statamem is also at this point **;
|
||
|
%end;
|
||
|
%** Convert STATAMEM bytes to megabytes **;
|
||
|
statamem=int(statamem / 1024**2);
|
||
|
%** Make sure memory is set to at least 20 megabytes **;
|
||
|
if (statamem< 20) then statamem=20;
|
||
|
mem=compress(statamem||"m");
|
||
|
put " set memory " mem;
|
||
|
%if &u_ver.>=80 %then %do;
|
||
|
put " } "; %** end of if memory setting is less than needed **;
|
||
|
%end;
|
||
|
%if &maxvar.>5000 %then %do; %** but only reset if not high enough (for -usesas- or user_s default setting) **;
|
||
|
put " if `c(max_k_current)' < &maxvar. set maxvar &maxvar. ";
|
||
|
%end;
|
||
|
put " #delimit ; ";
|
||
|
put " infile ";
|
||
|
end; %** end of if _n_=1 do loop **;
|
||
|
put ' ' stype name ;
|
||
|
if lastobs then do;
|
||
|
put " using ""&temp_dir._&tfns._.raw"" ";
|
||
|
put ';;;';
|
||
|
put ' ';
|
||
|
put ' #delimit cr ';
|
||
|
%** replace dyc char with double quote only in char vars that need fixing **;
|
||
|
%if &dq_fail.=1 and &dy_and_dq_fail.=0 and &u_ver.>=70 %then %do;
|
||
|
put "foreach svar of varlist &dq_fix. { ";
|
||
|
put " replace `svar' = subinstr(`svar',""&dyc."",`""""""',.) ";
|
||
|
put '} ';
|
||
|
%end;
|
||
|
put " do ""&temp_dir._&tfns._labels.do"""; %** This will call the next do-file. **;
|
||
|
put " do ""&temp_dir._&tfns._fix.do"""; %** This will call the next do-file. **;
|
||
|
put " do ""&temp_dir._&tfns._formats.do"""; %** This will call the next do-file. **;
|
||
|
%if &vlabels.=1 %then %do;
|
||
|
put " do ""&temp_dir._&tfns._dlabels.do"""; %** This will call the next do-file. **;
|
||
|
put " do ""&temp_dir._&tfns._vlabels.do"""; %** This will call the next do-file. **;
|
||
|
%end;
|
||
|
|
||
|
put " ";
|
||
|
%if "&sysscp."="WIN" %then %do;
|
||
|
put " global S_FN ""\&fdset..dta"" ";
|
||
|
%end;
|
||
|
%else %do;
|
||
|
put " global S_FN ""/&fdset..dta"" ";
|
||
|
%end;
|
||
|
put " label data ""&crdate."" ";
|
||
|
|
||
|
%******* save Stata dataset *********************************;
|
||
|
%*----------------------------------------------------------*;
|
||
|
%if "&script." ^= "usesas" %then %do;
|
||
|
put 'if _caller()<8 { ';
|
||
|
put ' quietly describe ';
|
||
|
put ' local obs=`r(N)'' ';
|
||
|
put ' local vars=`r(k)'' ';
|
||
|
put " } ";
|
||
|
put " else { ";
|
||
|
put ' local obs=`c(N)'' ';
|
||
|
put ' local vars=`c(k)'' ';
|
||
|
put " } ";
|
||
|
|
||
|
put " if `obs' == &nobs. & `vars' == &AVARS. { "; %** only save if successful **;
|
||
|
%** not saving will still allow checking data **;
|
||
|
%** add another back slash to directories that start with a back slash, as Stata **;
|
||
|
%* drops the first back slash because it sees it as an escape character. **;
|
||
|
%if %index(%nrbquote(&out_dir.),\)=1 %then %do;
|
||
|
if &u_ver.<80 then put " save ""\&out_dir.&fdset..dta"", &old. &intrcool. &replace. ";
|
||
|
else if &u_ver.>=80 then put " save&old. ""\&out_dir.&fdset..dta"", &intrcool. &replace. ";
|
||
|
%end;
|
||
|
%else %do;
|
||
|
if &u_ver.<80 then put " save ""&out_dir.&fdset..dta"", &old. &intrcool. &replace. ";
|
||
|
else if &u_ver.>=80 then put " save&old. ""&out_dir.&fdset..dta"", &intrcool. &replace. ";
|
||
|
%end;
|
||
|
put " } " ; %** end of if obs and vars match SAS dataset **;
|
||
|
%if &ascii.=0 and &u_ver.>=70 %then %do;
|
||
|
put " set linesize 100 "; %** -usesas- should not reset linesize **;
|
||
|
%end;
|
||
|
%end; %** of script ^= "usesas" do loop **;
|
||
|
%*** end save Stata dataset *********************************;
|
||
|
%*----------------------------------------------------------*;
|
||
|
|
||
|
%if "&script." = "usesas" %then %do;
|
||
|
put "capture program drop savastata_report ";
|
||
|
put "program savastata_report ";
|
||
|
put " if `c(N)' != &nobs | `c(k)' != &AVARS. { ";
|
||
|
put " noisily { ";
|
||
|
put " di _n ""{txt}SAS reports that the input dataset has {res}&nobs. {txt}observations "" /* ";
|
||
|
put " */ ""and {res}&AVARS. {txt}variables "" ";
|
||
|
put ' di "{txt}but Stata reports that the dataset has {res}`c(N)'' {txt}observations " /* ';
|
||
|
put ' */ "and {res}`c(k)'' {txt}variables " ';
|
||
|
put ' di as err "{help usesas:usesas} was unable to read in your SAS data correctly." ';
|
||
|
put ' di as err "Does your data contain non-roman characters?" ';
|
||
|
put ' di as err "SAVASTATA writes the data to ascii and non-roman characters mess that up." ';
|
||
|
put ' di as err "If you want to check out the intermediary files generated " ';
|
||
|
put ' di as err "by -usesas- in order to check out why -usesas- failed, " ';
|
||
|
put ' di as err "try -usesas- again using the {text}messy {error}option. " ';
|
||
|
put " } ";
|
||
|
put " drop _all // clear data from memory ";
|
||
|
put " } ";
|
||
|
put ' else noi di _n "{txt}Stata reports that the dataset has {res}`c(N)'' {txt}observations " /* ';
|
||
|
put ' */ "and {res}`c(k)'' {txt}variables. " ';
|
||
|
put "end";
|
||
|
%end; %** of script = "usesas" do loop **;
|
||
|
|
||
|
%if &ascii.=0 %then %do; %** -usesas- runs checks the Stata data inside the usesas.ado file **;
|
||
|
%if "&script." ^= "usesas" %then %do; %** -usesas- already knows if it loaded data correctly or not **;
|
||
|
put " capture program drop __save__ ";
|
||
|
put " program define __save__, nclass ";
|
||
|
put " args obs vars ";
|
||
|
put " capture log close ";
|
||
|
%if &check.=1 %then %do;
|
||
|
%** If a directory starts with a back slash, Stata likes to remove it. **;
|
||
|
%if %index(%nrbquote(&out_dir.),\)=1 %then %do;
|
||
|
put "&quietly. log using ""\&out_dir.&fdset._STATAcheck.log"", replace ";
|
||
|
%end;
|
||
|
%else %do;
|
||
|
put "&quietly. log using ""&out_dir.&fdset._STATAcheck.log"", replace ";
|
||
|
%end;
|
||
|
put " &noisily. display "" "" ";
|
||
|
put " &noisily. display as res ""** Compare these results with the results provided by SAS **"" ";
|
||
|
put " &noisily. display ""** in the file &out_dir.&fdset._SAScheck.lst. **"" ";
|
||
|
put " &noisily. display "" "" ";
|
||
|
put " &noisily. summarize ";
|
||
|
put " &noisily. describe ";
|
||
|
put " &noisily. list in 1/5";
|
||
|
put " capture log close ";
|
||
|
%end; %** of if check=1 do loop **;
|
||
|
put " ** If this file exists then Stata successfully saved &fdset..dta ** ";
|
||
|
put " quietly log using ""&temp_dir._&tfns._done.log"" ";
|
||
|
put " ** If this file exists then Stata successfully saved &fdset..dta ** ";
|
||
|
put ' display "%macro _______v;" ';
|
||
|
put ' display " %let SE=$S_StataSE ; " ';
|
||
|
put ' display " %let MP=$S_StataMP ; " ';
|
||
|
put ' display " %if &MP.=MP %then %let SE=SE ; " ';
|
||
|
put ' display " %let flavor=$S_FLAVOR; " ';
|
||
|
put ' display " %let version=%sysfunc(int(" _caller() ")); " ';
|
||
|
put ' display " %if &SE.=SE and &s_SEver=0 %then %let flavor=Intercooled; " ';
|
||
|
put ' display " %if &SE.=SE and &s_SEver.=1 and &s_ver.>=70 %then %let flavor=SE; " ';
|
||
|
%********* Stata version 9 is only version that saved to 2 versions previous **;
|
||
|
put ' display " %if &old.=old and &version.=9 %then %let version=%eval(&version.-2);" ';
|
||
|
put ' display " %else %if &old.=old %then %let version=%eval(&version.-1);" ';
|
||
|
put ' display " options notes; " ';
|
||
|
put " if `obs' != &nobs. | `vars' != &AVARS. { "; %** failed possibly due to non-roman characters **;
|
||
|
put ' di "%put %upcase(error): SAVASTATA was unable to save your SAS data correctly. *;" ';
|
||
|
put ' di "%put Does your data contain non-roman characters? *;" ';
|
||
|
put " di ""%nrstr(%put) SAS reports that the input dataset has &nobs. observations and &AVARS. variables. *; "" ";
|
||
|
put ' di "%put but Stata reports that the dataset has `obs'' observations and `vars'' variables. *; " ';
|
||
|
put ' di "%let fail23=1;" ';
|
||
|
put ' } ';
|
||
|
put ' else { '; %** success! **;
|
||
|
put ' di "%put NOTE: SAVASTATA has successfully saved the *; " ';
|
||
|
put ' di "%put Stata &version. &flavor data file &out_dir.&fdset..dta. *; " ';
|
||
|
put ' di "%put Stata reports that the dataset has `obs'' observations and `vars'' variables. *; " ';
|
||
|
put ' } ';
|
||
|
put ' if _caller() >= 8 { '; %** usagelog only works in version 8+ **;
|
||
|
put " capture which usagelog";
|
||
|
put " if _rc==0 {";
|
||
|
put " usagelog , type(savas) message(Output Stata dataset has `obs' obs and `vars' vars)";
|
||
|
put " }";
|
||
|
put " }";
|
||
|
|
||
|
|
||
|
%if &check.=1 %then %do;
|
||
|
put ' di "%put *; " ';
|
||
|
put ' di "%put You have requested to have SAVASTATA provide 2 check files: *; " ';
|
||
|
put ' di "%put ""&out_dir.&fdset._SAScheck.lst"" and *; " ';
|
||
|
put ' di "%put ""&out_dir.&fdset._STATAcheck.log"" *; " ';
|
||
|
put ' di "%put *; " ';
|
||
|
%end; %** if check=1 then do loop **;
|
||
|
put ' display " %mend _______v; " ';
|
||
|
put ' display " %_______v; " ';
|
||
|
put "quietly capture log close";
|
||
|
put "end "; %** end of defining program __save__ **;
|
||
|
put "&noisily. __save__ `obs' `vars'";
|
||
|
%end; %** of script ^= "usesas" do loop **;
|
||
|
%end; %** of if &ascii.=0 do loop **;
|
||
|
end; %** if last_obs do loop **;
|
||
|
run;
|
||
|
|
||
|
%** Write the Stata label do-file ***;
|
||
|
data _null_;
|
||
|
set _conten;
|
||
|
%** start a new Stata do-file **;
|
||
|
file "&temp_dir._&tfns._labels.do"; %* this is just max 32 char varname and 32 char label name *;
|
||
|
if _n_=1 then do;
|
||
|
put " ** This do-file assigns variable labels ** ";
|
||
|
end;
|
||
|
if label^="" then put ' label var ' name ' `"' label '"'' ';
|
||
|
%if %length(%qcmpres(%nrbquote(&llabvars.))) > 0 %then %do;
|
||
|
if lowcase(name) in(&llabvars.) then
|
||
|
put ' notes ' name ': ' llabel ; %** enclosing in compound double quotes does not help **;
|
||
|
%end;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%** Write the Stata fix do-file. ***;
|
||
|
data _null_;
|
||
|
set _conten end=lastobs;
|
||
|
file "&temp_dir._&tfns._fix.do"; %** start a new Stata do-file **;
|
||
|
if _n_=1 then do;
|
||
|
%** If a directory starts with a back slash, Stata likes to remove it. **;
|
||
|
put " ** This do-file replaces empty strings with null values. ** ";
|
||
|
end;
|
||
|
if type=2 then put ' replace ' name '="" if ltrim(' name ')=="" ';
|
||
|
run;
|
||
|
|
||
|
%** SAS defined format do-file ***;
|
||
|
data _null_;
|
||
|
set _conten end=lastobs;
|
||
|
%** start a new Stata do-file **;
|
||
|
file "&temp_dir._&tfns._formats.do"; %* This is just 32 max varname and 32 max format name *;
|
||
|
if _n_=1 then do;
|
||
|
put " ** This do-file assigns variables formats. ** ";
|
||
|
end;
|
||
|
if format^="default" then put ' format ' name format;
|
||
|
if lastobs then do;
|
||
|
put ' ';
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%if &vlabels.=1 %then %do;
|
||
|
|
||
|
%** If there are user defined formats try to save as many as possible. **;
|
||
|
%if &workfmts.=1 and &librfmts.=1 %then %do;
|
||
|
%let fb=1;
|
||
|
%let fe=2;
|
||
|
%end;
|
||
|
%else %if &workfmts.=1 and &librfmts.=0 %then %do;
|
||
|
%let fb=1;
|
||
|
%let fe=1;
|
||
|
%end;
|
||
|
%else %if &workfmts.=0 and &librfmts.=1 %then %do;
|
||
|
%let fb=2;
|
||
|
%let fe=2;
|
||
|
%end;
|
||
|
|
||
|
%do i=&fb. %to &fe.;
|
||
|
%if &i.=1 %then %do;
|
||
|
%let flibr=work;
|
||
|
%end;
|
||
|
%else %if &i.=2 %then %do;
|
||
|
%let flibr=library;
|
||
|
%end;
|
||
|
proc format library=&flibr. cntlout=_conten&i.(keep=type fmtname start end label);
|
||
|
run;
|
||
|
|
||
|
proc sort data=_conten&i.(rename=(fmtname=format label=fmtlabel));
|
||
|
by format;
|
||
|
%if &sm.=0 %then %do;
|
||
|
%** Stata can only handle formats of integers. **;
|
||
|
where not index(start,".") and not index(end,".")
|
||
|
%** Stata can not handle formats of **OTHER**. **;
|
||
|
and upcase(start)^='**OTHER**'
|
||
|
and upcase(start) not in('LOW','HIGH')
|
||
|
and upcase(end) not in('LOW','HIGH')
|
||
|
%*********************************************************;
|
||
|
%** formats with ranges using LOW, HIGH and OTHER **;
|
||
|
%** could aplly to multiple variables **;
|
||
|
%*********************************************************;
|
||
|
%** Stata can only handle formats of numeric vars. **;
|
||
|
and upcase(type)="N";
|
||
|
run;
|
||
|
%end; %** if sm=0 then do loop **;
|
||
|
|
||
|
%else %if &sm.=1 %then %do;
|
||
|
where upcase(type)="N"; %** Stata can only handle formats of numeric vars. **;
|
||
|
run;
|
||
|
|
||
|
data _conten&i.;
|
||
|
set _conten&i.;
|
||
|
fine=0;
|
||
|
%** If both start and end are special missing that is okay, ranges now okay. **;
|
||
|
if (upcase(compress(start))>=".A" and upcase(compress(start))<=".Z")
|
||
|
and (upcase(compress(end))>=".A" and upcase(compress(end))<=".Z") then do;
|
||
|
start=lowcase(start);
|
||
|
end=lowcase(end);
|
||
|
fine=1;
|
||
|
end;
|
||
|
else %** Stata can only handle formats of integers. **;
|
||
|
if not index(start,".") and not index(end,".")
|
||
|
and upcase(start)^='**OTHER**'
|
||
|
and upcase(start) not in('LOW','HIGH')
|
||
|
and upcase(end) not in('LOW','HIGH')
|
||
|
%*********************************************************;
|
||
|
%** formats with ranges using LOW, HIGH and OTHER **;
|
||
|
%** could aplly to multiple variables **;
|
||
|
%*********************************************************;
|
||
|
then fine=1;
|
||
|
if fine=1;
|
||
|
run;
|
||
|
%end; %** if sm=1 then do loop **;
|
||
|
|
||
|
%end; %** do i=&fb. to &fe. **;
|
||
|
|
||
|
|
||
|
%if &workfmts.=1 and &librfmts.=1 %then %do;
|
||
|
%** If there are both work formats and library formats, choose work over library. **;
|
||
|
data _conten3;
|
||
|
merge _conten1(in=a keep=format)
|
||
|
_conten2(in=b keep=format);
|
||
|
by format;
|
||
|
%** Find ones in common so that formats in library.formats can be excluded. **;
|
||
|
if a and b;
|
||
|
run;
|
||
|
|
||
|
data _conten3;
|
||
|
set _conten3;
|
||
|
by format;
|
||
|
%** Reduce to just one obs per format. **;
|
||
|
if first.format;
|
||
|
run;
|
||
|
|
||
|
data _conten2;
|
||
|
merge _conten3(in=a keep=format)
|
||
|
_conten2(in=b);
|
||
|
by format;
|
||
|
%** Exclude formats in work.library that are also in work.formats. **;
|
||
|
if not a;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%** Concatenate the two sets of formats. **;
|
||
|
proc sort data=_conten1;
|
||
|
by format start;
|
||
|
run;
|
||
|
proc sort data=_conten2;
|
||
|
by format start;
|
||
|
run;
|
||
|
|
||
|
data _conten1;
|
||
|
set _conten1
|
||
|
_conten2;
|
||
|
by format start;
|
||
|
run;
|
||
|
|
||
|
%end; %** if workfmts=1 and librfmts=1 then do loop **;
|
||
|
|
||
|
|
||
|
%if &workfmts.=0 and &librfmts.=1 %then %do;
|
||
|
data _conten1;
|
||
|
set _conten2;
|
||
|
run;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
proc sort data=_conten(keep=type varnum format name orig_fmt
|
||
|
where=(format="default"))
|
||
|
out=_conten(drop=format rename=(orig_fmt=format));
|
||
|
by orig_fmt;
|
||
|
run;
|
||
|
|
||
|
data _conten3;
|
||
|
merge _conten(in=a keep=format)
|
||
|
_conten1(in=b keep=format);
|
||
|
by format;
|
||
|
%** Only keep the formats used in the dataset. **;
|
||
|
if a and b;
|
||
|
run;
|
||
|
|
||
|
data _conten3;
|
||
|
set _conten3;
|
||
|
by format;
|
||
|
%** Reduce to one obs per format. **;
|
||
|
if first.format;
|
||
|
run;
|
||
|
|
||
|
data _conten1;
|
||
|
merge _conten3(in=a keep=format)
|
||
|
_conten1(in=b);
|
||
|
by format;
|
||
|
if a and b; %** Only keep the numeric formats used in the dataset. **;
|
||
|
run;
|
||
|
|
||
|
|
||
|
%** Make an attempt to save some of the other formats. **;
|
||
|
%** first check to see if any will be truncated **;
|
||
|
%let labtrunc = 0;
|
||
|
data _null_;
|
||
|
set _conten1; %** _conten1 contains only numeric formats for numeric vars **;
|
||
|
%** Stata can only handle value labels up to &maxvallablen. characters. **;
|
||
|
if length(fmtlabel) > &maxvallablen. then call symput('labtrunc',"1");
|
||
|
run;
|
||
|
|
||
|
%if &labtrunc.=1 %then %do;
|
||
|
%put %upcase(warning): SAVASTATA truncated at least one format label because it contained more than &maxvallablen. characters. *;
|
||
|
%end;
|
||
|
|
||
|
data _null_;
|
||
|
%** Increase length to allow for compound quotes to be attached later. **;
|
||
|
length fmtlabel $%eval(&maxvallablen.+500);
|
||
|
set _conten1 (where=(fmtlabel^="")) end=lastobs ;
|
||
|
%** stata cannot handle empty value labels **;
|
||
|
|
||
|
by format;
|
||
|
file "&temp_dir._&tfns._dlabels.do" ls=32200; %** start a new Stata do-file **;
|
||
|
if _n_=1 then do;
|
||
|
put " ** This do-file defines value labels. ** ";
|
||
|
end;
|
||
|
%** nstart and nend have to be numeric. they are only used in ranges **;
|
||
|
nstart=start*1;
|
||
|
nend=end*1;
|
||
|
%** format byte is okay but not as nice as the same as the var name BYTE **;
|
||
|
if upcase(format) not in(&bstatavs.) then format=lowcase(format);
|
||
|
%** make sure fmtlabel not longer than max **;
|
||
|
fmtlabel=substr(fmtlabel,1,&maxvallablen.); %** need to test length before escaping $ and \ **;
|
||
|
%** prepare fmtlabel to be written to _dlabels.do **;
|
||
|
|
||
|
%** value labels cannot end in a left quote even if it is escaped **;
|
||
|
if length(fmtlabel)=1 and
|
||
|
substr(fmtlabel,length(fmtlabel),length(fmtlabel)) = "`" then
|
||
|
fmtlabel="'"; %** replace with right quote **;
|
||
|
else if substr(fmtlabel,length(fmtlabel),length(fmtlabel)) = "`" then
|
||
|
fmtlabel=substr(fmtlabel,1,length(fmtlabel)-1)||"'"; %** replace with right quote **;
|
||
|
%** the above can create right compound quotes **;
|
||
|
|
||
|
%** value labels cannot contain either a left or right compound quote **;
|
||
|
if index(fmtlabel,compress("`"||' " ')) or
|
||
|
index(fmtlabel,compress('"'||" ' ")) then do;
|
||
|
call symput("cq","1"); %** Format contains a compound quote. **;
|
||
|
%if "es.=1 %then %do;
|
||
|
fmtlabel = tranwrd(fmtlabel,"`"||'"',"''"); %* replace left compound quote with two single quotes *;
|
||
|
fmtlabel = tranwrd(fmtlabel,'"'||"'","''"); %* replace right compound quote with two single quotes *;
|
||
|
%end;
|
||
|
end;
|
||
|
|
||
|
%if &u_ver. < 90 or "&script." = "usesas" %then %do;
|
||
|
%** replace two back slashes with four **;
|
||
|
if index(fmtlabel,"\\") then fmtlabel = tranwrd(fmtlabel,"\\","\\\\");
|
||
|
%end;
|
||
|
|
||
|
%** escape all left quotes (already know they are not left compound quotes) **;
|
||
|
if index(fmtlabel,"`") then fmtlabel = tranwrd(fmtlabel,"`","\`");
|
||
|
%** escape all dollar signs **;
|
||
|
if index(fmtlabel,"$") then fmtlabel = tranwrd(fmtlabel,"$","\$");
|
||
|
/** replace \\` with \\' since stata hates \\` **/
|
||
|
if index(fmtlabel,"\\`") then fmtlabel = tranwrd(fmtlabel,"\\`","\\'");
|
||
|
%** the above cannot create a right compound quote **;
|
||
|
|
||
|
%** One format can be assigned to many variables. **;
|
||
|
%** new way of defining each value and adding if more than 1 **;
|
||
|
%* because long value labels can make Stata unable to find end quote. **;
|
||
|
%* the added bonus is that a semicolon in a label will not throw off Stata **;
|
||
|
%*****;
|
||
|
|
||
|
%* add compound quotes at beginning and end of fmtlabel *;
|
||
|
fmtlabel = " `"""|| trim(fmtlabel) ||"""' " ;
|
||
|
|
||
|
%** value labels are stored as datatype long. **;
|
||
|
if .z < nstart < &longmin. then nstart = &longmin. ;
|
||
|
if nend > &longmax. then do;
|
||
|
nend = &longmax.;
|
||
|
end;
|
||
|
|
||
|
if start = end then do;
|
||
|
%** start and end could equal "**OTHER**" and will only be assigned to **;
|
||
|
%* the first "other" value. Not able to replicate OTHER in Stata. **;
|
||
|
if first.format then do;
|
||
|
j=1; %** for counting inside ranges. one format can only have 65,536 values **;
|
||
|
put " label define " format start fmtlabel ;
|
||
|
end;
|
||
|
else do;
|
||
|
j=j+1;
|
||
|
if j <= 65536 then
|
||
|
put " label define " format start fmtlabel " , add " ;
|
||
|
end;
|
||
|
end;
|
||
|
else if ( nstart > .z and nend > .z ) then do i=nstart to nend;
|
||
|
if first.format and i=nstart then do;
|
||
|
j=1; %** for counting inside ranges. one format can only have 65,536 values **;
|
||
|
put " label define " format i fmtlabel ;
|
||
|
end;
|
||
|
else do;
|
||
|
j=j+1;
|
||
|
if j <= 65536 then
|
||
|
put " label define " format i fmtlabel " , add " ;
|
||
|
end;
|
||
|
end;
|
||
|
else if (compress(start)>=".a" and compress(start)<=".z")
|
||
|
and (compress(end)>=".a" and compress(end)<=".z") then do;
|
||
|
cstart = substr(lowcase(compress(start)),2,1);
|
||
|
%** Stata does not allow special missing ._ **;
|
||
|
nstart = index("abcdefghijklmnopqrstuvwxyz",compress(cstart));
|
||
|
cend = substr(lowcase(compress(end)),2,1);
|
||
|
nend = index("abcdefghijklmnopqrstuvwxyz",compress(cend));
|
||
|
do i = nstart to nend;
|
||
|
_sm_ = compress("." || substr("abcdefghijklmnopqrstuvwxyz",i,1));
|
||
|
if first.format and i=nstart then do;
|
||
|
j=1; %** for counting inside ranges. one format can only have 65,536 values **;
|
||
|
put " label define " format _sm_ fmtlabel ;
|
||
|
end;
|
||
|
else do;
|
||
|
j=j+1;
|
||
|
if j <= 65536 then
|
||
|
put " label define " format _sm_ fmtlabel " , add " ;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
run;
|
||
|
|
||
|
%if &cq.=1 and "es.=0 %then %goto fail17; %** at least one format contains a compound quote. **;
|
||
|
|
||
|
data _conten;
|
||
|
merge _conten(in=a keep=type varnum name format)
|
||
|
_conten3(in=b keep=format);
|
||
|
by format;
|
||
|
if a and b; %** Keep only the variables assigned to these formats. **;
|
||
|
run;
|
||
|
|
||
|
data _null_;
|
||
|
set _conten (where=(type=1)) end=lastobs; %** can only format numeric variables **;
|
||
|
%** start a new Stata do-file **;
|
||
|
file "&temp_dir._&tfns._vlabels.do"; %** this is just a max 32 char varname and *;
|
||
|
%* 32 char user-defined label name *;
|
||
|
if _n_=1 then do;
|
||
|
put " ** This do-file assigns value labels. ** ";
|
||
|
end;
|
||
|
if upcase(format) not in(&bstatavs.) then format=lowcase(format);
|
||
|
put 'label value ' name format;
|
||
|
run;
|
||
|
|
||
|
%end; %** of if vlabels=1 then do loop **;
|
||
|
|
||
|
|
||
|
%if "&script." ^= "usesas" %then %do;
|
||
|
%let u_sysrc=0; %** initialize macro var **;
|
||
|
%let w_sysrc=0; %** initialize macro var **;
|
||
|
%if &ascii.=0 %then %do;
|
||
|
%if &unix.=1 %then %do;
|
||
|
%** This submits the Stata do-file that reads in the ascii dataset that becomes the Stata dataset. ***;
|
||
|
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
|
||
|
%sysexec cd %nrbquote(&work_dir.) ; %** change to the drive and directory where the Stata do-files are. **;
|
||
|
|
||
|
%** Run Stata in batch. from within the directory where the temp files are. **;
|
||
|
%sysexec %nrbquote(&ustata.) -b do "_&tfns._infile.do";
|
||
|
%let u_sysrc=&sysrc.; %** store value of sysrc until after if ascii=0 do loop **;
|
||
|
%end; %** if unix=1 then do loop **;
|
||
|
|
||
|
%if &unix.=0 %then %do;
|
||
|
%sysexec &drive.;
|
||
|
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
|
||
|
%sysexec cd %nrbquote(&work_dir.) ;
|
||
|
%** Run Stata in batch. **;
|
||
|
%sysexec "&wstata." /e do "&temp_dir._&tfns._infile.do";
|
||
|
%let w_sysrc=&sysrc.; %** store value of sysrc until after if ascii=0 do loop **;
|
||
|
%end; %** if unix=0 then do loop **;
|
||
|
%end; %** if ascii=0 then do loop. Do not run Stata if only want ascii dataset **;
|
||
|
%if &u_sysrc.^=0 %then %goto fail21;
|
||
|
%if &w_sysrc.^=0 %then %do;
|
||
|
%if &u_ver.<80 and &w_sysrc.=17 %then %let w_sysrc=0;
|
||
|
%else %if &u_ver.<90 and &w_sysrc.=2180 %then %let w_sysrc=0;
|
||
|
%if &w_sysrc.^=0 %then %goto fail20;
|
||
|
%end;
|
||
|
%end; %** of script ^= "usesas" do loop **;
|
||
|
|
||
|
%let fail23=0;
|
||
|
%if (&isysver.<7 and &ascii.=0) or (&ascii.=0 and %sysfunc(fileexist("&temp_dir._&tfns._done.log"))) %then %do;
|
||
|
%include"&temp_dir._&tfns._done.log"; %** Run report program written by Stata. **;
|
||
|
%if &fail23.=1 %then %goto fail23;
|
||
|
%let success=1;
|
||
|
%end;
|
||
|
%if &ascii.=1 and %sysfunc(fileexist("&out_dir._&tfns._.raw")) %then %do;
|
||
|
%let success=1;
|
||
|
%end;
|
||
|
|
||
|
%if &success.=0 and "&nosave."="" %then %goto fail19;
|
||
|
|
||
|
|
||
|
|
||
|
%********* delete intermediary files when successful *********************;
|
||
|
options nonotes;
|
||
|
%if &success.=1 and &ascii.=0 and &messy.=0 %then %do;
|
||
|
%** at least delete the biggest file which is the ascii data file **;
|
||
|
data _null_;
|
||
|
fname="________";
|
||
|
rc =0;
|
||
|
if rc = 0 and fexist(fname) then
|
||
|
rc=fdelete(fname);
|
||
|
run;
|
||
|
%end; %** if ascii=0 do loop **;
|
||
|
options notes;
|
||
|
%********* (end of) delete intermediary files when successful **************;
|
||
|
|
||
|
%goto okay;
|
||
|
|
||
|
|
||
|
%** The following are all the failure messages returned to the user when the macro **;
|
||
|
%* is unable to process the input SAS dataset. **;
|
||
|
%fail1:
|
||
|
%put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%if "%sysfunc(lowcase(&dset.))"="_null_" %then %do;
|
||
|
%put You do not have a SAS dataset in the WORK library for * ;
|
||
|
%put SAVASTATA to convert to Stata. * ;
|
||
|
%end;
|
||
|
%else
|
||
|
%put The input dataset &dset. has to be in the WORK library. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%** SAS 8 will put a note at the end of the log stating what page errors **;
|
||
|
%* occurred but earlier versions do not. So insert bad code to generate an error. **;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=1;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail2: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put You have set u_ver=&u_ver., s_ver=&s_ver., u_SEver=&u_SEver. and s_SEver=&s_SEver. * ;
|
||
|
%put which is invalid. Perhaps edit savastata.sas to set all these vars to 0 (zero)? * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=2;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail3: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The dataset cannot be named &fdset. * ;
|
||
|
%put SAVASTATA uses this dataset name. * ;
|
||
|
%put Consider renaming the dataset. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=3;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail4: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put You did not tell SAVASTATA what directory you want to save the Stata dataset. * ;
|
||
|
%put Your call to SAVASTATA should look something like this: * ;
|
||
|
%put %nrstr(%%)savastata(C:\mydata\,-replace) * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=4;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail5: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The directory %nrbquote(&out_dir.) does not exist. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=5;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail6: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put You can only choose to save one type of dataset. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=6;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail7: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The dataset %nrbquote(&out_dir.)&fdset..dta already exists. * ;
|
||
|
%put If you want to overwrite this file, then use the SAVASTATA option "-replace". * ;
|
||
|
%put Like: %nrstr(%%)savastata(%nrbquote(&out_dir.),-replace &options.)%nrstr(;) ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=7;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail8: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put Your dataset &dset. contains a variable named _N which is not a valid * ;
|
||
|
%put variable name in Stata. Consider renaming it to a valid Stata * ;
|
||
|
%put variable name or dropping the variable from the SAS dataset. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put ;
|
||
|
%let fail=8;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail9: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The input dataset &dset. cannot contain a variable named &bvar. * ;
|
||
|
%put because SAVASTATA uses this name. * ;
|
||
|
%put Either rename the variable or drop it. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=9;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail10: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put At least one variable label in input dataset &dset. contains a compound quote ( %nrquote(%str(`%") or %str(%")%nrstr(%')) ). * ;
|
||
|
%put This is not allowed by SAVASTATA. * ;
|
||
|
%put Consider replacing any compound quotes with two single quotes ( %nrquote(%str(%'%')) ) using * ;
|
||
|
%put the "quotes" option. * ;
|
||
|
%if "&script." = "" %then %do;
|
||
|
%put Like: %nrstr(%%)savastata(%nrbquote(&out_dir.),-quotes &options.)%nrstr(;) ;
|
||
|
%end;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=10;
|
||
|
%goto okay;
|
||
|
|
||
|
|
||
|
%fail11: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put SAVASTATA tried to rename the variable names that are 9 or more characters * ;
|
||
|
%put to valid Stata 6 variable names (8 or less characters). SAVASTATA was * ;
|
||
|
%put unable to come up with unique variables names. * ;
|
||
|
%put Rename the long variable names to 8 characters or less and try SAVASTATA again. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=11;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail12: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The input dataset &dset. has no variables. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=12;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail13: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The input dataset &dset. has no observations. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=13;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail14: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put At least one character variable in the input dataset &dset. contains a double quote ( %nrquote(%str(%")) ). * ;
|
||
|
%put This is not allowed by SAVASTATA. * ;
|
||
|
%put Consider replacing any double quotes with a single quote ( %nrquote(%str(%')) ) by using * ;
|
||
|
%put the "quotes" option. * ;
|
||
|
%if "&script." = "" %then %do;
|
||
|
%put Like: %nrstr(%%)savastata(%nrbquote(&out_dir.),-quotes &options.)%nrstr(;) ;
|
||
|
%end;
|
||
|
%put The following is a list of all character variables in your dataset that * ;
|
||
|
%put contain double quotes: * ;
|
||
|
data _conten1;
|
||
|
set &dset. end=___lo___;
|
||
|
keep _character_; %** keep only character variables **;
|
||
|
array ___ch___ ( &VAR_C. ) _temporary_;
|
||
|
array ___cv___( &VAR_C. ) _character_ ; %** all character variables in dataset **;
|
||
|
do _n_=1 to &VAR_C.;
|
||
|
if index(___cv___[_n_],compress(' " ')) then
|
||
|
___ch___[_n_]=1;
|
||
|
end;
|
||
|
if ___lo___;
|
||
|
do _n_=1 to &VAR_C.;
|
||
|
___cv___[_n_]=___ch___[_n_];
|
||
|
end;
|
||
|
run;
|
||
|
proc transpose data =_conten1 out=_conten1;
|
||
|
var _all_;
|
||
|
run;
|
||
|
data _null_;
|
||
|
set _conten1;
|
||
|
if compress(col1)="1";
|
||
|
_name_=lowcase(_name_);
|
||
|
put " " _name_ " * ";
|
||
|
run;
|
||
|
%put *;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=14;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail15: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put Only Stata SE can handle more than 2,047 variables. * ;
|
||
|
%let avars=%sysfunc(putn(&avars.,comma32.));
|
||
|
%put You have &avars. variables in dataset &dset.. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=15;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail16: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The input dataset &dset. exceeds the width limit of the version of Stata you * ;
|
||
|
%put are using or saving to. * ;
|
||
|
%if &float.=0 %then %do;
|
||
|
%put Consider using the "float" option to save space. The "float" option saves numeric * ;
|
||
|
%put variables that contain decimal values as storage type float instead of the default * ;
|
||
|
%put of double. Storage type float is %nrquote(Stata%str(%'s)) default for numeric variables. * ;
|
||
|
%end;
|
||
|
%else %if &float.=1 %then %do;
|
||
|
%put Consider dropping some variables. * ;
|
||
|
%end;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=16;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail17: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put At least one of the formats for a numeric variable contains a compound quote ( %nrquote(%str(`%") or %str(%")%nrstr(%')) ). * ;
|
||
|
%put This is not allowed by SAVASTATA. * ;
|
||
|
%put Consider replacing any compound quotes with two single quotes ( %nrquote(%str(%'%')) ) using * ;
|
||
|
%put the "quotes" option. * ;
|
||
|
%if "&script." = "" %then %do;
|
||
|
%put Like: %nrstr(%%)savastata(%nrbquote(&out_dir.),-quotes &options.)%nrstr(;) ;
|
||
|
%end;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=17;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail18: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The work directory cannot start with a forward slash ( \ ) because * ;
|
||
|
%put SAVASTATA needs to cd to it. * ;
|
||
|
%put Is it possible to reassign your work directory to a drive like C: or D: ? * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=18;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail19: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put Stata had an error when attempting to infile the data. * ;
|
||
|
%* tfns = &sysjobid.&sysindex. when not run by -usesas- or savas **;
|
||
|
%if "&script." ^= "" %then %do;
|
||
|
%*if &messy.=0 %then %do; %** messy is always equal 1 for usesas and savas **;
|
||
|
%put Run &script. again using the "messy" option * ;
|
||
|
%put and then check the files "&out_dir._SomeNumber_infile.log" and * ;
|
||
|
%put "&out_dir._SomeNumber_con.log" for errors. * ;
|
||
|
%*end;
|
||
|
%end;
|
||
|
%else %do;
|
||
|
%if &messy.=0 %then %do;
|
||
|
%put Run SAVASTATA again using the "messy" option * ;
|
||
|
%put Like: %nrstr(%%)savastata(%nrbquote(&out_dir.),-messy &options.)%nrstr(;) * ;
|
||
|
%put and then check the file "&out_dir._SomeNumber_infile.log" for errors. * ;
|
||
|
%end;
|
||
|
%end;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=19;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail20: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put Either Stata ran with an error (use -messy option to see) or * ;
|
||
|
%put SAVASTATA was not able to get Stata to execute and * ;
|
||
|
%put this is not where your Stata executable file is located: * ;
|
||
|
%put &wstata. * ;
|
||
|
%put There are instructions in the top section of the savastata.sas file * ;
|
||
|
%put that explain how to edit the savastata.sas file to set the * ;
|
||
|
%put macro variable wstata to the correct location of your Stata executable file. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=20;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail21: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put Either Stata ran with an error (use -messy option to see) or * ;
|
||
|
%put SAVASTATA was not able to get Stata to execute and * ;
|
||
|
%put this is not how to call Stata: * ;
|
||
|
%put &ustata. *;
|
||
|
%put There are instructions in the top section of the savastata.sas file * ;
|
||
|
%put that explain how to edit the savastata.sas file to set the * ;
|
||
|
%put macro variable ustata to the correct way to call Stata. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=21;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail22: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put For reasons unknown SAVASTATA was not able to get Stata to execute. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=22;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail23: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=23;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail24: %put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%put The input dataset &dset. has &avars. variables which exceeds the 32,767 limit of Stata SE * ;
|
||
|
%put Consider dropping at least %eval(&avars. - 32766) variables. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=24;
|
||
|
%goto okay;
|
||
|
|
||
|
%fail25: %put * ;
|
||
|
%put * ;
|
||
|
%put %upcase(error): SAVASTATA did not save your dataset. * ;
|
||
|
%let nobs=%sysfunc(putn(&nobs.,comma32.));
|
||
|
%let maxobs=%sysfunc(putn(&maxobs.,comma32.));
|
||
|
%put The input dataset &dset. has &nobs. observations. * ;
|
||
|
%put which exceeds %nrquote(Stata%str(%'s)) limit of &maxobs. observations. * ;
|
||
|
%put For more help check here: &http. * ;
|
||
|
%if &isysver.<8 %then
|
||
|
SAVASTATA did not save your dataset
|
||
|
%put * ;
|
||
|
%let fail=25;
|
||
|
%goto okay;
|
||
|
|
||
|
|
||
|
|
||
|
%okay: %put ;
|
||
|
%if &success.=0 and "&nosave."="" %then %goto done;
|
||
|
|
||
|
%if &fail. > 0 and "&script." = "usesas" %then %do;
|
||
|
%** used to just delete the _infile.do file but now also creating a text file that usesas *;
|
||
|
%* looks for to see if savastata failed with a known error **;
|
||
|
%* fail22 and fail23 are unknown reasons and fail13 could be an unknown reason *;
|
||
|
%if (&fail. < 22 or &fail. > 23) and &fail. ^= 13 %then %do;
|
||
|
data _null_;
|
||
|
file "&temp_dir._&tfns._knerror.txt";
|
||
|
put "fail==&fail.";
|
||
|
run;
|
||
|
%end;
|
||
|
%** erase _infile.do so that -usesas- will not attemp to run it **;
|
||
|
%if %sysfunc(fileexist(%nrbquote("&temp_dir._&tfns._infile.do"))) %then %do;
|
||
|
data _null_;
|
||
|
fname="tempfile";
|
||
|
rc=filename(fname,"&temp_dir._&tfns._infile.do");
|
||
|
if rc = 0 and fexist(fname) then
|
||
|
rc=fdelete(fname);
|
||
|
run;
|
||
|
%end;
|
||
|
%* since only run by usesas, no need to clean up or figure out how long savastata took to run. *;
|
||
|
%goto nevrmind;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
%if &ascii.=1 %then %do;
|
||
|
options notes;
|
||
|
%put * ;
|
||
|
%put NOTE: SAVASTATA has successfully created the ascii data file %nrbquote(&out_dir.)_&tfns._.raw. * ;
|
||
|
%put * ;
|
||
|
%end;
|
||
|
%else %if &ascii.=0 and &messy.=1 and "&script."="" %then %do;
|
||
|
options notes;
|
||
|
%put * ;
|
||
|
%put NOTE: SAVASTATA has created its intermediary files _&tfns._* in: * ;
|
||
|
%put %nrbquote(&out_dir.) * ;
|
||
|
%put * ;
|
||
|
%end;
|
||
|
|
||
|
|
||
|
options nonotes; %** Make sure notes are shut off while deleting temp files and figuring out run time. **;
|
||
|
%****** clean up ***************;
|
||
|
%if "&script." ^= "usesas" %then %do;
|
||
|
proc datasets library=work nodetails nolist nowarn;
|
||
|
%** if a dataset does not exist, SAS does not give error message **;
|
||
|
%* so delete all of them. **;
|
||
|
delete _conten _conten1 _conten2 _conten3;
|
||
|
run;
|
||
|
quit;
|
||
|
%end; %** if script ^= usesas **;
|
||
|
|
||
|
%** Figure out how much time savastata took to process the dataset. **;
|
||
|
%** initialize macro vars **;
|
||
|
%let diffhour=%sysfunc(compress(%sysfunc(hour(%sysfunc(datetime())-&startdat.))));
|
||
|
%let diffmin=%sysfunc(compress(%sysfunc(minute(%sysfunc(datetime())-&startdat.))));
|
||
|
%let diffsec=%sysfunc(compress(%sysfunc(second(%sysfunc(datetime())-&startdat.))));
|
||
|
|
||
|
options notes;
|
||
|
%if &diffhour.>0 %then %put NOTE: SAVASTATA took about &diffhour. hours and &dffmin. minutes to run. * ;
|
||
|
%else %if &diffmin.=0 %then %put NOTE: SAVASTATA took less than a minute to run. * ;
|
||
|
%else %put NOTE: SAVASTATA took about &diffmin. mins to run. * ;
|
||
|
%if &sysindex.=10 and &check.=1 %then %do;
|
||
|
%put ;
|
||
|
%put Michael says, %str(%"Checking data is cool!%") ;
|
||
|
%put ;
|
||
|
%end;
|
||
|
%done: ;
|
||
|
|
||
|
options nonotes;
|
||
|
%if %sysfunc(fileexist(&usagelog.)) %then %do;
|
||
|
data _null_;
|
||
|
difftime=compress("&diffhour."||":"||"&diffmin."||":"||round(&diffsec.,0.1));
|
||
|
file &usagelog. mod;
|
||
|
put " SAS dataset name: &dset. pwd=&pwdir. ";
|
||
|
put " Elapsed time for SAVASTATA macro is " difftime;
|
||
|
put " fail=&fail. ";
|
||
|
run;
|
||
|
%end;
|
||
|
|
||
|
options obs=&obs. ¬es.; %** Restore options. **;
|
||
|
%** Make sure that the last dataset created in work is the users dataset. **;
|
||
|
%let sysdsn=&s_dsn.;
|
||
|
%let syslast=&s_last.;
|
||
|
|
||
|
%if &unix.=0 %then %do;
|
||
|
%sysexec &pwdrive. ; %** change to the drive that SAS started out in. **;
|
||
|
%end; %** end of if unix=0 do loop **;
|
||
|
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
|
||
|
%sysexec cd &pwdir. ; %** change to the directory that SAS started out in. **;
|
||
|
%nevrmind: ; %** Go to here if an error occurred before savastata started **;
|
||
|
|
||
|
%MEND savastata;
|
||
|
|