#delim ; prog def listtab; version 11.0; * List the variables in -varlist- as a table to files specified in -using- and/or -handle()- and/or to the Stata log with a value delimiter string and (optionally) a begin-line and/or end-line string. This program was first intended to output data to a file which is then input into a TeX table, in which case the value delimiter is usually "&" and the line terminator is usually "\cr". *! Author: Roger Newson *! Date: 04 November 2012 *; syntax [varlist (min=1)] [using/] [if] [in] [, Begin(passthru) Delimiter(passthru) End(passthru) Missnum(passthru) VBegin(varname string) VDelimiter(varname string) VEnd(varname string) RStyle(passthru) HEadlines(string asis) FOotlines(string asis) HEADChars(namelist) FOOTChars(namelist) noLabel Type REPLACE APpendto(string) HAndle(name) ]; * -varlist- specifies variables to be written to output file. -using- specifies output file. -begin()- is string at beginning of each obs (set to "" if absent). -delimiter()- is delimiter for separating values of same obs (set in default to "&"). -end()- is string at end of each obs (set to "" if absent). -missnum()- is string code for missing numeric value (defaulting to empty string if absent). -vbegin()- is a string variable, containing observation-specific begin() strings. -vdelimiter()- is a string variable, containing observation-specific delimiter() strings. -vend()- is a string variable, containing observation-specific end() strings. -rstyle()- is a row style (a named combination of -begin-, -end-, -using- and -missnum-). -headlines()- is a list of head lines to be added to the -using- file. -footlines()- is a list of foot lines to be added to the -using- file. -nolabel- specifies that numeric variables with value labels must be output as numbers and not as value labels. -type- specifies that the output file must be typed to the Stata log. -replace- specifies that any pre-existing file with the same name as the -using- file must be overwritten. -appendto()- specifies the name of a file not currently open, to which the variables (and headlines and footlines if specified) will be written, closing the file at the end of execution. -handle()- specifies a handle of a file currently open as a text file in write mode (using the -file open- command), to which the variables (and headlines and footlines if specified) will be written, leaving the file open at the end of execution, so that further output can be added using the -file- command. *; * Check that the user has specified either -using-, -type-, -appendto()- or -handle()- *; if (`"`using'"'=="")&("`type'"=="")&(`"`appendto'"'=="")&("`handle'"=="") {; disp as error "You must specify using and/or type and/or appendto() and/or handle()." _n "If type is specified, then data are typed to the Stata log." _n "If using is specified, then data are output to a file." _n "If appendto() is specified, then data are appended to a file." _n "If handle() is specified, then data are added to a file already open with that handle."; error 498; }; * Default output file *; if `"`using'"'=="" {; tempfile tf0; local using `"`tf0'"'; }; * Extract row style elements *; listtab_rstyle, `begin' `delimiter' `end' `missnum' `rstyle'; mata: st_local("begin",st_global("r(begin)")); mata: st_local("delimiter",st_global("r(delimiter)")); mata: st_local("end",st_global("r(end)")); mata: st_local("missnum",st_global("r(missnum)")); local nvar:word count `varlist'; marksample touse, novarlist strok; * Create temporary variables containing begin, delimiter and end strings, if these variables are not supplied *; foreach BDE in begin delimiter end {; if "`v`BDE''"=="" {; tempvar v`BDE'; qui gene `v`BDE''=""; qui replace `v`BDE''=`"``BDE''"' if `touse'; }; }; * Create list of output variables *; local ovarlist `"`vbegin'"'; forvalues i1=1(1)`nvar' {; local vari1:word `i1' of `varlist'; local typei1:type `vari1'; if substr("`typei1'",1,3)=="str" {; * String variable - do not convert *; local ovarlist `"`ovarlist' `vari1'"'; }; else {; * Numeric variable - convert to temporary string variable *; tempvar sv`i1'; local vli1: value label `vari1'; if ("`label'"!="nolabel")&("`vli1'"!="") {; qui decode `vari1', gene(`sv`i1''); }; else {; local fmti1: format `vari1'; qui gene str1 `sv`i1''=""; qui replace `sv`i1''=string(`vari1',"`fmti1'") if `touse'; qui replace `sv`i1''=`"`missnum'"' if `touse' & missing(`vari1'); }; local ovarlist `"`ovarlist' `sv`i1''"'; }; * Append delimiter or end *; if `i1'==`nvar' {;local ovarlist `"`ovarlist' `vend'"';}; else {;local ovarlist `"`ovarlist' `vdelimiter'"';}; }; * Output to temporary file *; tempfile tempout; qui outfile `ovarlist' using `"`tempout'"' if `touse', runtogether replace; * Copy temporary output file to permanent output file, adding headlines and footlines and characteristic headlines and footlines, if requested *; * Tokenize headlines and footlines and count the tokens *; mata:listtab_tokenize("nhead","headlines"); forv i1=1(1)`nhead' {; local headline`i1' `"`macval(`i1')'"'; }; mata:listtab_tokenize("nfoot","footlines"); forv i1=1(1)`nfoot' {; local footline`i1' `"`macval(`i1')'"'; }; local nheadchar: word count `headchars'; local nfootchar: word count `footchars'; if `nhead'+`nheadchar'<=0 & `nfoot'+`nfootchar'<=0 {; * No headlines or footlines *; copy `"`tempout'"' `"`using'"', text `replace'; }; else {; * Headlines or footlines required *; tempfile tempout2; tempname handle1 handle2; file open `handle2' using `"`tempout2'"', write text; * Head lines and characteristics *; forv i1=1(1)`nhead' {; local linecur `"`macval(headline`i1')'"'; file write `handle2' `"`macval(linecur)'"' _n; }; forv i1=1(1)`nheadchar' {; local charcur: word `i1' of `headchars'; listtab_vars `varlist', b(`"`macval(begin)'"') d(`"`macval(delimiter)'"') e(`"`macval(end)'"') sub(char `charcur') lo(linecur); file write `handle2' `"`macval(linecur)'"' _n; }; * Table body *; file open `handle1' using `"`tempout'"',read; file read `handle1' linecur; while r(eof)==0 {; file write `handle2' `"`macval(linecur)'"' _n; file read `handle1' linecur; }; file close `handle1'; * Foot characteristics and lines *; forv i1=1(1)`nfootchar' {; local charcur: word `i1' of `footchars'; listtab_vars `varlist', b(`"`macval(begin)'"') d(`"`macval(delimiter)'"') e(`"`macval(end)'"') sub(char `charcur') lo(linecur); file write `handle2' `"`macval(linecur)'"' _n; }; forv i1=1(1)`nfoot' {; local linecur `"`macval(footline`i1')'"'; file write `handle2' `"`macval(linecur)'"' _n; }; file close `handle2'; copy `"`tempout2'"' `"`using'"', text `replace'; }; * Append to a file if -appendto()- is requested *; if `"`appendto'"'!="" {; tempname aphandle uhandle; file open `aphandle' using `"`appendto'"', write append text; file open `uhandle' using `"`using'"', read; file read `uhandle' linecur; while r(eof)==0 {; file write `aphandle' `"`macval(linecur)'"' _n; file read `uhandle' linecur; }; file close `uhandle'; file close `aphandle'; }; * Add to an already open text file if -handle()- is requested *; if "`handle'"!="" {; tempname uhandle; file open `uhandle' using `"`using'"', read; file read `uhandle' linecur; while r(eof)==0 {; file write `handle' `"`macval(linecur)'"' _n; file read `uhandle' linecur; }; file close `uhandle'; }; * Type to the Stata log if requested *; if "`type'"!="" {;type `"`using'"';}; end; #delim cr version 11.0 /* Private Mata programs */ mata: void listtab_tokenize(string scalar tokencount,string scalar tokenlist) { /* Count tokens in local macro with name in tokenlist and return result in local macro with name in tokencount */ string rowvector tokenrow; real i1; /* tokenrow will be a row vector of the tokens. i1 will be a counter. */ tokenrow=tokens(st_local(tokenlist)); st_local(tokencount,strofreal(cols(tokenrow))); for(i1=1;i1<=cols(tokenrow);i1++){ st_local(strofreal(i1),tokenrow[i1]); } } end