I have written a small Stata program, that does frequency analysis of Likert Scale items and outputs the results as a HTML file
The program
Copy the code below and save it as likertlist.ado in your “C:/ado/plus/l ” folder. I am trying to submit it to SSC as well
*! History:
*! Version 1.
0 Vivek Gupta , 30 June 2020
*! This program opens an HTML file - Analyses Likert scaled variables and calculates frequencies
*! Finally, the results are pushed to the a HTML file
*! Inspirations- htput, htsummary and mrtab
*! Disclaimer: This program is provided "AS IS".
*! Authors are not responsible of any kind of damage, derived from the use of this program.
*! Example usage: likertlist q01-q47 using "results_scale.html", low(1) high(4) replace
*! Example usage: likertlist q01-q47 using "results_scale.html", low(1) high(4) replace noper
*! Example usage: likertlist q01-q47 using "results_scale.html", low(1) high(4) replace nop
* See: https://www.epidemiology.tech/2020/07/01/likert-scale-frequency-analysis-html-output/
capture program drop likertlist
program define likertlist
syntax varlist(min=1 max=50) using/ [if], low(integer) high(integer) [noPer] [append|replace]
if "`append'" != "" & "`replace'" != "" {
di as err "options append and replace not allowed simultaneously"
exit 198
}
if `high' < `low'{
di as err "High value (`high') is lower than the specified low value (`low')"
exit 198
}
* Check value Labels
local valLbList
foreach var of local varlist {
local varValLbl : value label `var'
local lenValLab1 : length local varValLbl
if `lenValLab1' < 2 { /* No value Label associated with variable*/
di as err "No Value Label associated with `var' variable"
exit 602
}
else {
local valLbList `valLbList' `varValLbl'
}
}
di "Value Labels Used by Variables specified: " "`valLbList'"
local valLbListUniq : list uniq valLbList
di "Unique Value Labels: " "`valLbListUniq'"
local valLbListUniqNo : list sizeof valLbListUniq
// di `valLbListUniqNo'
if `valLbListUniqNo' > 1 { /* No value Label associated with variable*/
di as err "More than one Value Label associated with specified variables"
exit 198
}
if (!regexm(`"`using'"',".htm$") & !regexm(`"`using'"',".html$") & !regexm(`"`using'"',".css$")) local using `"`using'.html"'
tempname handleLikertList
cap file open `handleLikertList' using `"`using'"', write text `replace' `append'
if _rc == 602 { /* using exist */
di as err "HTML file `using' already exists, use replace or append"
exit 602
}
preserve
** APPLY IF / in conditions
if `"`if'"' != "" quietly keep `if'
*** START WRITING HTML FILE
* Write HTML headers abnd styles for new / replace files
if "`append'" == "" {
file write `handleLikertList' "<!DOCTYPE html >" _n
file write `handleLikertList' "<html >" _n
file write `handleLikertList' "<head>" _n
file write `handleLikertList' `"<meta charset="utf-8">"' _n
* CSS Styling
file write `handleLikertList' "<style>" _n
file write `handleLikertList' "table {" _n
file write `handleLikertList' "border-collapse: collapse;" _n
file write `handleLikertList' "width: 100%;" _n
file write `handleLikertList' "}" _n
file write `handleLikertList' "th, td {" _n
file write `handleLikertList' "text-align: left;" _n
file write `handleLikertList' "padding: 8px;" _n
file write `handleLikertList' "}" _n
file write `handleLikertList' "tr:nth-child(even) {background-color: #f2f2f2;}" _n
file write `handleLikertList' "tr:hover {background-color:#e3e1ec;}" _n
file write `handleLikertList' "</style>" _n
file write `handleLikertList' "</head>" _n
}
* Write results conetnt HTML for all scenarios
file write `handleLikertList' _newline(1) "<h2> Likert Scale results </h2>"
if `"`if'"' != "" file write `handleLikertList' _newline(1) "<h2> `if' </h2>"
di "`per'"
if "`per'" == "" {
*********** WITH PERCENTAGES ****************************
*********** TABLE HEADER ****************************
file write `handleLikertList' _newline(1) "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>"
file write `handleLikertList' _newline(1) "<thead><tr><th>" "ITEM" "</th>"
file write `handleLikertList' _newline(1) "<th>" "N" "</th>"
* Fetch labels for each scale value
foreach y of numlist `low'(1)`high' {
local nameValueLabelItem : label `varValLbl' `y'
local lenValLab : length local nameValueLabelItem
if `lenValLab' < 2 {
local nameValueLabelItem ="`y'"
}
file write `handleLikertList' _newline(1) "<th colspan=2>" "`nameValueLabelItem'" " (`y') " "(N %)" "</th>"
}
file write `handleLikertList' _newline(1) "</tr> </thead>"
*********** TABLE HEADER COMPLETE ****************************
******* Table Body ****************************
file write `handleLikertList' _newline(1) "<tbody>"
foreach x of local varlist {
quietly count if `x' != .
local denom = r(N)
local varl: variable label `x'
file write `handleLikertList' _newline(1) "<tr><td>" "`varl'" "</td>"
file write `handleLikertList' _newline(1) "<td>" "`denom'" "</td>"
foreach y of numlist `low'(1)`high' {
local levelsOfLabel : label(`x') `y'
quietly count if `x' == `y'
local n = r(N)
if `denom' > 0 local pct: di %3.1f (`n'/`denom') * 100
else local pct 0
file write `handleLikertList' _newline(1) "<td>" "`n'" "</td> <td>" "`pct'" "%" "</td>" // write locals separated by commas into the text file
}
file write `handleLikertList' _newline(1) "</tr>"
}
file write `handleLikertList' _newline(1) "</tbody>"
******* Table Body closed ****************************
file write `handleLikertList' _newline(1) "</TABLE>"
** Table closed
file write `handleLikertList' _newline(1) "<br/>"
** added a line break
*********** WITH PERCENTAGES ****************************
}
else {
*********** WITHOUT PERCENTAGES ****************************
*********** TABLE HEADER ****************************
file write `handleLikertList' _newline(1) "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>"
file write `handleLikertList' _newline(1) "<thead><tr><th>" "ITEM" "</th>"
file write `handleLikertList' _newline(1) "<th>" "N" "</th>"
* Fetch labels for each scale value
foreach y of numlist `low'(1)`high' {
local nameValueLabelItem : label `varValLbl' `y'
local lenValLab : length local nameValueLabelItem
if `lenValLab' < 2 {
local nameValueLabelItem ="`y'"
}
file write `handleLikertList' _newline(1) "<th >" "`nameValueLabelItem'" " (`y') " "(N)" "</th>"
}
file write `handleLikertList' _newline(1) "</tr> </thead>"
*********** TABLE HEADER COMPLETE ****************************
******* Table Body ****************************
file write `handleLikertList' _newline(1) "<tbody>"
foreach x of local varlist {
quietly count if `x' != .
local denom = r(N)
local varl: variable label `x'
file write `handleLikertList' _newline(1) "<tr><td>" "`varl'" "</td>"
file write `handleLikertList' _newline(1) "<td>" "`denom'" "</td>"
foreach y of numlist `low'(1)`high' {
local levelsOfLabel : label(`x') `y'
quietly count if `x' == `y'
local n = r(N)
if `denom' > 0 local pct: di %3.1f (`n'/`denom') * 100
else local pct 0
file write `handleLikertList' _newline(1) "<td>" "`n'" "</td> " // write locals separated by commas into the text file
}
file write `handleLikertList' _newline(1) "</tr>"
}
file write `handleLikertList' _newline(1) "</tbody>"
******* Table Body closed ****************************
file write `handleLikertList' _newline(1) "</TABLE>"
** Table closed
file write `handleLikertList' _newline(1) "<br/>"
** added a line break
*********** WITHOUT PERCENTAGES ****************************
}
file close `handleLikertList'
** file closed
restore
end
Code language: Stata (stata)
Usage Syntax
likertlist varlist using "FILENAME.HTML", low(#) high(#) [noPer] [append | replace]
Code language: CSS (css)
Example with percentages
likertlist q01-q47 using "results_scale.html", low(1) high(4) replace
Code language: JavaScript (javascript)
Usage – with NO percentages
likertlist q01-q47 using "results_scale.html", low(1) high(4) replace noper
likertlist q01-q47 using "results_scale.html", low(1) high(4) replace nop
Code language: JavaScript (javascript)
Output
Error Handling
- Options append and replace not allowed simultaneously
- File already exists, and none of the options append or replace were used
- There is no value label associated with a variable specified
- The variables specified have different value labels
- High value < low value
likertlist q01-q47 using "results_scale.html", low(1) high(4) append replace
options append and replace not allowed simultaneously
likertlist q01-q47 using "results_scale.html", low(1) high(4)
HTML file results_scale.html already exists, use replace or append
likertlist q01-q47 age using "results_scale.html", low(1) high(4) append
No Value Label associated with age variable
likertlist q01 resi using "results_scale.html", low(1) high(5) replace per
Unique Value Labels: lbl1 LABEL_RESI
More than one Value Label associated with specified variables
likertlist q01 using "results_scale.html", low(10) high(5) replace per
High value (5) is lower than the specified low value (10)
Code language: JavaScript (javascript)
Output HTML code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
text-align: left;
padding: 8px;
}
tr:nth-child(even) {background-color: #f2f2f2;}
tr:hover {background-color:#e3e1ec;}
</style>
<h2> Likert Scale results </h2>
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>
<thead>
<tr><th>ITEM</th>
<th>N</th>
<th colspan=2>Very Difficult (1) (N %)</th>
<th colspan=2>Fairly Difficult (2) (N %)</th>
<th colspan=2>Fairly Easy (3) (N %)</th>
<th colspan=2>Very Easy (4) (N %)</th>
</tr>
</thead>
<tbody>
<tr><td>q01 find information about symptoms of illnesses that concern you?</td>
<td>144</td>
<td>11</td> <td>7.6%</td>
<td>35</td> <td>24.3%</td>
<td>73</td> <td>50.7%</td>
<td>25</td> <td>17.4%</td>
</tr>
<tr><td>q02 find information on treatments of illnesses that concern you?</td>
<td>146</td>
<td>9</td> <td>6.2%</td>
<td>39</td> <td>26.7%</td>
<td>69</td> <td>47.3%</td>
<td>29</td> <td>19.9%</td>
</tr>
</tbody>
<TABLE/>
<br/>
Code language: HTML, XML (xml)