Development

library(XlsFormUtil)

Data examples to demo the package

The included demo xlsform comes from https://github.com/pmaengineering/ppp

fct_xlsfrom_language

## With different language
fct_xlsfrom_language( xlsformpath = system.file("demo.xlsx",
                                                package = "XlsFormUtil"))
#> [1] "English"   "Tigirigna" "Amharic"   "Oromiffa"

## without language
fct_xlsfrom_language( xlsformpath = system.file("KoBoXLSFormExamples.xlsx",
                                                package = "XlsFormUtil"))
#> NULL

fct_interview_duration

## Generate the summary chart
result <- fct_interview_duration( 
  xlsformpath = system.file("demo.xlsx", package = "XlsFormUtil"), 
  label_language = NULL,
  # wpm  word per minute - an average 180 word per minute (per default) required 
  #to read loudly the text
  wpm  = 180, 
# maxmodalities if more than 7 potential answers for a select question 
#(per default)- then we assume that those modalities will not be read by the
# enumerator - but rather selected based on an open answer - and not be
# accounted for the modalities duration estimation
  maxmodalities = 7 , 
# resptimeclose  an average 4 seconds (per default) for respondent to reply for
# closed questions
  resptimeclose  = 4,
# resptimecondopen an average of  7 seconds (per default) to reply to conditional
# text question (accounting for question type of "other, please specify"). 
  resptimecondopen = 7,
# resptimeopen an average of  10 seconds (per default) to reply to open text
# question. 
  resptimeopen = 10,
# avrgrepeat In case of repeat questions, an average 3 repeat (per default) is
# accounted for. 
  avrgrepeat = 3 
  )
#> ! You did not set up any language requirement to launch the functions... Are you sure your xlsform does not include any language specifification like `English (eng)` or `Español (es)` or `Français (fr)`

result[["plot"]]

result[["totaldur"]]
#> [1] 12

