SurveyLoopr
Tips & Tricks
10 min read

Search Large Choice Lists in XLSForm

Mehrab Ali
Mehrab AliPublished November 3, 2026

To make a long list searchable in XLSForm, set the type to select_one_from_file facilities.csv and the appearance to minimal search. The options come from an attached CSV with name and label columns, and the enumerator types part of a label to narrow thousands of options to a few. Every example below compiles with pyxform and ODK Validate, the same check ODK Central runs when you upload a form.

Download example form (.xlsx)All five examples in one XLSForm, one group each. Tested with pyxform and ODK Validate; free to reuse under CC BY 4.0. Attach your own facilities.csv and crops.csv to fill it.Download

How do I add a searchable list from a CSV file?

A facility survey needs the enumerator to pick one of 3,000 health facilities. Typing them onto the choices sheet makes the form slow to open and hard to update, so they go in facilities.csv:

name,label,district
10101,Kurigram District Hospital,1
10102,Ulipur Upazila Health Complex,1
20101,Rangpur Medical College Hospital,2
20102,Mithapukur Upazila Health Complex,2

The survey sheet then needs one row:

typenamelabelappearance
select_one_from_file facilities.csvfacilityWhich health facility are you visiting?minimal search
surveychoicessettings

Three rules cover most mistakes:

  1. Keep the extension. The type is select_one_from_file facilities.csv, with .csv. This is the opposite of pulldata(), which takes the file name without it.
  2. name and label columns. The saved answer is the name column, so facility stores 10101, not the hospital's name. Use numeric or short codes there.
  3. Attach the file. The CSV is uploaded with the form, not pasted into it. It also works offline once the form is downloaded to the phone.

.xml and .geojson files work the same way. Excel files do not: save the sheet as CSV first.

What does the search appearance do?

search adds a text box above the options. The enumerator types any part of a label, upper or lower case, and only matching options stay visible. Typing ulip finds "Ulipur Upazila Health Complex".

minimal shows the list as a dropdown instead of a full screen of options. The two together, minimal search, are the usual choice for long lists, because the question then fits on a screen with other questions in a field-list group.

autocomplete is an older name for search. ODK's documentation now lists search as the recommended spelling, but forms that still use autocomplete keep working. Both also work on a list typed onto the choices sheet, so a 60-option list of districts can use minimal search without a CSV.

Warning:

Search filters on the label only. If enumerators look facilities up by code, put the code in the label too, such as 10101 Kurigram District Hospital, or they will type the code and find nothing.

How do I filter a CSV list by an earlier answer?

Any extra column in the CSV can be used in choice_filter, just as on the choices sheet. Here the district column limits the search to the facilities of the district already picked:

typenamelabelappearancechoice_filter
select_one districtvisit_districtWhich district is the facility in?minimal
select_one_from_file facilities.csvdistrict_facilityWhich health facility are you visiting?minimal searchdistrict=${visit_district}
surveychoicessettings
list_namenamelabel
district1Kurigram
district2Rangpur
surveychoicessettings

The district codes on the choices sheet (1, 2) must match the district column of the CSV exactly. Filtering first also keeps the phone fast: searching 200 facilities in one district is quicker than searching 3,000. The cascading selects guide covers multi-level filters.

What if my CSV columns are not called name and label?

Use the parameters column to say which columns to read. This is handy when the list comes straight from a facility registry export:

typenamelabelappearanceparameters
select_one_from_file facility_registry.csvregistry_facilityWhich health facility are you visiting?minimal searchvalue=facility_code label=facility_name
surveychoicessettings

value= names the column that is saved and label= the column that is shown. Only value, label, randomize and seed are accepted; any other word is an error.

For multi-select lists, select_multiple_from_file works the same way. The values in its name column must not contain spaces, because a select_multiple answer is a space-separated list:

typenamelabelappearance
select_multiple_from_file crops.csvcrops_grownWhich crops did the household grow this season?search
surveychoicessettings

To show the chosen label later in the form, for example in a confirmation note, see showing the label, not the value.

Should I still use the search() function?

Older forms load CSV options with a search('file') appearance and a placeholder row on the choices sheet. It still runs in ODK Collect, but it sits outside the ODK form specification, so newer features such as dynamic defaults do not work with it. Use select_one_from_file for new forms. For reference, this is the old pattern:

typenamelabelappearance
select_one facility_listlegacy_facilityWhich health facility are you visiting?search('facilities')
surveychoicessettings
list_namenamelabel
facility_listnamelabel
surveychoicessettings

