#delim ; program define sdecode; version 13.0; /* Decode an input numeric variable to an output string variable, which may be new or replace the input variable, optionally replacing unlabelled input values with formatted values. *! Author: Roger Newson *! Date: 21 July 2022 */ syntax varname(numeric) [if] [in] , [ Generate(name) replace MAXLength(string) FORMat(string) LABOnly Missing FTRim XMLSub ESub(string asis) PRefix(string) SUffix(string) FAST ]; /* -generate()- specifies the name of a new output string variable. -replace- specifies that the output string variable will replace the input numeric variable. -maxlength- is the maximum length of the output string variable. -format- is a string or string variable name specifying the format used to define output string variable values corresponding to unlabelled input numeric variable values. -labonly- specifies that only labelled values are to be decoded. -missing- specifies that missing values will be decoded (using formats). -ftrim- specifies that formatted values will be trimmed to remove left and right spaces. -xmlsub- specifies that the substrings "&", &<" and ">" will be substituted with the XML entity references "&", "<" and ">", respectively. -esub()- specifies rule for substitution of exponents in formatted output values. -prefix- specifies a prefix string (to be added on the left). -suffix- specifies a suffix string (to be added on the right). -fast- specifies that -sdecode- will not use preserve and restore. */ * Check that either -generate- or -replace- is present (but not both) and initialise -generate- accordingly *; if "`replace'"!="" {; if "`generate'"!="" {; disp as error "options generate() and replace are mutually exclusive"; error 498; }; * Save old variable order *; unab oldvars: *; tempvar generate; }; else {; if "`generate'"=="" {; disp as error "must specify either generate() or replace option"; error 498; }; confirm new variable generate; }; * Initialise -maxlength- if absent and check that -maxlength- is legal otherwise *; local maxmaxl=c(maxvlabellen); if "`maxlength'"=="" {; local maxlength=`maxmaxl'; }; else {; cap confirm integer number `maxlength'; if _rc!=0 {; disp as error "option maxl() incorrectly specified"; error 498; }; if `maxlength'<1 | `maxlength'>`maxmaxl' {; disp as error "maxlength() must be between 1 and `maxmaxl' in this form of Stata"; error 498; }; }; * Initialise -format- if absent *; if "`format'"=="" {; local format:format `varlist'; }; * Preserve if -fast- is not specified *; if "`fast'"=="" {; preserve; }; marksample touse, novarlist; * Decode labelled values (and unlabelled values if specified) *; local vallab: value label `varlist'; if `"`vallab'"'=="" {; * No value label is present *; qui gene str1 `generate'=""; local Glab: var lab `varlist'; lab var `generate' `"`Glab'"'; }; else {; * Value label is present *; decode `varlist' if `touse', gene(`generate') maxlength(`maxlength'); }; if "`labonly'"=="" {; tempvar toformat; gene byte `toformat' = `touse' & missing(`generate'); cap confirm string variable `format'; if _rc==0 {; * -format()- is a string variable *; qui replace `generate'=substr(string(`varlist',`format'),1,`maxlength') if `toformat'; }; else {; * -format()- is a format *; qui replace `generate'=substr(string(`varlist',"`format'"),1,`maxlength') if `toformat'; }; if "`missing'"=="" {;qui replace `generate'="" if `toformat' & missing(`varlist');}; if "`ftrim'"!="" {;qui replace `generate'=trim(`generate') if `toformat';}; * XML substitution *; if "`xmlsub'"!="" {; qui {; replace `generate'=subinstr(`generate',"&","&",.) if `touse'; replace `generate'=subinstr(`generate',"<","<",.) if `touse'; replace `generate'=subinstr(`generate',">",">",.) if `touse'; }; }; * Exponent substitution *; if `"`esub'"'!="" {; _esub `generate' `toformat' `esub'; }; }; qui compress `generate'; * Add prefix and/or suffix if specified *; if `"`prefix'"'!="" {; qui replace `generate'=`"`prefix'"'+`generate' if `touse'; }; if `"`suffix'"'!="" {; qui replace `generate'=`generate'+`"`suffix'"' if `touse'; }; * Replace input string variable with generated coded variable if -replace- is specified *; if "`replace'"!="" {; char rename `varlist' `generate'; drop `varlist'; rename `generate' `varlist'; order `oldvars'; }; * Restore if -fast- is not specified *; if "`fast'"=="" {; restore, not; }; end; prog def _esub; version 13.0; /* Substitute exponents in formatted values. */ syntax namelist(min=2 max=3) [ , ELZero ]; /* elzero specifies that leading zeros in the exponent will be retained. */ local generate: word 1 of `namelist'; local toformat: word 2 of `namelist'; local esub: word 3 of `namelist'; /* generate is the output string variable being generated. toformat is the indicator of observations being formatted. esub is the exponent substitution rule. */ * Check for illegal esub() values *; if `"`esub'"'=="" {; disp as error "Invalid esub()" _n "substitution_rule required"; error 498; }; local esub=lower(`"`esub'"'); if !inlist(`"`esub'"',"none","x10","rtfsuper","texsuper","htmlsuper","smclsuper","mdsuper") {; disp as error `"Illegal esub(`esub')"'; error 498; }; * Generate temporary variable toemsub and toepsub, indicating observations for positive and negative exponent substitution. *; tempvar emstart epstart toemsub toepsub; qui {; gene long `emstart'=cond(`toformat',strpos(`generate',"e-"),0); gene long `epstart'=cond(`toformat',strpos(`generate',"e+"),0); gene byte `toemsub'=`emstart'>0; gene byte `toepsub'=`epstart'>0; replace `toemsub'=0 if 0<`epstart' & `epstart'<`emstart'; replace `toepsub'=0 if 0<`emstart' & `emstart'<`epstart'; }; * Remove leading zeros if requested. *; if "`elzero'"=="" {; qui {; replace `generate' = substr(`generate',1,`emstart'+1) + trim(string(real(trim(substr(`generate',`emstart'+2,.))),"%9.0g")) if `toemsub';; replace `generate' = substr(`generate',1,`epstart'+1) + trim(string(real(trim(substr(`generate',`epstart'+2,.))),"%9.0g")) if `toepsub';; }; }; * Do esponent substitution. *; qui {; if `"`esub'"'=="x10" {; replace `generate'=subinstr(`generate',"e-","x10-",1) if `toemsub'; replace `generate'=subinstr(`generate',"e+","x10",1) if `toepsub'; }; else if `"`esub'"'=="rtfsuper" {; replace `generate'=subinstr(`generate',"e-","x10{\super -",1) if `toemsub'; replace `generate'=subinstr(`generate',"e+","x10{\super ",1) if `toepsub'; replace `generate'=`generate'+"}" if `toemsub' | `toepsub'; }; else if `"`esub'"'=="texsuper" {; replace `generate'=subinstr(`generate',"e-","\times 10^{-",1) if `toemsub'; replace `generate'=subinstr(`generate',"e+","\times 10^{",1) if `toepsub'; replace `generate'=`generate'+"}" if `toemsub' | `toepsub'; }; else if `"`esub'"'=="htmlsuper" {; replace `generate'=subinstr(`generate',"e-","x10-",1) if `toemsub'; replace `generate'=subinstr(`generate',"e+","x10",1) if `toepsub'; replace `generate'=`generate'+"" if `toemsub' | `toepsub'; }; else if `"`esub'"'=="smclsuper" {; replace `generate'=subinstr(`generate',"e-","x10{sup:-",1) if `toemsub'; replace `generate'=subinstr(`generate',"e+","x10{sup:",1) if `toepsub'; replace `generate'=`generate'+"}" if `toemsub' | `toepsub'; }; else if `"`esub'"'=="mdsuper" {; replace `generate'=subinstr(`generate',"e-","x10^-",1) if `toemsub'; replace `generate'=subinstr(`generate',"e+","x10^",1) if `toepsub'; replace `generate'=`generate'+"^" if `toemsub' | `toepsub'; }; }; end;