knitr::kable(head(result[["variables"]], 15))
type list_name name label label::Tigirigna label::Amharic label::Oromiffa hint hint::Tigirigna hint::Amharic hint::Oromiffa testing required test_arbitrary_strings relevant calculation constraint_message read_only appearance constraint repeatvar type2 label_duration count num_word readtime modality_duration response_duration repeat_duration question_duration question_duration_sum order seq is_repeated is_note is_question
text NA your_name 001b. Enter your name below. bla bla bla bla NA NA NA Please record your name NA NA NA hello true 1 NA NA NA NA NA NA text 3.0000000 NA NA NA 0.0000000 7 0 10.0000000 0.1666667 1 1_text once no yes
select_one school_list school_level_001 Whoa - does this question sync? 2 NA NA NA NA NA NA NA hello true 27 (begininterview = ′yes′)and({available}=‘yes’) NA NA NA NA NA select 2.3333333 12 19 6.3333333 0.0000000 4 0 6.3333333 0.2722222 2 2_select_one once no yes
text NA name_typed 001b. Enter your name below. NA NA NA Please record your name NA NA NA hello true 2 NA NA NA NA NA NA text 1.6666667 NA NA NA 0.0000000 7 0 8.6666667 0.4166667 3 3_text once no yes
note NA level1 003a. Region NA NA NA NA NA NA NA hello false 5 NA NA NA NA NA NA note 0.6666667 NA NA NA 0.0000000 0 0 0.6666667 0.4277778 4 4_note once yes no
note NA level2 003b. Zone NA NA NA NA NA NA NA hello false 6 NA NA NA NA NA NA note 0.6666667 NA NA NA 0.0000000 0 0 0.6666667 0.4388889 5 5_note once yes no
note NA level3 003c. District NA NA NA NA NA NA NA hello false 7 NA NA NA NA NA NA note 0.6666667 NA NA NA 0.0000000 0 0 0.6666667 0.4500000 6 6_note once yes no
note NA level4 003d. Locality name NA NA NA NA NA NA NA hello false 8 NA NA NA NA NA NA note 1.0000000 NA NA NA 0.0000000 0 0 1.0000000 0.4666667 7 7_note once yes no
note NA EA 004. Enumeration area NA NA NA NA NA NA NA hello false 9 NA NA NA NA NA NA note 1.0000000 NA NA NA 0.0000000 0 0 1.0000000 0.4833333 8 8_note once yes no
integer NA structure 005. Structure number NA NA NA Please record the structure number from the household listing form. NA NA NA hello true 10 NA NA Invalid response. NA NA NA number 1.0000000 NA NA NA 0.0000000 4 0 5.0000000 0.5666667 9 9_integer once no yes
integer NA household 006. Household number NA NA NA Please record the household number from the household listing form. NA NA NA hello true 11 NA NA Invalid response. NA NA NA number 1.0000000 NA NA NA 0.0000000 4 0 5.0000000 0.6500000 10 10_integer once no yes
select_one yes_no_list hh_duplicate_check CHECK: Have you already sent a form for this structure and household? NA NA NA DO NOT DUPLICATE ANY FORM UNLESS YOU ARE CORRECTING A MISTAKE IN AN EARLIER FORM. NA NA NA hello true 12 NA NA NA NA NA NA select 4.0000000 2 2 0.6666667 0.6666667 4 0 8.6666667 0.7944444 11 11_select_one once no yes
note NA duplicate_warning WARNING: Please ensure that the data processing team is aware of the duplication. NA NA NA NA NA NA NA hello false 13 (hhduplicatecheck = ′yes′)|NA|NA|yes|NA|NA||note|4.3333333|NA|NA|NA|0.0000000|0|0|4.3333333|0.8666667|12|12note|once|yes|no||selectmultiple|resubmitreasonslist|resubmitreasons|CHECK : Whyareyouresendingthisform?|NA|NA|NA|Chooseallthatapply.|NA|NA|NA|hello|true|14|({hh_duplicate_check} = ‘yes’) NA NA NA NA NA select 2.3333333 5 45 15.0000000 15.0000000 4 0 21.3333333 1.2222222 13 13_select_multiple once no yes
note NA duplicate_warning_hhmember WARNING: Each household should have ONLY ONE household roster with all household members listed on the same form. NA NA NA Please contact the central staff before sending this form. NA NA NA hello false 15 selected (${resubmit_reasons}, ‘new_members’) NA NA yes NA NA note 6.0000000 NA NA NA 0.0000000 0 0 6.0000000 1.3222222 14 14_note once yes no
select_one yes_no_list available 009. Is a member of the household and competent respondent present and available to be interviewed today? NA NA NA You should try 2 times to find the same respondent that did the original HH interview. After a second failed attempt you may interview a different household member. NA NA NA hello true 16 NA NA NA NA NA NA select 5.6666667 2 2 0.6666667 0.6666667 4 0 10.3333333 1.4944444 15 15_select_one once no yes

fct_tabulate_form

# fct_tabulate_form()

prettyform <- fct_tabulate_form( xlsformpath = system.file("demo.xlsx", 
                                              package = "XlsFormUtil") )

knitr::kable(utils::head(prettyform, 10))
Questions Choices Variables Logic
( type: start) start
( type: end) end
( type: simserial) simserial
( type: deviceid) deviceid
( type: phonenumber) phonenumber
001b. Enter your name below. bla bla bla bla
*(hint: Please record your name) ( type: text) your_name
Whoa - does this question sync? 2 ( type: select_one)

-[never] Never attended -[primary] Primary -[secondary] Secondary -[tertiary] Tertiary -[-99] No response -[never] Never Attended -[primary] Primary (1-8) -[secondary] Secondary (9-12) -[technical] Technical/Vocational -[higher] Higher -[-88] Don’t know -[-99] No response |school_level_001 |school_level_001 is relevant if begin_interview=yes and available=yes | |001b. Enter your name below. *(hint: Please record your name) |( type: text) |name_typed | | |003a. Region |( type: note) |level1 | | |003b. Zone |( type: note) |level2 | |

