/*--------------------------------------------------------------------- /// XTABLE - export table output to excel /// Weverthon Machado v1.0.2 - 2019-12-22 ---------------------------------------------------------------------*/ program define xtable, rclass version 13.1 /* Get only -table- options that are needed here. The final asterisk captures everything else */ syntax varlist(max=3) [if] [in] [fw aw pw iw] [, /// BY(varlist) Name NOPut FILEname(string) /// SHeet(string) MODify REPLACE KEEPCELLFormat *] /********************************************************************* # Parse arguments **********************************************************************/ /* Tokenize */ tokenize `varlist' local rowvar = "`1'" local colvar = "`2'" local scolvar = "`3'" tokenize `by' local srow1var = "`1'" local srow2var = "`2'" local srow3var = "`3'" local srow4var = "`4'" local nby: list sizeof by /* Run -table- */ preserve table `varlist' `if' `in' [`weight'`exp'], by(`by') `options' replace /* Get numbers and levels of vars and stats */ /* + encode string variables */ capture confirm string variable `rowvar' if !_rc { encode `rowvar', gen(temp_rowvar) drop `rowvar' rename temp_rowvar `rowvar' } qui levelsof `rowvar', local(row_levels) missing local nrow: list sizeof row_levels unab stat_list: table* local nstats: word count `stat_list' if !missing("`colvar'") { capture confirm string variable `colvar' if !_rc { encode `colvar', gen(temp_colvar) drop `colvar' rename temp_colvar `colvar' } qui levelsof `colvar', local(col_levels) missing local ncol: list sizeof col_levels } else { /* If there's no colvar, stats are displayed in columns*/ local ncol = `nstats' } if !missing("`scolvar'") { capture confirm string variable `scolvar' if !_rc { encode `scolvar', gen(temp_scolvar) drop `scolvar' rename temp_scolvar `scolvar' } qui levelsof `scolvar', local(scol_levels) missing local nscol: list sizeof scol_levels } else { local scol_levels 1 local nscol = 1 } forvalues n = 1/4 { if !missing("`srow`n'var'") { capture confirm string variable `srow`n'var' if !_rc { encode `srow`n'var', gen(temp_srowvar) drop `srow`n'var' rename temp_srowvar `srow`n'var' } qui levelsof `srow`n'var', local(srow`n'_levels) missing local nsrow`n': list sizeof srow`n'_levels } else { local srow`n'_levels 1 local nsrow`n' = 1 } } /* complete obs if there's at least a col or srow var */ if !missing("`colvar'") | !missing("`srow1var'") { cap drop _fillin fillin `rowvar' `colvar' `scolvar' `srow1var' `srow2var' `srow3var' `srow4var' drop _fillin } /********************************************************************* # Build matrix **********************************************************************/ matrix xt_results = J(1,`ncol'*`nscol', .) /*----------------------------------------------------------------------------- ## Superrow var 1 -----------------------------------------------------------------------------*/ foreach srow1 in `srow1_levels' { local psrow1: list posof "`srow1'" in srow1_levels matrix xt_results_`psrow1' = J(1,`ncol'*`nscol', .) if `nsrow1' > 1 { tempfile stats_data_`psrow1' qui save `stats_data_`psrow1'' qui keep if `srow1var' == `srow1' } /*------------------------------------------------------------------------- ## Superrow var 2 -------------------------------------------------------------------------*/ foreach srow2 in `srow2_levels' { local psrow2: list posof "`srow2'" in srow2_levels matrix xt_results_`psrow1'`psrow2' = J(1,`ncol'*`nscol', .) if `nsrow2' > 1 { tempfile stats_data_`psrow1'`psrow2' qui save `stats_data_`psrow1'`psrow2'' qui keep if `srow2var' == `srow2' } /*--------------------------------------------------------------------- ## Superrow var 3 ---------------------------------------------------------------------*/ foreach srow3 in `srow3_levels' { local psrow3: list posof "`srow3'" in srow3_levels matrix xt_results_`psrow1'`psrow2'`psrow3' = J(1,`ncol'*`nscol', .) if `nsrow3' > 1 { tempfile stats_data_`psrow1'`psrow2'`psrow3' qui save `stats_data_`psrow1'`psrow2'`psrow3'' qui keep if `srow3var' == `srow3' } /*----------------------------------------------------------------- ## Superrow var 4 -----------------------------------------------------------------*/ foreach srow4 in `srow4_levels' { local psrow4: list posof "`srow4'" in srow4_levels if !missing("`colvar'") { mat def xt_results_`psrow1'`psrow2'`psrow3'`psrow4' = /// J(`nrow'*`nstats', 1, .) } else { mat def xt_results_`psrow1'`psrow2'`psrow3'`psrow4' = /// J(`nrow', 1, .) } if `nsrow4' > 1 { tempfile stats_data_`psrow1'`psrow2'`psrow3'`psrow4' qui save `stats_data_`psrow1'`psrow2'`psrow3'`psrow4'' qui keep if `srow4var' == `srow4' } /*------------------------------------------------------------- ## Supercolumn -------------------------------------------------------------*/ foreach scol in `scol_levels' { if `nscol' > 1 { tempfile stats_data_scol qui save `stats_data_scol' qui keep if `scolvar' == `scol' } local pscol: list posof "`scol'" in scol_levels sort `rowvar' `colvar' `scolvar' `srowvar1' `srowvar2' `srowvar3' `srowvar4' if !missing("`colvar'") { mat def xt_`pscol' = J(`nrow'*`nstats', `ncol', .) } else { mat def xt_`pscol' = J(`nrow', `nstats', .) } /*--------------------------------------------------------- ## Basic matrix (row X col X stat) ---------------------------------------------------------*/ forvalues row = 1/`nrow' { forvalues col = 1/`ncol' { forvalues stat = 1/`nstats' { if !missing("`colvar'") { mat xt_`pscol'[((`row'-1)*`nstats')+`stat', `col'] = /// table`stat'[((`row'-1)*`ncol')+`col'] } else { mat xt_`pscol'[`row', `col'] = table`col'[`row'] } } } } /*---------------------------------------------------------*/ mat xt_results_`psrow1'`psrow2'`psrow3'`psrow4' = /// xt_results_`psrow1'`psrow2'`psrow3'`psrow4', xt_`pscol' mat drop xt_`pscol' if `nscol' > 1 { qui use `stats_data_scol', clear } } /*-----------------------------------------------------------*/ mat xt_results_`psrow1'`psrow2'`psrow3'`psrow4' = /// xt_results_`psrow1'`psrow2'`psrow3'`psrow4'[1..., 2...] if `nby' > 0 { mat srow_header = J(`nby',`ncol'*`nscol', .) mat xt_results_`psrow1'`psrow2'`psrow3' = /// xt_results_`psrow1'`psrow2'`psrow3' \ /// srow_header \ /// xt_results_`psrow1'`psrow2'`psrow3'`psrow4' mat drop xt_results_`psrow1'`psrow2'`psrow3'`psrow4' srow_header } else { mat xt_results_`psrow1'`psrow2'`psrow3' = /// xt_results_`psrow1'`psrow2'`psrow3' \ /// xt_results_`psrow1'`psrow2'`psrow3'`psrow4' mat drop xt_results_`psrow1'`psrow2'`psrow3'`psrow4' } if `nsrow4' > 1 { qui use `stats_data_`psrow1'`psrow2'`psrow3'`psrow4'', clear } } /*---------------------------------------------------------------*/ mat xt_results_`psrow1'`psrow2'`psrow3' = /// xt_results_`psrow1'`psrow2'`psrow3'[2..., 1...] mat xt_results_`psrow1'`psrow2' = /// xt_results_`psrow1'`psrow2' \ xt_results_`psrow1'`psrow2'`psrow3' mat drop xt_results_`psrow1'`psrow2'`psrow3' if `nsrow3' > 1 { qui use `stats_data_`psrow1'`psrow2'`psrow3'', clear } } /*-------------------------------------------------------------------*/ matrix xt_results_`psrow1'`psrow2' = xt_results_`psrow1'`psrow2'[2..., 1...] mat xt_results_`psrow1' = xt_results_`psrow1' \ xt_results_`psrow1'`psrow2' mat drop xt_results_`psrow1'`psrow2' if `nsrow2' > 1 { qui use `stats_data_`psrow1'`psrow2'', clear } } /*-----------------------------------------------------------------------*/ matrix xt_results_`psrow1' = xt_results_`psrow1'[2..., 1...] mat xt_results = xt_results \ xt_results_`psrow1' mat drop xt_results_`psrow1' if `nsrow1' > 1 { qui use `stats_data_`psrow1'', clear } } /*---------------------------------------------------------------------------*/ mat xtable = xt_results[2..., 1...] mat drop xt_results /********************************************************************* # Labels **********************************************************************/ /* Rows and superrows */ foreach row in `row_levels' { local row_label : label (`rowvar') `row' if `row'== . { local row_label "Total" } #delimit ; local mat_rownames_rows = `"`mat_rownames_rows'"' + `" ""' + subinstr(substr("`row_label'", 1, 30), ".", " ", .) + `"""' ; #delimit cr if !missing("`colvar'"){ local mat_rownames_rows = `"`mat_rownames_rows'"' + (`""-""')*(`nstats'-1) } } foreach srow1 in `srow1_levels' { local psrow1: list posof "`srow1'" in srow1_levels cap local srow1_label : label (`srow1var') `srow1' if missing("`srow1_label'"){ local mat_rownames = `"`mat_rownames_rows'"' } else { foreach srow2 in `srow2_levels' { local psrow2: list posof "`srow2'" in srow2_levels cap local srow2_label : label (`srow2var') `srow2' if missing("`srow2_label'"){ #delimit ; local mat_rownames = `"`mat_rownames'"' + `" ""' + subinstr(substr("`srow1_label'", 1, 30), ".", " ", .) + `"""' + `"`mat_rownames_rows'"' ; #delimit cr } else{ foreach srow3 in `srow3_levels' { local psrow3: list posof "`srow3'" in srow3_levels cap local srow3_label : label (`srow3var') `srow3' if missing("`srow3_label'"){ #delimit ; local mat_rownames = `"`mat_rownames'"' + `" ""' + subinstr(substr("`srow1_label'", 1, 30), ".", " ", .) + `"""' + `" ""' + subinstr(substr("`srow2_label'", 1, 30), ".", " ", .) + `"""' + `"`mat_rownames_rows'"' ; #delimit cr } else{ foreach srow4 in `srow4_levels' { local psrow4: list posof "`srow4'" in srow4_levels cap local srow4_label : label (`srow4var') `srow4' if missing("`srow4_label'"){ #delimit ; local mat_rownames = `"`mat_rownames'"' + `" ""' + subinstr(substr("`srow1_label'", 1, 30), ".", " ", .) + `"""' + `" ""' + subinstr(substr("`srow2_label'", 1, 30), ".", " ", .) + `"""' + `" ""' + subinstr(substr("`srow3_label'", 1, 30), ".", " ", .) + `"""' + `"`mat_rownames_rows'"' ; #delimit cr } else { #delimit ; local mat_rownames = `"`mat_rownames'"' + `" ""' + subinstr(substr("`srow1_label'", 1, 30), ".", " ", .) + `"""' + `" ""' + subinstr(substr("`srow2_label'", 1, 30), ".", " ", .) + `"""' + `" ""' + subinstr(substr("`srow3_label'", 1, 30), ".", " ", .) + `"""' + `" ""' + subinstr(substr("`srow4_label'", 1, 30), ".", " ", .) + `"""' + `"`mat_rownames_rows'"' ; #delimit cr } } } } } } } } mat rownames xtable = `mat_rownames' /* Columns */ if !missing("`colvar'") { foreach scol in `scol_levels' { local pscol: list posof "`scol'" in scol_levels foreach col in `col_levels' { local col_label : label (`colvar') `col' if `col'== . { local col_label "Total" } #delimit ; local mat_colnames_`pscol' = `"`mat_colnames_`pscol''"' + `" ""' + subinstr(substr("`col_label'", 1, 30), ".", " ", .) + `"""' ; #delimit cr } local mat_colnames = `"`mat_colnames'"' + `"`mat_colnames_`pscol''"' } } else { forvalues s =1/`nstats' { local stat_label: var label table`s' local mat_colnames = `"`mat_colnames'"' + `" ""' + /// subinstr(substr("`stat_label'", 1, 30), ".", " ", .) + `"""' } } mat colnames xtable = `mat_colnames' /* Supercolumns */ if missing("`put'") { if !missing("`scolvar'") { foreach scol in `scol_levels' { mat scol_names = J(1, `nscol'*`ncol', .) local scol_label: label (`scolvar') `scol' if `scol'== . { local scol_label "Total" } local mat_scolnames = `"`mat_scolnames'"' /// + `" ""' /// + subinstr(substr("`scol_label'", 1, 30), ".", " ", .) /// + `"""' /// + (`""---""')*(`ncol'-1) } mat colnames scol_names = `mat_scolnames' } } /********************************************************************* # Export **********************************************************************/ /* option noput supresses export */ if missing("`noput'") { /* If user dows not specify replace or modify, does the following: - If no filename was specified, replace xtable.xlsx - If a filnema was specified, modify it. */ if missing("`replace'") & missing("`modify'") { if missing("`filename'") { local replace replace } else { local modify modify } } if missing("`filename'"){ local filename xtable.xlsx } /* Parse sheet name and replace option */ local comma = strpos(`"`sheet'"', ",") local sheetreplace = substr(`"`sheet'"', `comma', .) if `comma' != 0 { local sheet = substr(`"`sheet'"', 1, `comma'-1) } /* Variable labels */ local rowvar_label: var label `rowvar' if missing("`rowvar_label'"){ local rowvar_label "`rowvar'" } if `nby'>0 { forvalues n = 1/`nby'{ local srow`n'var_label: var label `srow`n'var' if missing("`srow`n'var_label'"){ local srow`n'var_label "`srow`n'var'" } if `n' > 1 { local srow`n'var_label = ", " + `"`srow`n'var_label'"' } } local rowvar_label = `"`srow1var_label'"' + /// `"`srow2var_label'"' + /// `"`srow3var_label'"' + /// `"`srow4var_label'"' + /// " and " + `"`rowvar_label'"' } if !missing("`colvar'") { local colvar_label: var label `colvar' if missing("`colvar_label'"){ local colvar_label "`colvar'" } } if !missing("`scolvar'"){ local scolvar_label: var label `scolvar' if missing("`scolvar_label'"){ local scolvar_label "`scolvar'" } local colvar_label = `"`scolvar_label'"' + " and " + `"`colvar_label'"' } /* putexcel */ qui putexcel A1=(" ") /// using `filename', `keepcellformat' sheet(`sheet' `sheetreplace') `replace' `modify' if !missing("`scolvar'") { qui putexcel A2 = matrix(scol_names, names) /// using `filename', modify `keepcellformat' sheet(`sheet') mat drop scol_names } qui putexcel A3 = matrix(xtable, names) /// A3 = ("`rowvar_label'") /// using `filename', modify `keepcellformat' sheet(`sheet') if !missing("`colvar'") { if !missing("`scolvar'") { local colvar_cell B1 } else { local colvar_cell B2 } qui putexcel `colvar_cell' = ("`colvar_label'") /// using `filename', modify `keepcellformat' sheet(`sheet') } if !regexm("`filename'", "(\.xls|\.xlsx)") { local filename = `"`filename'"' + ".xlsx" } di as smcl "Output written to {browse "`"`filename'}"'" } return matrix xtable = xtable end