Stata: Using S_ADO to reference files from your program w/o an argument

I’ve been working with a user-written module in Stata where the program’s code isn’t separate from its data; that is, the program relies on a big macro containing operational details it needs to perform. The program iterates a selected do-file over a set of data files that can be selected on the basis of a battery of characteristics, and the roster of data files and their characteristics is a big local macro inside the program.

That’s not a bad way to go, but I want that data to be accessible outside the program so that I can use it for other things, have someone who doesn’t understand code maintain it, etc. Separating code from data also satisfies a programming principle that was drilled into me from an early age (but, see this exchange on SE).

Because the program needs to be portable, I can’t hard-code the data file’s location into the program. Because the program needs to be backward-compatible with the user code that calls it, I can’t require that the program take a new argument indicating where the data live.

What to do?

The -adopath- command lets the user specify a location to look for ado files. It stores those values in the global macro $S_ADO, along with Stata’s native paths (like /ado/base/, /ado/plus/, et al).

If a user specifies adopath + /somepathname/ , it’ll put /somepathname/ at the end of the list. If a user specifies adopath ++ /somepathname/, /somepathname/ is inserted at the front.

If I know how the user specified adopath, I can put this in my program’s ado-file:


adopath + "/mypathname/"
local adop = `"$S_ADO"' // Unnecessary -- I do this for comfort.
local adop = subinstr(`"`adop'"',";"," ",.) // Stata likes spaces
local len_adop: word count `adop'           // macro length (numeric)
tokenize `"`adop'"'                         // splits into `1',`2',...,`len_adop'
di "``len_adop''"                           // value of the last (`len_adop'th) element

Then I can do two more things:

  1. Put my data file in the same folder as my ado file, and
  2. Reference `mypath’/mydatafile in my code.

I don’t have to pass an argument to my program telling it where its operational data lives, and I don’t have to open the program’s source and change a hard-coded path every time the program moves.

Leave a Reply

Your email address will not be published. Required fields are marked *