fct_create_flextable

fct_create_flextable(
  xlsformpath = system.file("demo.xlsx", package = "XlsFormUtil"),
  label_language = NULL )

Questions

Choices

Variables

Logic

( type: start)

start

( type: end)

end

( type: simserial)

simserial

( type: deviceid)

deviceid

( type: phonenumber)

phonenumber

001b. Enter your name below. bla bla bla bla
*(hint: Please record your name)

( type: text)

your_name

Whoa - does this question sync? 2

( type: select_one)
-[never] Never attended
-[primary] Primary
-[secondary] Secondary
-[tertiary] Tertiary
-[-99] No response
-[never] Never Attended
-[primary] Primary (1-8)
-[secondary] Secondary (9-12)
-[technical] Technical/Vocational
-[higher] Higher
-[-88] Don’t know
-[-99] No response

school_level_001

school_level_001 is relevant if begin_interview=yes and available=yes

001b. Enter your name below.
*(hint: Please record your name)

( type: text)

name_typed

003a. Region

( type: note)

level1

003b. Zone

( type: note)

level2

003c. District

( type: note)

level3

003d. Locality name

( type: note)

level4

004. Enumeration area

( type: note)

EA

005. Structure number
*(hint: Please record the structure number from the household listing form.)

( type: integer)

structure


Constraint on structure: Invalid response.)

006. Household number
*(hint: Please record the household number from the household listing form.)

( type: integer)

household


Constraint on household: Invalid response.)

CHECK: Have you already sent a form for this structure and household?
*(hint: DO NOT DUPLICATE ANY FORM UNLESS YOU ARE CORRECTING A MISTAKE IN AN EARLIER FORM.)

( type: select_one)
-[yes] Yes
-[no] No

hh_duplicate_check

WARNING: Please ensure that the data processing team is aware of the duplication.

( type: note)

duplicate_warning

duplicate_warning is relevant if hh_duplicate_check = yes

CHECK: Why are you resending this form?
*(hint: Choose all that apply.)

( type: select_multiple)
-[new_members] There are new household members on this form
-[correction] I am correcting a mistake made on a previous form
-[dissappeared] The previous form disappeared from my phone without being sent
-[not_received] I submitted the previous form and my supervisor told me that it was not received
-[other] Other reason(s)

resubmit_reasons

resubmit_reasons is relevant if hh_duplicate_check = yes

WARNING: Each household should have ONLY ONE household roster with all household members listed on the same form.
*(hint: Please contact the central staff before sending this form.)

( type: note)

duplicate_warning_hhmember

duplicate_warning_hhmember is relevant if selected resubmit_reasons new_members

009. Is a member of the household and competent respondent present and available to be interviewed today?
*(hint: You should try 2 times to find the same respondent that did the original HH interview. After a second failed attempt you may interview a different household member.)

( type: select_one)
-[yes] Yes
-[no] No

available

INFORMED CONSENT
*(hint: Find a competent member of the household. Read the greeting on the following screen.)

( type: note)

consent_start

consent_start is relevant if available = yes

( type: begin_group)

consent_group

consent_group is relevant if available=yes

Hello. My name is ______________________________ and I am working for the Addis Ababa University, and Federal Ministry of Health. Now I will read a statement explaining this investigation. Our team collects information on family planning in Ethiopia. We would like to ask you about the characteristics of your household, as well as activities related to family planning. information about you may be used for activities and family planning services in Ethiopia. data collected will be analyzed by researchers, but your name will be removed from all analyzes, so that your information remains anonymous. You can refuse to answer questions you will be asked many times as you want, and decide to stop the survey at any time. Do you have questions about this survey?

( type: note)

consent_readonly

009a. May I begin the interview now?

( type: select_one)
-[yes] Yes
-[no] No

begin_interview

begin_interview is relevant if available = yes

( type: end_group)

