Displaying a summary of answers at the end of the interview
An increasingly common requirement is to print out or display a summary of answers at the end of the interview so that respondents can review them and make changes before the interview terminates. There are several ways you can do this, ranging from the simple solution of using a page statement to display all the questions that the respondent has answered through to more complex solutions that present question names and responses in tabular form using a special layout template.
The approach you use depends on the length of the survey and why you need the summary; for example, is it to make it easy for respondents to check their answers, or is it because your company needs to keep a printed record of each interview. This topic takes you through a relatively simple example that lists all the questions in the script with the answers given to each one. You can either copy it and use it as it is or copy it and use it as the basis for your own solution. Suggestions for enhancements are given at the end of the topic.
The summary page that appears at the end of the interview resembles the following example:
Note The questions are displayed in the order they are defined in the metadata section, not the order in which they are asked.
The metadata code that defines this report is:
AnswerSummary "{MyAnswers}" info;
The routing code that creates the summary’s content is as follows (long lines have been split and marked with _ at the end of each continued line):
Routing(NewRouting, InterviewModes = Web)
IOM.LayoutTemplate = "DefaultLayout.htm"
TextQuestion.MustAnswer = true
TextQuestion.Ask()
AnswerSummary.Label.Inserts["MyAnswers"].Text = BuildAnswerSummary(IOM)
AnswerSummary.Show()
Function BuildAnswerSummary(IOM)
Dim Question, Html
For Each Question In IOM.Questions
Html = Html + FormatQuestion(Question, IOM)
Next
BuildAnswerSummary = BoldItalic("ANSWER SUMMARY") + "<br/><br/>" + Html
End Function
Function FormatQuestion(Question, IOM)
Dim Html, Iteration, SubQuestion
Select Case Question.QuestionType
Case QuestionTypes.qtSimple
' A simple question. Show question text and response
If Question.Info.IsOnPath Then
Html = Html + Italicise(Question.Label.Text)
Html = Html + FormatResponse(Question)
End If
Case QuestionTypes.qtLoopCategorical, QuestionTypes.qtLoopNumeric
' Question is a loop. Format all the iterations of the
' loop
For Each Iteration In Question
Html = Html + FormatQuestion(Iteration, IOM)
Next
' If there are any responses to the questions of the
' loop then show the loop heading. Also show a break
' before loop responses (in order to group them)
If Html <> "" Then
Html = "<br/>" + Italicise(Question.Label.Text) + _
"<br/>" + Html
End If
Case QuestionTypes.qtBlock, QuestionTypes.qtCompound, _
QuestionTypes.qtPage
' Build up responses for all questions in the block/page/compound
For Each SubQuestion In Question
Html = Html + FormatQuestion(SubQuestion, IOM)
Next
End Select
FormatQuestion = Html
End Function
Function FormatResponse(Question)
' Format the response for a simple question
If (Question.QuestionDataType = DataTypeConstants.mtCategorical) Then
FormatResponse = ": " + Question.Response.Label + "<br/>"
ElseIf (Question.QuestionDataType <> DataTypeConstants.mtNone) Then
FormatResponse = ": " + CText(HTMLEncode((Question.Response.Value))) + "<br/>"
End If
End Function
Function Italicise(qlabel)
Italicise = "<i>" + qlabel + "</i>"
End Function
Function BoldItalic(qlabel)
BoldItalic = "<b><i>" + qlabel + "</i></b>"
End Function
Function HTMLEncode(Val)
Dim i
Dim char
Dim HtmlEncodedVal
For i = 0 To Len(Val) - 1
char = Mid(Val, i, 1)
Select Case char
Case "&"
char = "&"
Case "<"
char = "<"
Case ">"
char = ">"
Case """"
char = """
Case ""
char = "'"
Case Else
' Just output normal char
End Select
HtmlEncodedVal = HtmlEncodedVal + char
Next
HTMLEncode = HtmlEncodedVal
End Function
End Routing
The script consists of a number of functions:
▪BuildAnswerSummary calls the FormatQuestion function for every question in the script (IOM.Questions), even the ones that do not apply to the respondent, and then returns a string containing a page title and a list of questions and answers.
▪FormatResponses is called by FormatQuestion to extract the answers to a question.
▪FormatQuestion tests the data type of each question and then extracts the name and answer to each one. As it processes each question, the script checks whether the question is on the interview path and, if so, appends the information onto a temporary variable called Html, whose final value is written out by the AnswerSummary item. If the question is categorical, the italicized question text is appended to Html and the FormatResponse function is called to process the answer.
When the script encounters a loop, it processes each question in the loop in the same way that it does for simple questions (the FormatQuestion function calls itself to do this). If any of the questions in the loop has an answer, the function inserts the italicized loop question text in front of the repeated questions.
When it encounters a block, compound, or page item, the function runs recursively to extract answers to every subquestion in the block, compound, or page.
When all questions have been processed, the function returns a string containing a list of question names and answers. This is displayed by the MyAnswers insert in the AnswerSummary item.
Suggested enhancements
▪Display an explanation of the summary at the top of the page, or on a previous page, so that the respondent knows how to proceed. For example, if you are not going to allow answers to be changed once the summary is displayed, you need to tell respondents this before they see the page.
▪Hide unwanted navigation buttons. For example, you might want to display only Next for accepting the answers, and Goto for skipping back and changing answers.
▪Display the summary in multiple columns using, for instance: AnswerSummary.Style.Columns=2
▪Apply a layout or question template that improves the overall appearance of the page.
▪Display the summary as a table, with the questions in one column and the answers in the other. Even without a template this will make the whole thing easier to read.
▪Use the OnAfterQuestionAsk event to append questions and answers to the summary as each question is answered, rather than dealing with all questions in one go at the end of the interview. This has the advantage of automatically excluding unasked questions from the summary.
Here’s a variation of the previous example that implements some of these suggestions.
IOM.Navigations.Remove(NavigationTypes.nvStop)
'Hide Stop Button
IOM.Navigations.Remove(NavigationTypes.nvPrev)
'Hide Previous Button
' Enclose all the answers that were formatted in a <table> tag
With AnswerSummary.Label.Inserts["MyAnswers"]
.Text = "<table border=""1"" width=""100%"">" + .Text +_
"</table>"
End With
AnswerSummary.Show()
Sub OnInterviewStart(IOM)
IOM.Questions["AnswerSummary"].Label.Inserts["MyAnswers"]. _
Text = BoldItalic("ANSWER SUMMARY")
End Sub
Sub OnAfterQuestionAsk(Question, IOM)
With IOM.Questions["AnswerSummary"].Label.Inserts["MyAnswers"]
.Text = .Text + FormatQuestion(Question, IOM)
End With
End Sub
Function FormatQuestion(Question, IOM)
Dim Html, Iteration, SubQuestion
Select Case Question.QuestionType
Case QuestionTypes.qtSimple
' A simple question. Show question text and response
If Question.Info.IsOnPath Then
Html = Html + "<tr>"
Html = Html + "<td>" +
Italicise(Question.Label.Text) + "</td>"
Html = Html + FormatResponse(Question)
Html = Html + "</tr>"
End If
Case QuestionTypes.qtLoopCategorical,
QuestionTypes.qtLoopNumeric
' Question is a loop. Format all iterations of the loop
For Each Iteration In Question
Html = Html + FormatQuestion(Iteration, IOM)
Next
' If there are any responses to the questions of the
' loop then show the loop heading. Also show a break
' before loop responses (in order to group them)
If Html <> "" Then
Html = "<tr><td>" + Italicise(Question.Label.Text) + "</td></tr>" + Html
End If
Case QuestionTypes.qtBlock, QuestionTypes.qtCompound,
QuestionTypes.qtPage
' Build up responses for all questions in the block/page/compound question.
For Each SubQuestion In Question
Html = Html + FormatQuestion(SubQuestion, IOM)
Next
End Select
FormatQuestion = Html
End Function
Function FormatResponse(Question)
' Format the response for a simple question
If (Question.QuestionDataType =
DataTypeConstants.mtCategorical) Then
FormatResponse = "<td>" + Question.Response.Label + "</td>"
ElseIf (Question.QuestionDataType <> DataTypeConstants.mtNone)
Then
FormatResponse = "<td>" + HTMLEncode(CText(Question.Response.Value)) + "</td>"
End If
End Function
Function HTMLEncode(Val)
Dim i
Dim char
Dim HtmlEncodedVal
For i = 0 To Len(Val) - 1
char = Mid(Val, i, 1)
Select Case char
Case "&"
char = "&"
Case "<"
char = "<"
Case ">"
char = ">"
Case """"
char = """
Case " " To "~"
' Just output normal char
Case Else
char = "&#" + AscW(char) + ";"
End Select
HtmlEncodedVal = HtmlEncodedVal + char
Next
HTMLEncode = HtmlEncodedVal
End Function
Function Italicise(qlabel)
Italicise = "<i>" + qlabel + "</i>"
End Function
Function BoldItalic(qlabel)
BoldItalic = "<b><i>" + qlabel + "</i></b>"
End Function
In this example, the task of extracting questions and answers has been moved into the OnAfterQuestionAsk event. This means that the answer summary is built up as each question is answered rather than at the end of the interview. The appearance of the summary has been improved by writing it out as a table, and the Previous and Stop navigation buttons have been hidden to prevent the respondent changing answers. Here’s the page that this script produces:
See also