Professional Documents
Culture Documents
Question Text
We can add text to each question in our survey by clicking on CAPI Questions in the toolbar. This allows
us to enter literal question text for the questionnaire that the interviewer will read verbatim.
Additionally, we can add interviewer instructions. Let’s start with the first few questions in section B.
For RELATIONSHIP, enter “What is (name’s) relationship to the head of the household?” For SEX enter
“Is (name) a male or a female?”. Run the application on Windows and then on Android to see how the
question text is displayed.
In addition to the text, we can add instructions to the interviewer. For example for AGE we can have:
Enter age in completed years (“000” for children less than one year old)
To make it clear to the interviewer that this is an instruction, we use italics to distinguish it from the
question. We can also use different colors and fonts as well. You can use whatever scheme you like as
long as it is consistent scheme throughout the questionnaire.
If you have your question text in Word or Excel you can copy and paste into CSPro and it will preserve
the formatting.
Page 1 of 13 05 - CAPI.docx
Help Text
In addition to question text, we can provide additional instructions to the interviewer as “help text”.
Help text is not shown by default but can be displayed by using the F2 key on Windows or tapping the
help icon next to the question text on Android.
Let’s add the following help text to the name field in section B:
Include all persons living in this house who have common arrangements for cooking and dining.
Run the application on both Android and Windows and see how the help text is displayed.
Let’s change the text for RELATIONSHIP, SEX and AGE to use %NAME% in place of “(name)”.
This will bring up the “Language” dialog box. Click on “Add” to add a language and then on “OK”.
Click on the “Add”
button to add a language
This simply specifies the names you will be using for the languages. It has no effect on the
translations.
Language names follow the same rules as names; that is, they must be unique and cannot
contain spaces. Try using abbreviations like ENG (English), SPA (Spanish), FRA (French), or
POR (Portuguese).
Page 2 of13 Language labels can contain any text to describe
05 - CAPI.docx
the language.
During data entry, the interviewer can easily switch among languages
When creating question text, you enter the question text for each language specified. Let’s look at the
question text for the “Sex” item. There is a Drop Down menu for the languages we specified in the
above steps. We select the language and then enter the question text in that language.
Now that you have created the question text in the specified languages, they can be selected during
data entry.
In Windows, we can go to the “Options” Menu and select “Change Language” and a menu of the
languages we defined will be displayed. Click on the desired language and the CAPI text will be
displayed in that language.
Tap to bring up Tap “Change Language” Tap on the language you The CAPI question is display
On Android:
the menu to select the language wish to display. In this case in the selected language. In
we will select “French”. this case, it is “French”.
Page 3 of 13 05 - CAPI.docx
Multiple Languages for Dictionary Items
To have multiple language in question text you first need to define the languages. This is similar to the
process done for multiple languages for CAPI questions; however, for dictionary items you define
languages from the Edit menu of the dictionary.
This will allow you to add labels for each language specified:
Page 4 of 13 05 - CAPI.docx
Using Occurrence Labels in Question Text
We have the following occurrence labels for the housing unit types in question F04.
We can use these occurrence labels in the question text for F04:
Anytime you use %getocclabel% in question text it is replaced by the occurrence label of the current
occurrence. With the above, the question text for the first occurrence will be “How many traditional
round hut units are in this household?” and the text for the second occurrence will be “How many
detached house units are in this household?” …
PROC NAME
setocclabel(NAMES_ROSTER, strip(NAME));
In the same proc we can also set the occurrence labels for the other rosters that use the individual
record (demographics, education, and fertility).
This works fine when we are adding a new case, however we open an existing case in modify mode the
occurrence labels are not set until we get to the person roster even though the occurrences already
exist. In modify mode, while still on section A you can scroll the case tree to see Names(1), Names(2)…
as we had before. In order to prevent this, we need to set the occurrence labels for the rosters as soon
as we open the case. What proc can we use? The preproc of the questionnaire!
Page 5 of 13 05 - CAPI.docx
We will use a loop to go through each occurrence in the names roster and set the labels for the
corresponding rows of the other rosters:
PROC HOUSEHOLDQUESTIONNAIRE_QUEST
preproc
Now that we have occurrence labels set in the individual rosters we could also use %getocclabel% in the
question text to fill in the names although using the field %NAME% directly will work just as well.
For question D05 we want to double check that the total of the children living with the women, living
elsewhere and deceased equals the number of total births. We do this by asking the question:
Just to make sure that I have this right, (name) has had in total (total number) births during her life. Is
this correct?
We can use the question text for this but we don’t have a dictionary variable for total births. We only
have the yes/no variable NUMBER_BIRTHS_CORRECT. We could create an additional dictionary variable
but instead we can simply create a logic variable in the program for totalBirths and use that as the fill
value.
We will declare it in the PROC global section so that it is available everywhere. If you declare a logic
variable inside the PROC of a dictionary variable or group, it is only available inside that PROC. Anything
in the PROC global is available in all the PROCs and in the question text.
To view the proc GLOBAL, in the logic view, click on the first item in the form tree. This shows all of the
program logic at once: the proc GLOBAL plus all the other procs. Clicking on any other item in the form
tree shows just the procs for that item.
Page 6 of 13 05 - CAPI.docx
We need to assign a value to totalBirths. Which proc do we do that in? We do that in the onfocus of
NUMBER_BIRTHS_CORRECT since we need to use it when we are in that field. The onfocus is called
every time the field is entered. We cannot do this in the preproc since the preproc is not triggered when
moving backwards through the questions.
PROC NUMBER_OF_BIRTHS_CORRECT
onfocus
// Compute total births to be used as fill in question text
totalBirths = CHILDREN_IN_HOUSEHOLD + CHILDREN_ELSEWHERE + CHILDREN_DECEASED;
What happens when one of the fields in this calculation is skipped? The value becomes notappl which
messes up the entire calculation. We need to be a little smarter in calculating our total to exclude the
skipped values.
PROC NUMBER_OF_BIRTHS_CORRECT
onfocus
Case Labels
By default, the case listing screen shows the id-items concatenated together. This is not very easy for an
interviewer to read. You can customize the case listing for a case using the setcaselabel command. As an
example let’s set the case label to the string “province-district-ea-household number: name of head of
household”. Since we need to have the name of the head of household to do this, we can add it in the
postproc of RELATIONSHIP.
PROC RELATIONSHIP
if RELATIONSHIP = 1 then
// Set label for case in case listing
// to an easier to read format.
// We do this in the relationship proc since
// that is where we first get the name of the head
// of household.
string caseLabel = maketext("%d-%02d-%03d-%03d: %s",
PROVINCE, DISTRICT, ENUMERATION_AREA,
HOUSEHOLD_NUMBER, strip(NAME(curocc())));
setcaselabel(POPSTAN2020_DICT, caseLabel);
endif;
Page 7 of 13 05 - CAPI.docx
Now after entering a case we have a much friendlier case listing:
Note that setcaselabel only works with data files of type CSPro DB.
PROC RELATIONSHIP
onfocus
// Show male or female version of value set depending on sex of the person.
if SEX = 1 then
setvalueset(RELATIONSHIP, RELATIONSHIP_MALE);
else
setvalueset(RELATIONSHIP, RELATIONSHIP_FEMALE);
endif;
PROC GLOBAL
numeric totalBirths;
array string labels(100);
array numeric codes(100);
An array logic variable is similar to a dictionary item with occurrences. A numeric array of length seven
stores seven numbers, each of which is accessed through subscripts.
We will fill in the two arrays of codes and labels with names and line numbers of the eligible women in
the household. For example, if we have the following household:
Page 8 of 13 05 - CAPI.docx
We would fill in the two arrays as follows:
PROC MOTHERS_LINE_NUMBER
onfocus
// Create the value set for child mother from all eligible
// women in household roster
numeric indexRoster;
numeric nextEntryValueSet = 1;
do indexRoster = 1 while indexRoster <= totocc(DEMOGRAPHICS_ROSTER)
labels(nextEntryValueSet) = "non-resident";
codes(nextEntryValueSet) = 87;
nextEntryValueSet = nextEntryValueSet + 1;
labels(nextEntryValueSet) = "deceased";
codes(nextEntryValueSet) = 88;
nextEntryValueSet = nextEntryValueSet + 1;
Finally, we need to terminate the array of codes with a notappl to tell CSPro not to use the whole array
and then pass the array of codes and the array labels to the setvalueset command.
codes(nextEntryValueSet) = notappl;
setvalueset(MOTHER_LINE_NUMBER, codes, labels);
Page 9 of 13 05 - CAPI.docx
Group Exercise:
Implement the dynamic value set for father line number (B15). Only show males in the household over
12. Don’t forget to include the codes for non-resident and deceased.
PROC MAIN_LANGUAGE
onfocus
enddo;
Page 10 of 13 05 - CAPI.docx
What if the interviewer doesn’t pick any language in B19? Then our dynamic value set is empty. We
should add a check to B19 to ensure that at least one language is chosen.
PROC LANGUAGES_SPOKEN
Dynamic Checkboxes
Let’s implement a dynamic value set for question G2, “were assets purchased with a loan”. Rather than
a series of yes/no question, we implement this using a single variable with checkboxes. We could have
one checkbox for each of the 12 items in the assets roster but it would be better if we only displayed the
checkboxes for the assets that the household actually possess. How do we know if the household
possess an item? The household possess the item if its quantity is greater than zero. We need to loop
through the rows of the roster and add a checkbox to the value set for each item with quantity greater
than zero. The only tricky part is that since these are checkboxes so we need to use alpha values.
In order to create a value set with alpha values we need a code array of type string. Where do we
declare it? PROC GLOBAL.
PROC GLOBAL
numeric totalBirths;
array string labels(100);
array codes (100);
array string codesString(100);
We build the value set in the onfocus of the checkboxes field. We use the alphabet string trick again to
get the alpha codes from the occurrence number. We also use the function getocclabel() to get the
occurrence label from the assets roster to use in the value set.
Page 11 of 13 05 - CAPI.docx
PROC POSSESSIONS_PURCHASED_WITH_LOAN
onfocus
// Create dynamic value set from assets that have quantity > 0
numeric nextEntry = 1;
// Mark end of array (use "" instead of notappl since field is alphanumeric)
codesString(nextEntry) = "";
setvalueset($, codesString, labels);
Page 12 of 13 05 - CAPI.docx
Exercises
1. Add question text to the rest of section B. Use fills to include the name as we did in the
examples.
2. Add a new language, the language of your choice, to the CAPI text and to the dictionary.
Translate the question text, labels and value sets for section B into the new language.
3. Add question text for section G and use the occurrence labels to fill in the name of the
possessions in the quantity and value fields.
4. Set the occurrence labels in section E to the names of the deceased using the setocclabel
command.
5. In question B06 (date of birth) use a dynamic value set for the day based on the month (January:
1-31, February: 1-28, March: 1-31…) so that the interviewer cannot enter an invalid date like
February 30 or April 31. Bonus if you can correctly handle leap years.
6. For E08 (line number of mother of deceased) use a dynamic value set to list the names of all
eligible women from the household roster.
7. Add a new record and form for section H, Agriculture:
a. for question H1, use a repeating item with occurrence labels like we did for the housing
units (F04). Add the question text using the occurrence labels as fills.
b. for question H2 parts a and b do NOT use repeating items. Use checkboxes instead. In
your dictionary, you will have two singly occurring alpha items instead of multiply
occurring numeric items and on the form you will have two non-repeating checkbox
questions instead of a roster. For H2 part c use a repeating numeric item with 7
occurrences for the ranking (this will be a roster on the form).
c. For H3, use checkboxes and
d. for H4 use a repeating numeric item with 3 occurrences.
8. Skip question H04 if “school fees” was NOT checked in question H03.
9. For question H04 create a dynamic value set of school age (age 5 to 25) members of the
household from the household roster. Add an additional option to the value set for “not a
household member” with code 99.
10. For question H02c (crops sold), use a dynamic value set to limit the options to only those crops
selected in H02b (crops produced).
11. Implement question H02d, crop ranking using a dynamic value set. The first occurrence will be
the top ranked crop, the second occurrence will be the second ranked crop, etc… Use dynamic
value sets to limit the crops for each occurrence so that it is not possible to pick the same crop
twice. In other words, show all crops for the first occurrence but if groundnuts is picked for the
first occurrence then show everything but groundnuts in the second occurrence and then if
maize is picked in the second occurrence show everything but groundnuts and maize in the third
occurrence... Bonus: display the current rankings in the question text using a logic variable and a
fill.
Page 13 of 13 05 - CAPI.docx