G. Do you recall a woman coming to your home asking questions about the members of your household, water, and sanitation?

( type: select_one)
-[yes] Yes
-[no] No
-[-77] The enumerator interviewed someone else in my household previously, not me.

confirm_interview

confirm_interview is relevant if available=yes

010. Interviewer's name: ${your_name}
*(hint: Mark your name as a witness to the consent process.)

( type: select_one)
-[1] NA

witness_auto

witness_auto is relevant if consent_obtained

010. Interviewer's name


Please record your name as a witness to the consent process. You previously entered "${name_typed}."

( type: text)

witness_manual

witness_manual is relevant if consent_obtained
Constraint on witness_manual: That is not what you entered for your name earlier in this survey.)

011. Respondent's first name.
*(hint: You should try 2 times to find the same respondent that did the original HH interview. After a second failed attempt you may interview a different household member.)

( type: text)

respondent_firstname

respondent_firstname is relevant if begin_interview=yes and available=yes

I. What is the highest level of school you attended?

( type: select_one)
-[never] Never attended
-[primary] Primary
-[secondary] Secondary
-[tertiary] Tertiary
-[-99] No response
-[never] Never Attended
-[primary] Primary (1-8)
-[secondary] Secondary (9-12)
-[technical] Technical/Vocational
-[higher] Higher
-[-88] Don’t know
-[-99] No response

school_level

school_level is relevant if begin_interview=yes and available=yes

Section 1 – Household Roster - Reinterview
*(hint: I am now going to ask a series of questions about each usual member of the household or anyone who slept in the house last night.)

( type: note)

sect_hh_roster

sect_hh_roster is relevant if consent_obtained and available=yes

Household member

( type: begin_repeat)

hh_rpt

hh_rpt is relevant if consent_obtained

( type: begin_group)

nm_grp

101. Name of household member / visitor
*(hint: Start with the head of the household)

( type: text)

firstname_raw

101a. Is this person the respondent?

( type: select_multiple)
-[1] NA

respondent_match

( type: end_group)

( type: begin_group)

mb_grp

102. What is ${firstname}'s relationship to the head of household?

( type: select_one)
-[head] Head
-[spouse] Wife/Husband
-[child] Son/Daughter
-[child_in_law] Son/Daughter-in-law
-[grandchild] Grandchild
-[parent] Parent
-[parent_in_law] Parent in law
-[sibling] Brother/Sister
-[help] House help
-[other] Other
-[-88] Don't know
-[-99] No response

relationship

103. Is ${firstname} male or female?

( type: select_one)
-[male] Male
-[female] Female

gender

104. How old was ${firstname} at their last birthday?
*(hint: If less than one year old, record 0)

( type: integer)

age


Constraint on age: Age must be less than 130 and greater than zero.)

( type: end_group)

( type: begin_group)

ms_grp

105. What is ${firstname}'s current marital status?
*(hint: If not married, probe to determine if they have ever been married and, if so, if they are divorced/separated or widowed.)

( type: select_one)
-[currently_married] Married
-[currently_living_with_partner] Living with a partner
-[divorced] Divorced / separated
-[widow] Widow / widower
-[never_married] Never married
-[-99] No response

marital_status

marital_status is relevant if age >= 10

106. Does ${firstname} usually live here?

( type: select_one)
-[yes] Yes
-[no] No
-[-99] No response

usually_live

107. Did ${firstname} stay here last night?

( type: select_one)
-[yes] Yes
-[no] No
-[-99] No response

last_night

( type: end_group)

ERROR: Members on household roster must usually live here or must have stayed here last night.

Go back and remove this household member.

( type: note)

not_usual_warn

not_usual_warn is relevant if usually_live is not yes and last_night is not yes

LCL_101. What is the religion of ${firstname}?

( type: select_one)
-[orthodox] Orthodox
-[catholic] Catholic
-[protestant] Protestant
-[moslem] Moslem
-[traditional] Traditional
-[other] Other
-[-77] No religion
-[-99] No response

