*! texsave 1.3.1 23may2011 by Julian Reif * 1.3.1: hlines now allows negative numbers * 1.3: Booktabs and tabularx packages now required. 'H' allowed as location option (for subfig package). Headerlines option now enabled when nonames option is requested. Fixed hlines bug when numlist was unsorted. SW options turned off by default. * 1.2.2: added headerlines option * 1.2.1: added extra space after \hline to make tables look nicer. Added -rowsep- option to set row height spacing. * 1.2: added booktab package and formatting options. * 1.1.1: changed default align option to 8cm (so SWP will no longer error on this). * 1.1: new hlines, autonumber options, and footnotes suboptions. Added '&' to badchar list. Align option now allows any table spec argument. * 1.0.3: integer values now allowed for size option * 1.0.2: added size option * 1.0.1: added location option program define texsave, nclass version 10 syntax [varlist] using/ [if] [in] [, noNAMES SW noFIX title(string) DELIMITer(string) footnote(string asis) headerlines(string asis) headlines(string asis) footlines(string asis) frag align(string) LOCation(string) size(string) width(string) marker(string) bold(string) italics(string) underline(string) slanted(string) smallcaps(string) sansserif(string) monospace(string) emphasis(string) VARLABels hlines(numlist) autonumber rowsep(string) replace] * Check if appendfile is installed cap appendfile if _rc==199 { di as error "appendfile not installed. Type -ssc install appendfile-" exit _rc } * Error check hlines if "`hlines'"!="" { numlist "`hlines'", integer sort local hlines "`r(numlist)'" local num_hlines : word count `hlines' local max : word `num_hlines' of `hlines' local min : word 1 of `hlines' qui count `if' `in' local num_rows = `r(N)' if `num_rows' < abs(`max') | `num_rows' < abs(`min') { di as error "hlines() cannot cannot include values larger than `r(N)', the size of the table" exit 198 } * Any negative numbers are interpreted as coming from the bottom of the table local tmp_hlines foreach v of local hlines { local tmp = `v' if `tmp' < 0 local tmp =`num_rows'+`tmp' local tmp_hlines "`tmp_hlines' `tmp'" } local hlines "`tmp_hlines'" numlist "`hlines'", integer sort local hlines "`r(numlist)'" } * Define a horizontal line local horiz_line "\midrule" * Define row separation spacing if applicable if `"`rowsep'"'!="" local rowsep `" \addlinespace[`rowsep']"' * Append .tex extension if no extension present if strpos(`"`using'"',".") == 0 local using `"`using'.tex"' * Get number of vars/columns local num_vars : word count `varlist' * Error check the location option. Set default to "tbp" if `"`location'"'!="" { * Only allowed chracters are 'H', 'h', 't', 'b', 'p' and ' ' (blank) local location: subinstr local location " " "", all forval x = 1/`=length(`"`location'"')' { local char = substr(`"`location'"',`x',1) if !inlist(`"`char'"', "h", "t", "b", "p", "H") { di as error "location() option contains invalid characters" exit 198 } } } else local location "tbp" * Set table width if "`width'"=="" local width "\textwidth" * Set default values for delimiter. Determine what the end-of-line character is for the machine (needed for filefilter command below) if `"`delimiter'"'=="" local delimiter "&" if "`c(os)'" == "MacOSX" { if "`c(eolchar)'"=="mac" local eol_char = "\M" else local eol_char = "\U" } else if "`c(os)'" == "Windows" local eol_char = "\W" else local eol_char = "\U" ***************************** ***** FOOTNOTE OPTIONS **** ***************************** * Pull out footnotesize and footnote align options if specificed foreach v in using size align varlist if in { local hold_`v' `"``v''"' } local 0 `"`footnote'"' gettoken footnote 0 : 0, parse(,) cap syntax, [size(string) align(string)] if _rc!=0 { di as error "Invalid syntax for footnote() option" exit 198 } local footnotesize `"`size'"' local footnotealign `"`align'"' foreach v in using size align varlist if in { local `v' `"`hold_`v''"' } * Error check the size and footnotesize options. Set default for footnotesize and footnotealign. if "`footnotesize'"=="" local footnotesize "footnotesize" if "`footnotealign'"=="" local footnotealign "p{\textwidth}" foreach opt in "size" "footnotesize" { if "``opt''"!="" { * If size number is given... cap confirm integer number ``opt'' if _rc == 0 { if ``opt''>10 | ``opt''<1 { di as error "`opt'() value must be between 1 and 10" exit 198 } if ``opt''==1 local size2 "tiny" if ``opt''==2 local size2 "scriptsize" if ``opt''==3 local size2 "footnotesize" if ``opt''==4 local size2 "small" if ``opt''==5 local size2 "normalsize" if ``opt''==6 local size2 "large" if ``opt''==7 local size2 "Large" if ``opt''==8 local size2 "LARGE" if ``opt''==9 local size2 "huge" if ``opt''==10 local size2 "Huge" assert "`size2'"!="" local `opt' "`size2'" } * Else user specified string else { if !inlist(`"``opt''"', "tiny","scriptsize","footnotesize","small","normalsize","large","Large","LARGE","huge") & "`size'"!="Huge" { di as error "``opt'' is an invalid option for `opt'()" exit 198 } } } } ***************************** ** Table column alignment ** ***************************** * Default is to have first column left-justified and the rest centered. if `"`align'"'=="" { local align "l" forval x = 2/`num_vars' { local align "`align'C" } } ***************************** ** HEADER ** ***************************** * Create a suitable header. Autonumber overrides varlabels (except for first var) if `"`headerlines'"' != "" { tokenize `"`headerlines'"' while `"`1'"' != "" { local head_lines_sep `"`head_lines_sep'`1'\tabularnewline "' macro shift } } local run_no = 1 foreach v of local varlist { if "`autonumber'"!="" { local lbl : variable label `v' if `run_no'==1 & "`varlabels'"!="" local header `"`header'`delimiter'`lbl'"' if `run_no'==1 & "`varlabels'"=="" local header `"`header'`delimiter'`v'"' if `run_no'>1 local header `"`header'`delimiter'(`=`run_no'-1')"' } else { if "`varlabels'"!="" { local lbl : variable label `v' local header `"`header'`delimiter'`lbl'"' } else local header `"`header'`delimiter'`v'"' } local run_no = `run_no'+1 } local header `"`header'\tabularnewline"' local header : subinstr local header `"`delimiter'"' "" local header `"`head_lines_sep'`header'"' ***** * Correct chars that cause problems in LaTeX; add bold, italics, underline etc. tags as necessary ***** if "`fix'"=="" { * Header, title, and footer foreach str in "header" "footnote" "title" { foreach symbol in _ & % # $ ~ { if "`str'"=="header" & "`symbol'"=="&" continue // Allow &'s in headers since they are delimiters local `str' : subinstr local `str' `"`symbol'"' `"\\`symbol'"', all } * We have braces in the header sometimes so skip that one if "`str'"!="header" local `str' : subinstr local `str' "{" `"\{"', all if "`str'"!="header" local `str' : subinstr local `str' "}" "\}", all * '^' is handled specially local `str' : subinstr local `str' `"^"' `"\^{}"', all } } if "`fix'"=="" | `"`bold'`italics'`underline'`slanted'`smallcaps'`sansserif'`monospace'`emphasis'"'!="" { local renamed = "yes" * Variables - create new temporary ones that have bad chars stripped out of them and are formatted as specified by user foreach v of local varlist { tempname `v'temp qui ren `v' ``v'temp' qui gen `v' = ``v'temp' capture confirm string var `v' if _rc==0 { * Fix problematic symbols if "`fix'"=="" { foreach symbol in _ & % # $ & ~ { qui replace `v' = subinstr(`v',"`symbol'","\\`symbol'",.) } qui replace `v' = subinstr(`v',"{","\{",.) qui replace `v' = subinstr(`v',"}","\}",.) qui replace `v' = subinstr(`v',"^","\^{}",.) } * Formatting options local tex_code "\textbf{ \textit{ \underline{ \textsl{ \textsc{ \textsf{ \texttt{ \emph{" local run_no = 1 foreach opt in bold italics underline slanted smallcaps sansserif monospace emphasis { local command : word `run_no' of `tex_code' tokenize `"``opt''"' while `"`1'"' != "" { qui replace `v' = "`command'" + `v' + "}" if strpos(`v',`"`1'"')!=0 macro shift } local run_no = `run_no'+1 } } } } ****** ** Open the file ****** tempfile data1 data2 end_file tempname fh qui file open `fh' using "`using'", write `replace' ****** ** Table start ****** if "`frag'" == "" { file write `fh' "\documentclass{article}" _n file write `fh' "\usepackage{booktabs}" _n file write `fh' "\usepackage{tabularx}" _n file write `fh' "\begin{document}" _n } * Headlines option if `"`headlines'"' != "" { tokenize `"`headlines'"' while `"`1'"' != "" { file write `fh' `"`1'"' _n macro shift } } if "`sw'"!="" file write `fh' "%TCIMACRO{\TeXButton{B}{\begin{table}[`location'] \centering}}%" _n if "`sw'"!="" file write `fh' "%BeginExpansion" _n file write `fh' "\begin{table}[`location'] \centering%" _n file write `fh' "\newcolumntype{C}{>{\centering\arraybackslash}X}" _n if "`sw'"!="" file write `fh' "%EndExpansion" _n if `"`title'"'!="" file write `fh' `"\caption{`title'}%"' _n if `"`size'"'!="" file write `fh' `"{\\`size'"' _n file write `fh' "\begin{tabularx}{`width'}{`align'}" _n * Create double-line or thick line, depending on book tabs file write `fh' "\toprule" _n ******** ** Header, if specified ******** if "`names'"=="" qui file write `fh' "`header'" _n "`horiz_line'\addlinespace[1.5ex]" _n else if `"`head_lines_sep'"'!="" qui file write `fh' "`head_lines_sep'" _n file close `fh' ********* ** Data ********* * If hlines() option is specified, need to split up dataset and insert hlines if "`hlines'"!="" { tempvar dummy rownum touse tempfile tmp qui gen byte `touse' = 1 `if' `in' qui replace `touse' = 0 if mi(`touse') * Generate table rownumbers qui gen byte `dummy' = 1 qui gen `rownum' = sum(`dummy') `if' `in' * Outsheet the groups one by one tokenize `hlines' forval grp = 1/`=`num_hlines'+1' { * First group if `grp'==1 { qui outsheet `varlist' if `touse'==1 & inrange(`rownum',1,``grp'') using "`data1'", replace delimiter(`delimiter') nonames noquote } * Rest of groups else { * Append hline qui file open `fh' using "`data1'", write append file write `fh' "`horiz_line' " qui file close `fh' if `grp' == `=`num_hlines'+1' { local g1 = ``=`grp'-1'' + 1 // This allows for double/triple lines etc since it will make inrange(x+1,x) local g2 . } else { local g1 = ``=`grp'-1'' + 1 local g2 ``grp'' } * Append next group qui outsheet `varlist' if `touse'==1 & inrange(`rownum',`g1',`g2') using "`tmp'", replace delimiter(`delimiter') nonames noquote appendfile "`tmp'" "`data1'" } } } else qui outsheet `varlist' `if' `in' using "`data1'", replace delimiter(`delimiter') nonames noquote filefilter "`data1'" "`data2'", from("`eol_char'") to(" \BStabularnewline`rowsep'`eol_char'") replace ********* ** Table end ********* qui file open `fh' using "`end_file'", write `replace' * SW has a bug with \bottomrule that requires you to output an extra \\ file write `fh' "\bottomrule \addlinespace[1.5ex]" _n if `"`footnote'"'!="" file write `fh' `"\multicolumn{`num_vars'}{`footnotealign'}{\begin{`footnotesize'} `footnote'\end{`footnotesize'}}"' _n file write `fh' "\end{tabularx}%" _n if `"`size'"'!="" file write `fh' "}" _n if `"`marker'"'!="" file write `fh' `"\label{`marker'}%"' _n if "`sw'"!="" file write `fh' "%TCIMACRO{\TeXButton{E}{\end{table}}}%" _n if "`sw'"!="" file write `fh' "%BeginExpansion" _n file write `fh' "\end{table}%" _n if "`sw'"!="" file write `fh' "%EndExpansion" _n * Footlines option if `"`footlines'"' != "" { tokenize `"`footlines'"' while `"`1'"' != "" { file write `fh' `"`1'"' _n macro shift } } * End the tex document if "`frag'"=="" file write `fh' "\end{document}" _n * Close the file file close `fh' ******** ** Append table start ("using"), data, and table end together ******** appendfile "`data2'" "`using'" appendfile "`end_file'" "`using'" * Return vars to original state if "`renamed'"=="yes" { * Variables foreach v of local varlist { qui drop `v' qui ren ``v'temp' `v' } } end **EOF