#delim ; prog def docxtab, rclass; version 16.0; * List the variables in varlist as a table to a putdocx table. *! Author: Roger Newson *! Date: 20 January 2023 *; syntax [ varlist (min=1) ] [if] [in] , TABlename(name) [ HEADChars(namelist) FOOTChars(namelist) HEADformat(string asis) FOOTFormat(string asis) TCOLchars(namelist) TROWseq(name) varnames obsno title(passthru) note(passthru) * ]; * varlist specifies variables to be written to table. tablename() specifies the name of a table to be generated. headchars() is a list of variable characteristics containing header rows. footchars() is a list of variable characteristics containing footer rows. headformat() is a list of cell format options for header rows. footformat() is a list of cell format options for footer rows. tcolchars() is a list of variable characteristics containing corresponding column formats. trowseq() specifies a generated variable containing the table row sequence for each observation. Other options (including varnames, obsno, title(), and note()) are passed to putdocx table. *; * Count variables and mark sample *; local nvar: word count `varlist'; marksample touse, novarlist strok; * Check that table row sequence variable is new if it is requested *; if "`trowseq'"!="" conf new var `trowseq'; * Scalars to be eventually output *; tempname nrow ncol nfoot lfoot ffoot nhead lhead fhead nbody lbody fbody; summ `touse', meanonly; scal `nbody'=r(sum); if "`headchars'"=="" {; scal `nhead'=0; }; else {; local nheadl: word count `headchars'; scal `nhead'=`nheadl'; }; if "`footchars'"=="" {; scal `nfoot'=0; }; else {; local nfootl: word count `footchars'; scal `nfoot'=`nfootl'; }; * Initialise cumulative number of rows *; scal `nrow'=0; * Initialise first and last head rows *; if `nhead'==0 {; scal `fhead'=.; scal `lhead'=.; }; else {; scal `fhead'=`nrow'+1; scal `lhead'=`nrow'+`nhead'; scal `nrow'=`lhead'; }; * Initialise first and last body rows *; if `nbody'==0 {; scal `fbody'=.; scal `lbody'=.; }; else {; scal `fbody'=`nrow'+1; scal `lbody'=`nrow'+`nbody'; scal `nrow'=`lbody'; }; * Initialise first and last foot rows *; if `nfoot'==0 {; scal `ffoot'=.; scal `lfoot'=.; }; else {; scal `ffoot'=`nrow'+1; scal `lfoot'=`nrow'+`nfoot'; scal `nrow'=`lfoot'; }; * Update if title() option is present *; if `"`title'"'!="" {; foreach X in nrow lfoot ffoot lhead fhead lbody fbody {; scal ``X''=``X''+1; }; }; * Update if note() option is present *; if `"`note'"'!="" scal `nrow'=`nrow'+1; * Create initial table with just internal cells and title and note rows (if present) *; putdocx table `tablename'=data(`varlist') if `touse', `varnames' `obsno' `title' `note' `options'; * Count rows and columns (which may be affected by the options varnames, title, and/or note for rows and obsno for columns) *; qui putdocx describe `tablename'; scal `nrow'=r(nrows); scal `ncol'=r(ncols); * Add head char rows *; tempname cellcur; if `nhead'>0 {; if `"`title'"'=="" {; * Add rows at top of table *; forv i1=`=`nhead''(-1)1 {; local charcur: word `i1' of `headchars'; putdocx table `tablename'(1, .), addrows(1, before); forv i2=1(1)`nvar' {; local varcur: word `i2' of `varlist'; mata: st_strscalar("`cellcur'",st_global("`varcur'[`charcur']")); local i3=`ncol'-`nvar'+`i2'; putdocx table `tablename'(1, `i3') = (`cellcur'); }; }; }; else {; * Add rows after title row *; forv i1=1(1)`=`nhead'' {; local charcur: word `i1' of `headchars'; putdocx table `tablename'(1, .), addrows(1, after); forv i2=1(1)`nvar' {; local varcur: word `i2' of `varlist'; mata: st_strscalar("`cellcur'",st_global("`varcur'[`charcur']")); local i3=`ncol'-`nvar'+`i2'; putdocx table `tablename'(2, `i3') = (`cellcur'); }; }; }; }; * Count rows and columns again *; qui putdocx describe `tablename'; scal `nrow'=r(nrows); scal `ncol'=r(ncols); * Add foot char rows *; tempname cellcur; if `nfoot'>0 {; if `"`note'"'=="" {; * Add rows after end of table *; local nrowtemp=`nrow'; forv i1=1(1)`=`nfoot'' {; local charcur: word `i1' of `footchars'; putdocx table `tablename'(`nrowtemp', .), addrows(1, after); local nrowtemp=`nrowtemp'+1; forv i2=1(1)`nvar' {; local varcur: word `i2' of `varlist'; mata: st_strscalar("`cellcur'",st_global("`varcur'[`charcur']")); local i3=`ncol'-`nvar'+`i2'; putdocx table `tablename'(`nrowtemp', `i3') = (`cellcur'); }; }; }; else {; * Add rows before note row *; local nrowtemp=`nrow'; forv i1=1(1)`=`nfoot'' {; local charcur: word `i1' of `footchars'; putdocx table `tablename'(`nrowtemp', .), addrows(1, before); local nrowtemp=`nrowtemp'+1; forv i2=1(1)`nvar' {; local varcur: word `i2' of `varlist'; mata: st_strscalar("`cellcur'",st_global("`varcur'[`charcur']")); local i3=`ncol'-`nvar'+`i2'; putdocx table `tablename'(`=`nrowtemp'-1', `i3') = (`cellcur'); }; }; }; }; * Count rows and columns again *; qui putdocx describe `tablename'; scal `nrow'=r(nrows); scal `ncol'=r(ncols); if `nfoot'>0 {; local notepres=`"`note'"'!=""; scal `ffoot'=`nrow'-`notepres'-`nfoot'+1; scal `lfoot'=`nrow'-`notepres'; }; * Add header and footer format options if required *; if `nhead'>0 & `"`headformat'"'!="" {; putdocx table `tablename'(`=`fhead''/`=`lhead'',.), `headformat'; }; if `nfoot'>0 & `"`footformat'"'!="" {; putdocx table `tablename'(`=`ffoot''/`=`lfoot'',.), `footformat'; }; * Use table column characteristics if requested *; if "`tcolchars'"!="" {; foreach TCC in `tcolchars' {; forv i1=1(1)`nvar' {; local i2 = `i1' + ("`obsno'"!=""); local Vcur: word `i1' of `varlist'; mata: st_local("TCCcontents",st_global("`Vcur'[`TCC']")); cap putdocx table `tablename'(.,`i2') , `TCCcontents'; }; }; }; * Add table row sequence variable if requested *; if "`trowseq'"!="" qui {; gene byte `trowseq'=1 if `touse'; replace `trowseq'=sum(`trowseq')+`nhead' if `touse'; if `"`varnames'"'!="" replace `trowseq'=`trowseq'+1 if `touse'; if `"`title'"'!="" replace `trowseq'=`trowseq'+1 if `touse'; lab var `trowseq' "Table row sequence number"; }; * Return results *; foreach X in ncol nrow nfoot lfoot ffoot nhead lhead fhead nbody lbody fbody {; return scalar `X'=``X''; }; return local varlist "`varlist'"; * Table column sequences *; local tcolseq ""; forv i1=1(1)`nvar' {; local i2 = `i1' + ("`obsno'"!=""); local tcolseq "`tcolseq' `i2'"; }; local tcolseq: list clean tcolseq; return local tcolseq "`tcolseq'"; end;