religion

religion is relevant if relationship = head

This person IS NOT eligible for the female respondent questionnaire.

( type: note)

eligibility_screen_no

eligibility_screen_no is relevant if noteligible

This person IS eligible for the female respondent questionnaire.

( type: note)

eligibility_screen_yes

eligibility_screen_yes is relevant if eligible

108. Are there any other usual members of your household or persons who slept in the house last night?

( type: select_one)
-[yes] Yes
-[no] No

more_hh_members

There are other members of the household. Move forward and select "Add Group"

( type: note)

more_hh_members_add

more_hh_members_add is relevant if more_hh_members = yes

There are no other members of the household. Move forward and select "Do Not Add"

( type: note)

more_hh_members_donotadd

more_hh_members_donotadd is relevant if more_hh_members = no

( type: end_repeat)

ERROR: There is no household head.

Go back, select a head.

For each member, check that the relationship to the household head is accurate.

( type: note)

error_noheads

error_noheads is relevant if heads = 0 and consent_obtained

ERROR: There are ${heads} household heads selected:
${head_name_joined}

Go back, select only one head.

For each member, check that the relationship to the household head is accurate.

( type: note)

error_extraheads

error_extraheads is relevant if heads > 1

The respondent must be in the roster. Only one person in the roster can be marked as the respondent. Go back and make sure that only one person is selected as the respondent.

You entered the the following household members: ${names}

( type: note)

respondent_in_roster

respondent_in_roster is relevant if sumrespondent_match is not 1 and consent_obtained

109. READ THIS CHECK OUT LOUD: There are ${num_HH_members} household members who are named ${names}. Is this a complete list of the household members?
*(hint: Remember to include all children in the household.)

( type: select_one)
-[yes] Yes
-[no] No

roster_complete

roster_complete is relevant if consent_obtained
Constraint on roster_complete: Go back and update the roster.)

Section 3 - Household Observation
*(hint: Please observe the floors, roof and exterior walls.)

( type: note)

sect_hh_observation_note

sect_hh_observation_note is relevant if consent_obtained

301. Main material of the floor
*(hint: Observe.)

( type: select_one)
-[earth] Earth/Sand
-[dung] Dung
-[planks] Wood Planks
-[palm_bamboo] Palm/Bamboo
-[parquet] Parquet or polished wood
-[vinyl_asphalt] Vinyl/Asphalt strips
-[ceramic_tiles] Ceramic Tile/Terazzo
-[cement] Cement
-[carpet] Carpet
-[other] Other
-[-99] No response

floor

floor is relevant if consent_obtained

302. Main material of the roof
*(hint: Observe.)

( type: select_one)
-[no_roof] No Roof
-[thatched] Thatch/Leaf/Mud
-[rustic_mat] Rustic Mat/Plastic Sheets
-[reed_bamboo] Reed/Bamboo
-[wood_planks] Wood Planks
-[cardboard] Cardboard
-[metal] Corrugated Iron/Metal
-[asbestos] Asbestos/Cement Fiber
-[cement] Cement/Concrete
-[shingles] Roof Shingles
-[other] Other
-[-99] No response

roof

roof is relevant if consent_obtained

303. Main material of the exterior walls
*(hint: Observe.)

( type: select_one)
-[no_walls] No Walls
-[cane] Cane/Trunks/Bamboo/Reed
-[dirt] Dirt
-[bamboo_mud] Bamboo/Wood with Mud
-[stone_mud] Stone with Mud
-[uncovered_adobe] Uncovered Adobe
-[plywood] Plywood
-[cardboard] Cardboard
-[reused_wood] Reused Wood
-[corrugated_sheets] Corrugated Iron/Metal
-[cement] Cement
-[stone_lime] Stone with Lime/Cement
-[bricks] Bricks
-[cement_blocks] Cement Blocks
-[covered_adobe] Covered Adobe
-[wood_planks] Wood Planks/Shingles
-[other] Other
-[-99] No response

