surveycto
SurveyCTOフォーム(XLSForm .xlsxファイル)とサーバーデータセット(XML定義ファイル)の設計、編集、デバッグができます。フォームロジック、式、選択肢リスト、繰り返しグループ、スキップパターン、制約条件、計算、データセット公開、ケース管理、Data Explorerワークブック定義、フィールドプラグイン(「custom-name」アピアランスで フィールドに添付される.fieldplugin.zipバンドル)に対応しています。SurveyCTO、XLSForm、ODKベースのフォーム、調査フォーム、データ収集フォームの言及時、survey/choices/settingsワークシートを含む.xlsxファイル、データセットルート要素を持つXMLファイル、データモニタリングダッシュボード用のExcelワークブック定義、.fieldplugin.zipプラグインバンドルの操作時にご利用ください。新規XLSFormは常にassets/xlsform-template.xlsxのバンドルテンプレートから開始され、ゼロから構築されることはありません。
description の原文を見る
Design, edit, and debug SurveyCTO forms (XLSForm .xlsx files) and server datasets (XML definition files). Covers form logic, expressions, choice lists, repeat groups, skip patterns, constraints, calculations, dataset publishing, case management, Data Explorer workbook definitions, and field plug-ins (.fieldplugin.zip bundles attached to fields via "custom-name" appearances). Use when the user mentions SurveyCTO, XLSForm, ODK-based forms, survey forms, or data collection forms, or when working with .xlsx files that contain survey/choices/settings worksheets, XML files with dataset root elements, Excel workbook definitions for data monitoring dashboards, or .fieldplugin.zip plug-in bundles. New XLSForms always start from the bundled template at assets/xlsform-template.xlsx — never built from scratch.
SKILL.md 本文
SurveyCTO Form and Dataset Authoring
SurveyCTO is a mobile data collection platform built on the XLSForm and ODK standards, with platform-specific extensions and divergences. This skill provides SurveyCTO domain expertise for the four definition file types you may encounter:
- XLSForm form definitions (
.xlsx) — survey instruments - Dataset definitions (
.xml) — server dataset structure and publishing rules - Data Explorer workbook definitions (
.xlsx) — monitoring dashboards - Field plug-in bundles (
.fieldplugin.zip) — custom HTML/CSS/JS that takes over rendering of a single field
For a high-level orientation, read references/overview.md first.
Identifying SurveyCTO files
| File type | Format | How to recognize |
|---|---|---|
| XLSForm | .xlsx | Worksheets named survey, choices, settings |
| Dataset definition | .xml | Root element <dataset> with <definition> child |
| Data Explorer workbook | .xlsx | Worksheets named summaries, settings, global_filters, global_exclusions |
| Field plug-in bundle | .fieldplugin.zip | Zip with manifest.json, template.html, style.css, script.js at the root; referenced from a field's appearance as custom-<name> |
XLSForm starting point
Before choosing tools, before writing code, before reading further:
- New form → Step 1 is ALWAYS a literal file copy from
assets/xlsform-template.xlsxto the output path (for example,cp assets/xlsform-template.xlsx <output_path>in a Unix shell). The template is bundled with this skill atassets/xlsform-template.xlsx(resolve relative to the skill's root directory). Then proceed with the tooling rules below, uploading or opening the copied file. - Existing form → load the user's workbook as-is; do not regenerate it.
- NEVER create an
.xlsxfrom scratch. This rule applies regardless of which tools are available — it is not an MCP-only requirement and there is no fallback exemption. See Anti-pattern: building the workbook from scratch for the specific tools and idioms to avoid.
This rule is the most commonly-skipped step in this skill. If you are about to call openpyxl.Workbook(), pandas.ExcelWriter against a new path, libreoffice --headless to create a new file, or any code that writes XLSX bytes from scratch, stop and copy the template instead.
Tools you may have available
This skill is fully usable with no special tools — you have enough SurveyCTO knowledge embedded here and at the live documentation links to advise the user, describe edits in prose, and reason about forms. If additional tools are present, use them in the priority order below.
Tool-selection rule for XLSForm work: if the SurveyCTO MCP server tools are connected, you MUST use them for nontrivial XLSForm inspection, editing, validation, and export. Do not choose generic bash, python, openpyxl, LibreOffice, or spreadsheet tooling as the primary authoring path when SurveyCTO MCP tools are available. Generic tooling is only a fallback if MCP tools are unavailable, disconnected, or return an unrecoverable error.
SurveyCTO MCP server (preferred when available)
The SurveyCTO MCP server is a public, no-auth MCP server with capabilities built for this domain (XLSForm session inspect/edit/export and SurveyCTO knowledge-base search). Endpoint: https://assistant-be.surveycto.net/mcp (Streamable HTTP, stateless, no auth). If the server isn't connected when the user is editing XLSForms or asking factual SurveyCTO questions, mention it exists and offer to help install it; don't insist.
Before using any SurveyCTO MCP tool, read references/mcp.md. It is mandatory for MCP usage; do not guess tool signatures, patch semantics, concurrency rules, error handling, or limits from this abbreviated overview.
Recommended workflow
- Before any MCP tool call: read
references/mcp.md, then callget_surveycto_mcp_capabilitieswhen unsure to learn the current tool list and primer topics. If the work involves XLSForms, you must also have readreferences/xlsform.mdfirst — see Prerequisite: read the XLSForm reference. - Factual SurveyCTO questions:
kb_search→ quote the returned URLs in your answer. - Create a new XLSForm: follow the Workflow: create a new form below — it is the canonical sequence and enforces the template-first rule.
- Inspect or edit an existing XLSForm:
- Load the user's workbook (do not regenerate).
start_xlsform_sessionfor a fresh upload, orget_xlsform_summaryif resuming an existingsession_id. - Take a starting inventory from
form_summarybefore patching or paging rows. Note existing column names, choice lists (especially reusable ones likeyesno), settings values, and any warnings. Do not assume spellings or values from memory. xls_get_rows/xls_get_rowto inspect rows you intend to touch. Parallel calls are fine.xls_apply_patches— batch all related edits into one call. Usevalidate_only=trueon the full batch for risky changes. Update settings viachange_setting, notedit_row. For large batches setreturn_form_summary=falseandinclude_details=false.export_xlsform→ hand thedownload_urlor resource link to the user. Avoidformat="base64"for real workbooks. If the form references anycustom-<name>appearances, remind the user to attach the matching.fieldplugin.zipfiles in the SurveyCTO console at upload time — this skill and the MCP server only edit local files.- Usually leave the session open until TTL expiry; only call
end_xlsform_sessionfor explicit cleanup.
- Load the user's workbook (do not regenerate).
Generic spreadsheet/xlsx tooling
Use generic xlsx, Excel, Python/openpyxl, LibreOffice, or spreadsheet tools only when SurveyCTO MCP tools are not available or have failed in a way you cannot recover from. These tools can read and edit .xlsx files cell by cell, but they do not understand SurveyCTO form semantics, MCP session concurrency, or server-side formula recalculation. If you must use generic tooling, explicitly tell the user you are falling back because the MCP tools are unavailable or failed, then follow the editing rules in the Working with XLSForm .xlsx files section below.
Web fetch
If you can fetch URLs, the most authoritative live sources are:
- docs.surveycto.com — product documentation
- support.surveycto.com — Support Center articles
- www.surveycto.com — site/marketing content
Prefer these over the bundled primers when verifying current product behavior.
No file tooling at all
You can still help: describe edits in prose ("add a row to the survey worksheet with type=integer, name=age, label=Age in years, constraint=. >= 0 and . <= 120"), explain expressions, debug logic, and validate the user's draft against the rules below. The user can apply changes themselves.
Authority hierarchy for knowledge questions
When the user asks about SurveyCTO product behavior, conventions, or documentation, prefer sources in this order:
- MCP
kb_search/get_surveycto_primerif available — current, indexed, authoritative. - Live web fetch of
docs.surveycto.com,support.surveycto.com,www.surveycto.comif you can. - Bundled primers in
references/— stable summaries, may lag the live docs. - General XLSForm/ODK knowledge — only with an explicit caveat that SurveyCTO has diverged in places (
=vs==,index()vsposition(),choice-label()vsjr:choice-name(),relevancecolumn name,selected()forselect_multiple, etc.).
Cite which level you're answering from when it matters.
XLSForm overview
An XLSForm is an XLSX workbook with three worksheets:
- survey — every question, group, repeat, and calculation is a row
- choices — choice lists for
select_oneandselect_multiplefields - settings — form-wide settings (title, ID, version, language, encryption)
Key columns (survey worksheet)
| Column | Purpose |
|---|---|
type | Field type: text, integer, decimal, select_one [list], select_multiple [list], note, calculate, date, geopoint, image, begin group, end group, begin repeat, end repeat, etc. |
name | Unique variable name (no spaces/punctuation); becomes the export column |
label | Prompt text (supports label:Language for translations) |
relevance | Skip logic expression controlling when the row appears |
constraint | Validation expression (. = current value) |
calculation | Expression for calculate fields |
choice_filter | Expression filtering choices for select fields |
appearance | Display options (minimal, quick, likert, field-list, etc.) |
repeat_count | Number of repetitions for repeat groups |
Key columns (choices worksheet)
| Column | Purpose |
|---|---|
list_name | Choice list name (referenced by select_one [list] / select_multiple [list]) |
value | Stored code for the choice |
label | Display text (supports label:Language) |
Core mechanics
${fieldname}references another field's value in expressions..refers to the current field's proposed value (used in constraints).- Groups (
begin group/end group) organize fields; arelevanceon the group controls all contents. - Repeats (
begin repeat/end repeat) repeat a block;repeat_countsets the number. - Field names must be unique across the entire form.
Full reference: references/xlsform.md.
SurveyCTO expression conventions
SurveyCTO uses XPath-like expressions with several platform-specific conventions. Always use these instead of standard ODK equivalents:
| Use this (SurveyCTO) | Not this (ODK/XPath) | Context |
|---|---|---|
= | == | Equality comparison |
index() | position() | Current repeat instance number |
choice-label() | jr:choice-name() | Get choice label text |
relevance column | relevant column | Skip logic column name |
div | / | Division operator in expressions |
Select field conventions
- For
select_one: both${field} = 'value'andselected(${field}, 'value')work. - For
select_multiple: always useselected(). The=operator does not work for multi-select.
String literals
Use single quotes for string literals: ${field} = 'yes'
Exception: when the string contains single quotes, use double quotes:
if(${yesno} = 1, "a string with 'quotes' in it", "no quotes")
Common expression patterns
Skip logic (relevance): ${consent} = 'yes'
Constraint with range: . >= 0 and . <= 120
Calculated age from date of birth: int((today() - ${dob}) div 365.25)
Conditional value: if(${gender} = 'female', 'F', 'M')
Pull data from attached dataset: pulldata('households', 'head_name', 'hhid', ${household_id})
Random assignment (calculate once): once(if(random() < 0.5, 'treatment', 'control'))
Full expression reference: references/expressions.md. Live documentation: Using expressions in your forms.
Working with XLSForm .xlsx files
This section applies regardless of which file-tooling path you're using (SurveyCTO MCP server, generic xlsx tool, or describing edits in prose for the user to apply). The rules are the same; only the mechanism differs. When MCP tools are connected, use this section to plan and validate edits, but apply the edits through xls_apply_patches and export through export_xlsform.
Prerequisite: read the XLSForm reference
Before any XLSForm work — creating, editing, debugging, or answering questions about an XLSForm — read references/xlsform.md. This is mandatory regardless of which tooling path you use (MCP, generic xlsx tooling, or prose-only) and regardless of how simple the task seems. It documents SurveyCTO-specific column conventions, multi-language structure, group/repeat rules, and expression syntax that diverge from general ODK knowledge — do not rely on general ODK memory, even for "obvious" things. If anything remains unclear after reading the reference, use kb_search (or live docs at docs.surveycto.com) before proceeding.
One known-recurring gotcha worth flagging up front, because general ODK memory consistently gets it wrong: in multi-language forms, the default language goes in the unsuffixed column (label, hint, constraint message, …) and additional languages go in suffixed columns (e.g., label:Spanish). Putting the default language in a suffixed column and leaving the base empty silently breaks the form. Other divergences are documented in references/xlsform.md; read it.
CRITICAL: Always start from the template
Every new XLSForm must start from the bundled template at assets/xlsform-template.xlsx.
How to use the template:
- Make a literal file copy from
assets/xlsform-template.xlsxto the output path (for example,cp assets/xlsform-template.xlsx <output_path>in a Unix shell; resolveassets/relative to the skill's root directory). Do not regenerate the file. - If MCP tools are available, pass the copied file to
start_xlsform_sessionvia the upload URL flow and apply edits withxls_apply_patches. - If MCP tools are unavailable, open the copied file and edit it in place — add your content into the existing worksheets.
Never do any of the following:
- Do NOT create a new
.xlsxfile from scratch. - Do NOT create new worksheets and build the structure yourself.
- Do NOT delete and recreate worksheets from the template.
- Do NOT "rebuild" the form "properly" — the template IS the proper starting point.
Anti-pattern: building the workbook from scratch
Never run any of these for a new form:
from openpyxl import Workbook; wb = Workbook()(or any other code that constructs a fresh workbook object and addssurvey/choices/settingssheets to it)pandas.ExcelWriter(<new_path>)orpandas.DataFrame.to_excel(<new_path>)against a path that doesn't already contain the template's contentslibreoffice --headless --convert-to xlsxstarting from a non-template source- Writing XLSX bytes directly (zipfile +
xl/worksheets/*.xml)
These produce a technically valid but unusable form: no conditional formatting, no help-survey/help-choices/help-settings sheets, no caseid row, no hidden audit calculations, no reusable yesno choice list, no auto-updating version formula, and no color-coded row styling. The user has to redo the work in Excel by hand. Copy assets/xlsform-template.xlsx instead — this is true even when MCP tools are unavailable and you fall back to openpyxl for editing. The fallback is for editing, not for creation from scratch.
Workflow: create a new form
Follow these steps in order:
- Make a literal file copy from
assets/xlsform-template.xlsxto the output path. Do not create a new workbook object, generate worksheets, or convert from another source. - Read
references/xlsform.mdbefore designing any form content. This is mandatory — not a lookup to do if confused later. Column conventions, multi-language structure, group/repeat rules, and expression syntax all have SurveyCTO-specific details that differ from general ODK knowledge. See Prerequisite: read the XLSForm reference. - If MCP tools are available, read
references/mcp.md, then upload the copied file viastart_xlsform_session. If MCP is unavailable, open the copied workbook directly with the best available spreadsheet/XLSX tooling. - Read the starting structure fully before editing. With MCP, use the returned
form_summary; without MCP, inspect the workbook sheets directly. Note next append location, exact column names already present, existing reusable choice lists, and current settings values. - Apply related edits in one batch. With MCP, use a single
xls_apply_patchescall andchange_settingforform_id,form_title, anddefault_language; without MCP, write directly into the copied workbook's existing worksheets. - Export or save the result. With MCP, use
export_xlsformand hand thedownload_urlto the user. Remind the user to attach any required.fieldplugin.zipfiles in the SurveyCTO console at upload time.
Why the template is mandatory: It contains conditional formatting rules, help worksheets, column headers, starter metadata fields, formula-based versioning, and pre-formatted rows that cannot be reliably recreated programmatically. Skipping the template produces files that are technically valid but painful for humans to edit in Excel.
The template provides:
- survey worksheet with correct column headers and starter metadata fields, including hidden audit calculations and a
caseidrow - choices worksheet with headers and a
yesnochoice list - settings worksheet with headers and an auto-updating
versionformula - help-survey, help-choices, help-settings worksheets with reference documentation
- Conditional formatting rules that color-code rows by field type
Editing rules (apply to every path)
- Preserve all existing worksheets — including
help-survey,help-choices,help-settingsand any other sheets present in the template or existing form. - Preserve existing formatting — do not clear or overwrite conditional formatting, column widths, or cell styles.
- Only write to rows that contain or will contain data. Don't touch unused rows below your content; don't write empty strings or
Noneto clear already-empty cells. - Append new rows after existing data. Do not assume a fixed starter-row count — the template ships with several pre-populated metadata and calculation rows (including hidden audit calculations and a
caseidrow), and an existing form may have any number of rows. With MCP,add_rowappends automatically; you do not need to compute a row index, but you can derive one fromform_summary(counts.n_rows, or the largestexcel_rowinsurvey_preview_rows) or by pagingxls_get_rowsif you need it. Without MCP, scan the workbook for the first row insurvey(andchoices) wheretype/list_nameand the surrounding columns are all empty, and append there. - Don't overwrite the
versioncell insettings— it contains an auto-updating formula. (The MCP server'sexport_xlsformrecalculates this for you.) - Use plain labels by default. SurveyCTO does not render Markdown in labels, hints, notes, or messages. Prefer plain text; use simple inline HTML only when it materially helps. See Label, Hint, And Message Formatting.
Editing workflow
- Start from the right base — copy the template (new forms) or load the existing workbook.
- Read
references/xlsform.mdbefore writing any patches. This applies to edits of existing forms just as much as new ones. Do not rely on general ODK memory for column names, expression syntax, or multi-language conventions. See Prerequisite: read the XLSForm reference. - Read the existing structure so you know what's there.
- With MCP available: upload first with
start_xlsform_session, then use the returnedform_summaryas the starting overview. Callxls_get_rowsonly when you need more detail than the summary provides. - Without MCP: open and read all three sheets.
- With MCP available: upload first with
- Plan the edits — identify the rows to add/modify and the cell values.
- Apply — write cell values into the appropriate rows and columns.
- With MCP available:
xls_apply_patches. - Without MCP: write cells directly.
- With MCP available:
- Validate against the checklist below.
- Save / export — with MCP available,
export_xlsformruns formula recalculation and returns the file; without MCP, save the workbook and use the best available recalculation path.
Common operations
- Add a field: write
type,name, andlabel(at minimum) into the next empty row insurvey. Place it in the correct position relative to groups and repeats. - Add a choice list: write
list_name,value,labelrows inchoices. Ensurelist_namematches what's referenced in theselect_one/select_multipletype. - Add a group:
begin grouprow and matchingend grouprow with the samename. Place fields between them. - Add a repeat:
begin repeat/end repeatrows with matchingname. Setrepeat_countif needed. - Add skip logic: write the expression into the
relevancecolumn on the target row. - Add a constraint: write the expression into
constraint(use.for current value); write a user-facing message intoconstraint message. - Add a calculation: row with
type=calculate, uniquename, expression incalculation. - Update settings: with MCP, use
change_settingforform_title,form_id, anddefault_language. Without MCP, write those values into row 2 ofsettings. Leaveversionalone.
Validation checklist
After editing, verify:
- All
namevalues are unique across the entire form - No
namecontains spaces or special punctuation - Every
begin grouphas a matchingend group(samename) - Every
begin repeathas a matchingend repeat(samename) - Groups and repeats are properly nested (no overlapping)
- Every
select_one [list]/select_multiple [list]references a list that exists inchoices - Every choice list has at least one row with a
valueandlabel -
${fieldname}references in expressions point to fields that exist - Expressions use SurveyCTO conventions (
=not==,index()notposition(), etc.) - Labels, hints, notes, and messages use plain text or simple inline HTML fragments, not Markdown
-
settingshasform_titleandform_id - Every
custom-<name>appearance in the form has a corresponding<name>.fieldplugin.zipthat the user will attach to the form - When handing the form back to the user, explicitly remind them to attach every required
.fieldplugin.zipin the SurveyCTO console at upload time. The skill and MCP server only edit local files; they do not upload or attach anything for the user
Dataset XML definitions
Dataset definitions are XML files with a <dataset> root element. They define column structure, form attachments, and publishing rules.
Key elements
| Element | Purpose |
|---|---|
<id> | Dataset ID used in pulldata() and search() calls |
<title> | Display name |
<datasetType> | SERVER, CLIENT, or REPORT |
<fieldNames> | Comma-separated column names/order |
<formLinks> | Forms that attach this dataset for pre-loading |
<dataLinks> | Publishing rules (incoming from forms, outgoing to files) |
<caseManagementOptions> | Case management display and workflow config |
<uniqueRecordField> | Column used as unique key for upserts |
Critical notes
- Element names are case-sensitive (e.g.,
otherUserCode, nototherUsercode). - Forms in
<formLinks>and<dataLinks>must be deployed before uploading the definition. <showColumnsWhenTable>contains multiple<columnNames>child elements, not a comma-separated string.
Full reference: references/datasets-xml.md.
Data Explorer workbook definitions
Data Explorer workbooks are XLSX files with four worksheets: summaries, settings, global_filters, global_exclusions.
The summaries worksheet defines visualizations. Each row is a summary with a type (text, categorical, numeric, temporal, scatterplot, crosstab, …) and a field reference. Groups use begin group / end group with matching label values.
Full reference: references/data-explorer.md.
Field plug-ins
A field plug-in is a .fieldplugin.zip bundle (HTML/CSS/JS at the zip root) that takes over the rendering of a single form field. Plug-ins are supported only on text, integer, decimal, select_one, and select_multiple fields, and they run inside SurveyCTO Collect (Android), SurveyCTO Collect for iOS, and web forms.
When to use a field plug-in
Default to native field types and appearances. Plug-ins add real cost — attachment management, version bumps, aggressive caching, and cross-platform (Android/iOS/web) testing — so reach for them only when a native field can't deliver the needed behavior or UX. Decide in this order:
- Native fields and appearances first. Most needs are met by built-in
type/appearancecombinations. - Use as-is from the field plug-in catalog. If a maintained catalog plug-in already does what's needed, attach it without authoring anything.
- Customize an existing plug-in. Download the closest catalog plug-in or SurveyCTO
baseline-*repo as a ZIP from GitHub (Code → Download ZIP), or clone/fork it if the user is comfortable with Git, then edit the four files at the bundle root. - Start from the bundled template.
assets/field-plugin-template/is an intentionally minimal text-only skeleton — useful for an offline starting point or the smallest possible reading surface, but it omits several behaviors thatbaseline-textships (see What the bundled template omits inreferences/field-plugins.md). Add those back manually if you need them.
Agent behavior rule: when a form could benefit from a plug-in, present the trade-offs (added complexity vs. functionality/UX gained) and confirm with the user before adding any plug-in dependency. Unless the user has explicitly directed plug-in use, do not add custom-<name> appearances or attach .fieldplugin.zip files unilaterally.
Use an existing plug-in in a form
- Attach the
.fieldplugin.zipto the form (Form Designer → Attachments, or as a regular form attachment when uploading the XLSForm). - On the field, set
appearancetocustom-<filenamestem>— the part of the zip filename before.fieldplugin.zip, e.g.myplugin.fieldplugin.zip→custom-myplugin— with optional(key=value, …)parameters.
Authoring (when the user wants to build a plug-in)
Follow the decision order above. Concretely:
- Preferred starting point: download the closest SurveyCTO baseline plug-in for the field type (
baseline-text,baseline-integer,baseline-decimal,baseline-select_one,baseline-select_multiple) — or a closely related catalog plug-in — as a ZIP from GitHub's Code → Download ZIP button, then customize it. If the user prefers a Git workflow, cloning or forking works equally well; otherwise no Git tooling is required. - Minimal/offline alternative: copy
assets/field-plugin-template/. It is original code, not a copy ofbaseline-text, and intentionally leaves out several baseline behaviors (media rendering, HTML-entity unescaping in label/hint, standardnumbers/numbers_decimal/numbers_phoneappearance handling, soft-keyboard invocation, defaultplaceholderfallback, read-only display of empty values). Seereferences/field-plugins.mdfor the full list. - Edit the four files at the bundle root:
manifest.json,template.html,style.css,script.js. Always use triple-brace Mustache for{{{LABEL}}}and{{{HINT}}}(they may contain HTML). - Re-package as
<name>.fieldplugin.zipwith all files at the zip root (subdirectories get flattened on upload). Bumpmanifest.versionon every re-upload.
Testing
- Local fast loop:
assets/field-plugin-test-harness/shipsvalidate.mjs(static checks) andpreview.html(a single self-contained browser harness that renders the plug-in against editable fixtures with a stubbed host bridge). The harness works as an inline HTML/JS artifact in agent UIs that support them — pre-populate the textareas with the plug-in source and update them as the plug-in evolves. - Final validation: the in-product field plug-in console in the form designer's test view. Required before deployment; the local harness's stubs are not a complete substitute for real Android/iOS/web form runtimes.
For everything else — full manifest schema, form API (field properties, runtime CSS classes, provided/called JS functions), parameters and metadata model, Android-only intent and phone APIs, and common pitfalls — see references/field-plugins.md.
Common patterns
Cascading selects
Filter choices in one field based on the selection in another:
- In
choices, add afiltercolumn (e.g.,region) to the child list. - In
survey, setchoice_filteron the child field:region = ${region}.
Pre-loaded data lookup with pulldata()
- Create a
CLIENTdataset with the lookup data. - Attach it to the form via
<formLinks>in the dataset definition. - Use
pulldata('dataset_id', 'column_to_return', 'lookup_column', ${key_field})in acalculation.
Dynamic select list from pre-loaded data
- Create a
CLIENTdataset and attach it to the form. - In
survey, settypetoselect_one listnameandappearancetosearch('dataset_id')(or a more specific search expression). - In
choices, add one row forlistnamewherevalueandlabelcontain column names from the dataset (not literal values).
See references/xlsform.md for search() syntax patterns.
Random sampling from a repeat group
- Inside the repeat:
calculatefield withcalculation = once(random()). - Outside the repeat:
rank-index(1, ${random_calc})returns the index of the randomly-selected instance.
Use a custom field plug-in
Before adding a plug-in to a form, confirm with the user that the added complexity is worth the gained functionality, and remind them they will need to attach the .fieldplugin.zip themselves when uploading the form.
Attach the .fieldplugin.zip to the form, then set appearance on the field to custom-<filenamestem> with any parameters the plug-in expects. The <filenamestem> is the part of the zip filename before .fieldplugin.zip (for example, phonenumber.fieldplugin.zip → custom-phonenumber). The name field inside manifest.json is a human-readable display name and does not drive the appearance.
| type | name | appearance |
|---|---|---|
text | phone | custom-phonenumber(country='US', placeholder=${default_format}) |
Parameter values are evaluated by the form before the plug-in loads, so ${field} references and full SurveyCTO expressions work. In the plug-in, read parameters with getPluginParameter('country') rather than indexing fieldProperties.PARAMETERS. Full reference: references/field-plugins.md.
Publishing form data to a dataset
In the dataset XML, add a <dataLink> with:
<dataLinkClass>FORM</dataLinkClass><dataLinkType>INCOMING</dataLinkType><linkObjectId>form_id</linkObjectId><fieldMap>with JSON mapping form fields to dataset columns
Debugging common issues
| Symptom | Likely cause | Fix |
|---|---|---|
| Form won't upload | Duplicate name values | Search for duplicates in the name column |
| Form won't upload | Unbalanced groups/repeats | Check every begin/end pair |
| Field never appears | Incorrect relevance expression | Verify syntax; verify referenced fields exist |
| Constraint never passes | Wrong use of . vs ${fieldname} | In constraints, . is the current field; ${fieldname} is another field |
| Choices missing | list_name mismatch | select_one [list] must match a list_name in choices |
select_multiple logic fails | Using = instead of selected() | Always use selected(${field}, 'value') |
| Date comparison fails | Comparing string to date | Wrap with date(): ${field} > date('2024-01-01') |
| Dataset won't upload | Referenced form not deployed | Deploy all forms in <formLinks> and <dataLinks> first |
| Dataset element ignored | Case-sensitivity error | Check exact casing (e.g., otherUserCode) |
Plug-in field doesn't appear / custom-<name> ignored | Plug-in .fieldplugin.zip not attached, name mismatch, or unsupported field type | Re-attach the zip; confirm the custom-<name> token matches the .fieldplugin.zip filename stem (e.g. myplugin.fieldplugin.zip → custom-myplugin), not manifest.name; plug-ins only work on text/integer/decimal/select_one/select_multiple |
| Plug-in answer not saved | setAnswer not called, or select_multiple value joined with commas | Wire input events to setAnswer(value); for select_multiple, pass a space-separated list |
| Plug-in attachments 404 at runtime | Files placed in subdirectories inside the zip | Flatten the zip — every file at the root, no duplicate basenames |
References
| Primer | When to read |
|---|---|
references/overview.md | First — orientation, file types, how they fit together |
references/xlsform.md | Mandatory before any XLSForm work — column conventions, expressions, groups/repeats, multi-language |
references/expressions.md | Any expression work (relevance, constraint, calculation, choice_filter) |
references/datasets-xml.md | Server dataset XML definitions |
references/data-explorer.md | Data Explorer dashboards |
references/field-plugins.md | Field plug-in authoring, packaging, form API, and testing |
Key documentation links
- Designing forms: core concepts
- Using expressions in your forms
- Grouping and repeating questions
- Using constraints to validate responses
- Implementing skip patterns with relevance
- Introduction to advanced dataset usage
- Working with server dataset XML files
- Advanced use of Data Explorer workbooks
- Using field plug-ins
- Field plug-in developer documentation (GitHub)
- SurveyCTO Support Center
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- surveycto
- ライセンス
- Apache-2.0
- 最終更新
- 2026/5/8
Source: https://github.com/surveycto/surveycto-agent-skill / ライセンス: Apache-2.0