The choices row is not an option: its name and label cells name the CSV columns to read. The function also takes a search mode, such as search('facilities', 'startswith', 'label', ${prefix}), with contains, startswith, endswith and matches. A filter written with choice_filter on select_one_from_file replaces most of these.

Common mistakes with searchable lists

These are the messages pyxform returns when ODK Central, KoboToolbox or the XLSForm converter rejects the form:

You wroteWrite insteadError you will see
select_one_from_file facilitiesselect_one_from_file facilities.csvFile name for 'select_one_from_file facilities' should end with one of the supported file extensions: '.csv', '.xml', '.geojson'
select_one_from_file facilities.xlsxSave as CSV, then facilities.csvSame "supported file extensions" error
select_one_from_file facilities.jsonRename a GeoJSON file to .geojsonSame "supported file extensions" error
choice_filter naming a question that does not existUse the exact name from the survey sheetReference variables must contain a name from the 'survey' sheet. Could not find the name 'district'.
labels=facility_name in parameterslabel=facility_nameAccepted parameters are 'label, randomize, seed, value'. The following are invalid parameter(s): 'labels'.
CSV not attached on the serverUpload it as a form attachmentNo form error; the list is empty on the phone
CSV filter column holds labels (Kurigram)Use the parent's codes (1)No error; the filtered list is empty

The last two compile without complaint and only show up in testing, so open the form on a phone before training day. For other messages, see common XLSForm errors, or paste the form into the free XLSForm validator.

Does this work the same in ODK, KoboToolbox and SurveyCTO?

The select_one_from_file and search syntax is the same in ODK and KoboToolbox, because both read XLSForm. What differs is where the file goes and how each app handles very long lists:

PlatformWhere the CSV goesNotes
ODK Central and CollectForm attachments on the draft, before publishingWorks offline. Very long lists open faster when filtered with choice_filter first
KoboToolboxProject Settings, then MediaType to filter works in KoboCollect and Enketo for select_one; forum reports show it is unreliable for select_multiple in Enketo
SurveyCTOAttached to the form as a .csv file or a server datasetLoads CSV options with a search() expression in the appearance column and a choices row naming the value and label columns

If one form must run on all three, keep the CSV columns plain (name, label, filter columns) and test it on each platform with the real file.

Why put long lists in a file?

A typed list catches problems a free-text answer never will. "Ulipur UHC", "Ulipur Upz" and "Ulipur health complex" are three spellings of one facility in a text field, and someone has to merge them in Stata later. A searchable list stores one code, 10102, every time, and updating the CSV next month does not mean editing the form.

Tip:

You can describe the list in plain language instead: "let the enumerator pick a health facility from facilities.csv, filtered by the district chosen before, with a search box". LooprAI writes the rows, then compiles the form with pyxform before anything is saved.

Build my first form free

Next: XLSForm cascading selects →

Frequently Asked Questions

How do I add a searchable dropdown in XLSForm?

Set the question type to select_one, or select_one_from_file for a CSV list, and write minimal search in the appearance column. The enumerator types part of a label and only matching options stay visible. The search is not case-sensitive and matches any part of the label.

What is the difference between search and autocomplete in XLSForm?

None in behaviour. autocomplete is an older alias for the search appearance, and both add a type-to-filter box above the options. ODK's documentation now recommends writing search. Forms that use autocomplete keep working in ODK Collect, KoboCollect and Enketo.

What columns does a select_one_from_file CSV need?

By default a name column, which is saved as the answer, and a label column, which is shown. To use other columns, write value=facility_code label=facility_name in the parameters column. Extra columns can be used in choice_filter expressions.

Why is my select_one_from_file list empty on the phone?

Usually the CSV was not uploaded as a form attachment, or a choice_filter compares against values the CSV does not have, such as labels instead of codes. The form compiles in both cases, so test on a phone with the real file before fieldwork.

How many options can a select_one_from_file list hold?

There is no fixed limit in ODK, but very long lists get slow to open and search on older phones and in web forms. Filter the list with choice_filter by an earlier answer, such as district, so each search runs over hundreds of rows rather than tens of thousands.

Does select_one_from_file work in KoboToolbox and SurveyCTO?

KoboToolbox reads it like ODK: upload the CSV under Project Settings, then Media. SurveyCTO loads CSV options with a search() expression in the appearance column and a choices row that names the value and label columns of the attached file.

No Credit Card Required

Build the form first. Add hosting when you need it.

Start free with LooprAI, then deploy a managed ODK Central server or run DataSnap checks when your project is ready.

Automation handles the mechanical work.

Researchers decide what the evidence means.