walls

walls is relevant if consent_obtained

Thank the respondent for his/her time.

( type: note)

thank_you

Location and Questionnaire result

( type: note)

sect_end

096. Location
Take a GPS point near the entrance to the household. Record location when the accuracy is smaller than 6m.
*(hint: Note that GPS Coordinates can only be collected when outside.)

( type: geopoint)

gps_point

098. In what language was this interview conducted?

( type: select_one)
-[english] English
-[amharic] Amharic
-[oromiffa] Oromiffa
-[tigringna] Tigringna
-[other] Other

survey_language

099. Questionnaire Result
*(hint: Record the result of the questionnaire.)

( type: select_one)
-[completed] Completed
-[not_at_home] No household member at home or no competent respondent at home at time of visit
-[postponed] Postponed
-[refused] Refused
-[partly_completed] Partly completed
-[vacant] Dwelling vacant or address not a dwelling
-[destroyed] Dwelling destroyed
-[not_found] Dwelling not found
-[absent_extended_period] Entire household absent for extended period

RQ_result

fct_render_prettyprint

# fct_render_prettyprint( dir =  system.file("", package = "XlsFormUtil"),
#   xlsformfile = "demo.xlsx",
#   label_language = NULL )

fct_xlsform_compare


## With 2 files
check <- fct_xlsform_compare(
          listfile = c( system.file("demo.xlsx", package = "XlsFormUtil"),
                        system.file("demo_adapt1.xlsx", package = "XlsFormUtil") ), 
          label_language = NULL,
          fileout = NULL)
#> demo_adapt1

# variablescompare,
knitr::kable(utils::head(as.data.frame(check[1]), 10))
name type type.ifdiff.demo_adapt1 list_name list_name.ifdiff.demo_adapt1 label label.ifdiff.demo_adapt1 hint hint.ifdiff.demo_adapt1 required required.ifdiff.demo_adapt1 relevant constraint.ifdiff.demo_adapt1 constraint relevant.ifdiff.demo_adapt1
start start NA NA NA NA NA NA NA NA NA NA NA NA NA
end end NA NA NA NA NA NA NA NA NA NA NA NA NA
simserial simserial NA NA NA NA NA NA NA NA NA NA NA NA NA
deviceid deviceid NA NA NA NA NA NA NA NA NA NA NA NA NA
phonenumber phonenumber NA NA NA NA NA NA NA NA NA NA NA NA NA
your_name text NA NA NA 001b. Enter your name below. bla bla bla bla NA Please record your name NA true NA NA NA NA NA
school_level_001 select_one NA school_list NA Whoa - does this question sync? 2 NA NA NA true NA (begininterview = ′yes′)and({available}=‘yes’) NA NA NA
name_typed text NA NA NA 001b. Enter your name below. NA Please record your name NA true NA NA NA NA NA
today calculate NA NA NA NA NA NA NA false NA NA NA NA NA
this_country calculate NA NA NA NA NA NA NA false NA NA NA NA NA
# choicescompare
knitr::kable(utils::head(as.data.frame(check[2]), 10, 10))
name list_name label label.ifdiff.demo_adapt1
never school_list Never attended NA
never school_list Never attended Never Attended
primary school_list Primary NA
primary school_list Primary Primary (1-8)
secondary school_list Secondary NA
secondary school_list Secondary Secondary (9-12)
tertiary school_list Tertiary NA
-99 school_list No response NA
-99 school_list No response NA
never school_list Never Attended Never attended

## With 3 files
check <- fct_xlsform_compare(
          listfile = c( system.file("demo.xlsx", package = "XlsFormUtil"),
                        system.file("demo_adapt1.xlsx", package = "XlsFormUtil"),
                        system.file("demo_adapt2.xlsx", package = "XlsFormUtil") ), 
          label_language = NULL,
          fileout = NULL)
#> demo_adapt1
#> 
#> demo_adapt2

run_app

# run_app()