*! version 1.06 16May2012 Minh Cong Nguyen * version 1.06: 16May2012 - adding more statistics for continuous variables. * version 1.05 19Nov2011 - basic command # delimit ; cap program drop tabmult; program define tabmult, rclass; version 9, missing; local version : di "version " string(_caller()) ", missing:"; syntax [anything] [if] [in] [aw], [cat(varlist) cont(varlist)] by(varlist) [Row Col SCol SRow Missing STATCont(string) save(string) SHeet(string) replace append SAVEMat(string)]; local cmdline: copy local 0 ; marksample touse; if `"`weight'"' != "" {; local wgt `"[`weight'`exp']"'; }; if ~missing(`"`missing'"') {; local missopt missing; local mcount = 1; local mstr _VX_; }; else {; local missopt; local mcount = 0; local mstr ; }; if ("`row'"!="") + ("`col'"!="") >1 {; di in red "choose only one option: row or col. The default is freq"; exit 198 ; }; local cat : list uniq cat; local cont : list uniq cont; local by : list uniq by; if "`:list cat & cont'"!="" {; di as err "Variables `:list cat & cont' cannot be both in the categorial and continuous lists"; error 198 ; }; local vlist : list cat | cont; if "`vlist'"=="" {; di as err "There are no variables in the categorial and/or continuous list"; error 198 ; }; // checking variables; foreach var of local cont {; qui su `var', meanonly; if r(N)==0 local vbad "`vbad' `var'"; }; if `: word count `vbad''>0 {; dis in ye _n "The following variable(s) have no numeric observations or is/are string variables: `vbad'"; error 109 ; }; if "`:list vlist & by'"!="" { ; di as err "Variables `:list vlist & by' cannot be both in the categorial and/or continuous lists and the by list"; error 198 ; }; if (`"`row'"'==`""' & `"`col'"'==`""') {; local opts; local weight1; local topt count; local rla "(count)"; if ~missing("`statcont'") local topt "`statcont'"; }; else if (`"`row'"'!=`""' & `"`col'"'==`""') {; local opts nof row; local weight1 `wgt'; local topt mean; local rla "(mean)"; if ~missing("`statcont'") local topt "`statcont'"; }; else if (`"`row'"'==`""' & `"`col'"'!=`""') {; local opts nof col; local weight1 `wgt'; local topt mean; local rla "(mean)"; if ~missing("`statcont'") local topt "`statcont'"; }; if ~missing(`"`scol'"') {; tempname __all; tempvar __alll; qui gen `__all' = 1 if `touse'; qui la var `__all' "All"; qui la def `__alll' 1 "sample"; qui la val `__all' `__alll'; local by `"`by' `__all'"'; }; // Saving and Excel options; if missing("`save'") {; local save "stata_tabmult.xml"; local replace "replace"; }; else {; _getfilename "`save'"; if `"`r(filename)'"'==`"`save'"' {; local save "`c(pwd)'/`save'"; }; else {; if index(`"`r(filename)'"', ".")==0 {; local save `"`save'.xml"'; }; }; if ~missing("`append'") {; capture confirm file "`save'"; if _rc {; local replace "replace"; }; else {; local append "append"; }; }; if missing("`append'`replace'") {; capture confirm file "`save'"; if ~_rc {; display as error `"Error 602: file `save' already exists"'; exit 198 ; }; else {; local replace "replace"; }; }; }; local filename = cond(strpos("`save'", "\") + strpos("`save'", "/") > 0, "`save'", "`c(pwd)'\\`save'"); // get sheet options local 0 `sheet'; syntax [anything(name=sheet)] [, COlor(integer -1) noGridlines]; // check if sheet name is valid gettoken a b : sheet, parse(":\/?*[]"); if ~missing("`b'") | length("`sheet'")>31 Error 198 `"not a valid Excel sheet name"'; if missing("`sheet'") local sheet "Sheet1"; // Excel options; local excelpath; capture local dirs : dir "C:/Program Files (x86)/Microsoft Office" dirs "office*"; if ~_rc {; local x86 " (x86)"; }; else {; capture local dirs : dir "C:/Program Files/Microsoft Office" dirs "office*"; }; foreach d of local dirs {; capture confirm file "C:/Program Files`x86'/Microsoft Office/`d'/excel.exe"; if ~_rc {; local excelpath "C:/Program Files`x86'/Microsoft Office/`d'/excel.exe"; continue, break; }; }; // Check variables; preserve; local vlist2 : list cat | by; local vlist3 : list cont | vlist2; foreach v2 of local vlist3 {; local varl : variable label `v2'; local varl : subinstr local varl `"`=char(34)'"' "", all; if (`"`varl'"'==`""') la var `v2' "`v2'"; capture confirm string variable `v2'; if !_rc {; qui encode `v2' if `touse', gen(`v2'_XXX) label(`v2'); qui drop `v2'; qui ren `v2'_XXX `v2'; }; }; // Process the labels for by groups; foreach v1 of local by {; qui levelsof `v1' if `touse', local(l_`v1'); local lbl0 : variable label `v1'; local rn0 = proper("`lbl0'"); local bynames "`bynames' "`rn0'""; foreach rn of local l_`v1' {; local lbl : label (`v1') `rn'; local lbl = proper("`lbl'"); local rn1 "`lbl'"; local cnames "`cnames' "`rn1'""; }; if ~missing(`"`missing'"') local cnames "`cnames' "`missopt'""; }; // Process the labels for cat groups; foreach v2 of local cat {; qui levelsof `v2' if `touse', local(l_`v2'); local lbl0 : variable label `v2'; local lbl0 = proper("`lbl0'"); local rn0 "_GX_`lbl0'"; local rnames "`rnames' "`rn0'""; foreach rn of local l_`v2' {; local lbl : label (`v2') `rn'; local lbl = proper("`lbl'"); local rn1 "_VX_`lbl'"; local rnames "`rnames' "`rn1'""; }; if ~missing(`"`missing'"') local rnames "`rnames' "`mstr'`missopt'""; if ~missing(`"`srow'"') local rnames "`rnames' "_VX_Total""; }; // Process the labels for cont groups; foreach v2 of local cont {; local lbl0 : variable label `v2'; local lbl0 = proper("`lbl0'"); if ("`statcont'"=="") {; local rn0 "_GZ_`rla'_`lbl0'"; local rnames "`rnames' "`rn0'""; }; else {; foreach nr of local statcont {; local rn0 "_GZ_(`nr')_`lbl0'"; local rnames "`rnames' "`rn0'""; }; }; }; // Process the numbers in cells for cat groups; cap mat drop mall2; if ("`cat'"!="") {; foreach v2 of local cat {; cap mat drop mall1; foreach v1 of local by {; qui ta `v2' `v1' if `touse' `weight1', `opts' `missopt' matcell(mcell) matrow(mrow) matcol(mcol); local strmcoll; forv i=1(1)`=colsof(mcol)' {; local xbs = mcol[1,`i']; local strmcoll "`strmcoll' `xbs'"; }; local strmrow; forv i=1(1)`=rowsof(mrow)' {; local xbs = mrow[`i',1]; local strmrow "`strmrow' `xbs'"; }; //Process the mcell matrix; local tot2 = 0; if ~missing(`"`srow'"') {; local misrow = 1; mat mrowt = J(1,`=colsof(mcell)',.); forv i=1(1)`=colsof(mcell)' {; local tot1 = 0; forv j=1(1)`=rowsof(mcell)' {; local tot1 = `tot1' + mcell[`j',`i']; }; local tot2 = `tot2' + `tot1'; mat mrowt[1,`i'] = `tot1'; }; if (("`col'"=="col") | ("`row'"=="row")) mat mrowt = (100/`tot2')*mrowt; }; if "`v1'"~="`__all'" {; if ("`row'"=="row") {; // row options, sum to 100 in rows; forv i=1(1)`=rowsof(mcell)' {; local tot = 0; forv j=1(1)`=colsof(mcell)' {; local tot = `tot' + mcell[`i',`j']; }; forv j=1(1)`=colsof(mcell)' {; mat mcell[`i',`j'] = (mcell[`i',`j']/`tot')*100; }; }; }; if ("`col'"=="col") {; // col options, sum to 100 in columns; forv i=1(1)`=colsof(mcell)' {; local tot = 0; forv j=1(1)`=rowsof(mcell)' {; local tot = `tot' + mcell[`j',`i']; }; forv j=1(1)`=rowsof(mcell)' {; mat mcell[`j',`i'] = (mcell[`j',`i']/`tot')*100; }; }; }; }; else {; if ("`col'"=="col") | ("`row'"=="row") {; // scol options, sum to 100 in columns; forv i=1(1)`=colsof(mcell)' {; local tot = 0; forv j=1(1)`=rowsof(mcell)' {; local tot = `tot' + mcell[`j',`i']; }; forv j=1(1)`=rowsof(mcell)' {; mat mcell[`j',`i'] = (mcell[`j',`i']/`tot')*100; }; }; }; }; if ~missing(`"`srow'"') mat mcell = mcell \ mrowt; local pos = 1; foreach mr of local l_`v1' {; local x : list posof "`mr'" in strmcoll; if `x'==0 {; if `pos'<=colsof(mcell) {; if (`pos'==1) mat mcell = J(rowsof(mcell),1,0), mcell; if (`pos'> 1) mat mcell = mcell[.,1..`=`pos'-1'], J(rowsof(mcell),1,0), mcell[.,`pos'..colsof(mcell)]; }; else if `pos'>colsof(mcell) {; mat mcell = mcell[.,1..`=`pos'-1'], J(rowsof(mcell),1,0); }; }; local ++ pos; }; // add missing to the output; local x : list posof "." in strmcoll; if `x'==0 & ~missing(`"`missing'"') {; mat mcell = mcell, J(rowsof(mcell),1,0); }; local pos = 1; foreach mr of local l_`v2' {; local x : list posof "`mr'" in strmrow; if `x'==0 {; if `pos' <= `=rowsof(mcell)-`misrow'' {; if (`pos'==1) mat mcell = J(1,colsof(mcell),0) \ mcell; if (`pos'> 1) mat mcell = mcell[1..`=`pos'-1',.] \ J(1,colsof(mcell),0) \ mcell[`pos'..rowsof(mcell),.]; }; else if `pos' > `=rowsof(mcell)-`misrow'' {; if ~missing(`"`srow'"') {; mat mcell = mcell[1..`=`pos'-1',.] \ J(1,colsof(mcell),0) \ mcell[rowsof(mcell),1..colsof(mcell)]; }; else {; mat mcell = mcell[1..`=`pos'-1',.] \ J(1,colsof(mcell),0); }; }; }; local ++ pos; }; local x : list posof "." in strmrow; if `x'==0 & ~missing(`"`missing'"') {; if ~missing(`"`srow'"') {; mat mcell = mcell[1..`=rowsof(mcell)-1',.] \ J(1,colsof(mcell),0) \ mcell[rowsof(mcell),1..colsof(mcell)]; }; else {; mat mcell = mcell \ J(1,colsof(mcell),0); }; }; mat mall1 = (nullmat(mall1), mcell); }; // end for by; mat rblanks = J(1,colsof(mall1),.a); mat mall1 = rblanks \ mall1 ; mat mall2 = (nullmat(mall2) \ mall1); }; // end for v2; }; // Process the numbers in cells in cont groups; if ("`cont'"!="") {; cap mat drop mallx; foreach v1 of local by {; qui tabstat `cont' `weight1' if `touse', by(`v1') stat(`topt') `missopt' save; if ~missing(`"`missing'"') {; local send = `:word count `l_`v1'''+1; }; else {; local send : word count `l_`v1''; }; forv s=1(1)`send' {; mat x0 = r(Stat`s'); if (`s'==`send') & (x0[1,1]==.) {; mat mallx = (nullmat(mallx), J(rowsof(mallx),1,.)); }; else {; mat x1 = vec(r(Stat`s')); mat mallx = (nullmat(mallx), x1); }; }; }; mat mall2 = (nullmat(mall2) \ mallx); }; if ~missing("`savemat'") {; local rn "`rnames'"; local rn : subinstr local rn "_GX_" "", all; local rn : subinstr local rn "_GZ_" "", all; local rn : subinstr local rn "_VX_" "", all; mat svm = mall2; mat rownames svm = `rn'; mat colnames svm = `cnames'; local 0 `savemat'; syntax name , [replace exit]; if missing("`replace'") {; matrix `namelist'= nullmat(`namelist') \ svm; }; else {; matrix `namelist'= svm; }; `exit'; }; // Put to dataset; local rr = rowsof(mall2); local rc = colsof(mall2); local obs = `rr'+2; drop _all; qui set obs `obs'; qui gen str d_0 = ""; local i=0; foreach v of local rnames {; qui replace d_0 = `"`v'"' in `=`i'+3'; local ++i; }; local j=1; foreach v1 of local cnames {; qui gen str d_`j' = `"`v1'"' in 2; forv i=1/`rr' {; qui replace d_`j' = string(mall2[`i',`j']) in `=`i'+2'; }; local ++j; }; //Puting into xml; tempfile tmpfile; tempname ofile outfile; local lsheet "`sheet'"; if ~missing("`replace'") {; local xmlheader " "; file open `outfile' using "`tmpfile'", write; file write `outfile' `"`xmlheader'"' _n; local fontstyles "01 Times New Roman 10"; file write `outfile' `"`fontstyles'"' _n; local styles " "; file write `outfile' `"`styles'"' _n; file write `outfile' ""; file write `outfile' "created using tabmult"; file write `outfile' `"?`lsheet'?"' _n; }; else {; // append file open `ofile' using "`save'", read; file open `outfile' using "`tmpfile'", write; file read `ofile' line; // header file write `outfile' `"`line'"' _n; file read `ofile' line; // font list file write `outfile' `"`line'"' _n; file read `ofile' line; // styles file write `outfile' `"`line'"' _n; file read `ofile' line; // Description, sheetnames if strpos(`"`line'"',"tabmult")==0 {; display as error "can not append, existing file was created or changed by some other program"; exit 603; }; local sheetID=0; local sheet "`lsheet'"; local dfdfdf : subinstr local line "?`lsheet'?" "", all count(local c); while `c'>0 {; local ++sheetID; local lsheet "`sheet' (`sheetID')"; local dfdfdf : subinstr local line "?`lsheet'?" "", all count(local c); }; //while local line : subinstr local line "" "`lsheet'?"; file write `outfile' `"`line'"' _n; while r(eof)==0 {; file read `ofile' line; if `"`line'"'!="" file write `outfile' `"`line'"' _n; }; //for }; file write `outfile' "" _n; if `color'>=0 | ~missing("`gridlines'") {; file write `outfile' ""; if `color'>=0 file write `outfile' "`color'"; if ~missing("`gridlines'") file write `outfile' ""; file write `outfile' ""; }; file write `outfile' "" _n; file write `outfile' " " ; tokenize `by'; local x=1; foreach byn of local bynames {; local k: word count `l_``x'''; local ltitle " `byn'"; file write `outfile' `"`ltitle'"'; local ++x; }; file write `outfile' ""; unab vlist : d_*; foreach var of local vlist {; local datum = `var'[2]; local xmlrow "`xmlrow' `datum'"; }; file write `outfile' `"`xmlrow'"'; file write `outfile' ""; local xmlrow ""; forvalues i = 3/`=_N' {; file write `outfile' ""; foreach var of local vlist {; local datum = `var'[`i']; if (`"`datum'"'==".") local datum = "na"; if (`"`datum'"'==".a") local datum = ""; local dtype = cond(~missing(real(`"`datum'"')), "Number", "String"); local stype = cond(~missing(real(`"`datum'"')), "s01_Numbers", "s01_Var"); if (`"`opts'"'=="") & (`"`dtype'"'=="Number") local stype s01_Freq; if strpos(`"`datum'"',"_GX_") {; local stype s01_Group; local datum : subinstr local datum "_GX_" "", all; }; if strpos(`"`datum'"',"_GZ_") {; local stype s01_Var; local datum : subinstr local datum "_GZ_" "", all; local datum : subinstr local datum "_" " ", all; }; if strpos(`"`datum'"',"_VX_") {; local stype s01_Var; local datum : subinstr local datum "_VX_" " ", all; }; local xmlrow "`xmlrow' `datum'"; }; file write `outfile' `"`xmlrow'"'; file write `outfile' "" _n; local xmlrow ""; }; file write `outfile' "
" _n; file write `outfile' ""; file close _all; capture copy "`tmpfile'" "`save'", replace; if _rc {; display as error "file can not be saved at this location"; exit 603; }; display as text "note: results saved to `filename'"; if "`c(os)'"=="Windows" & missing("`c(mode)'"){; if ~missing(`"`excelpath'"') {; display `"{ stata `"winexec "`excelpath'" "`filename'" "': click here}"' _c; display as text " to open with Excel"; if ~missing("`savepath'") global `savepath' "`excelpath'"; }; if ~missing(`"`calcpath'"') {; display `"{ stata `"winexec "`calcpath'" "`filename'" "': click here}"' _c; display as text " to open with Calc"; }; }; restore; end;