Formulas

You can use formulas to create smarter forms with ArcGIS Survey123.

Previous questions must always be referred to in formulas with the format ${field_name}.

Operators

The following operators are supported in Survey123:

OperatorDescriptionExample

.

The current answer

.=1

+

Addition

${question_one} + 4

-

Subtraction

${question_one} - 4

*

Multiplication

${question_one} * 4

div

Division

${question_one} div 4

=

Equal

${price}=9.80

!=

Not equal

${price}!=9.80

<

Less than

${price}<9.80

<=

Less than or equal to

${price}<=9.80

>

Greater than

${price}>9.80

>=

Greater than or equal to

${price}>=9.80

and

And

${price}>9.00 and ${price}<9.90

mod

Modulus (division remainder)

${question_one} mod ${question_two}

or

Or

${price}=9.80 or ${price}=9.70

Functions

The following functions are supported in Survey123:

FunctionDescriptionExample

boolean(question, expression, or value)

Returns true if the value provided is not null.

It's recommended that you use boolean-from-string() instead.

Caution:

This function always returns true in the Survey123 web app. For alternatives, see Empty values.

boolean(${question_one})

boolean-from-string()

Returns true if the string provided is 'true' or '1'. Otherwise, returns false.

boolean-from-string(${question_one})

coalesce(value1, value2)

Returns the first nonempty value. This function supports only two values.

coalesce(${question_one}, ${question_two})

concat(value1, value2, …)

Returns the concatenation of the string values.

concat(${question_one}, ' and ', ${question_two})

contains(string, substring)

Returns true if the given string contains the substring.

contains(${question_one}, 'red')

count(repeat)

Returns the amount of responses to a given question across repeats. For more information, see Aggregate functions.

Note:

When used in the Survey123 field app, this function can be placed inside or outside of the repeat. If the function is to be used in the Survey123 web app, it must be placed outside of the repeat. A count value from outside the repeat can be referenced in a calculation inside the repeat.

count(${question})

count-selected(question)

Returns the number of selected answers for select_one and select_multiple questions. This function also returns the number of attached files for image, audio, and file questions using the multiline appearance.

count-selected(${question_one})

date(question, expression, or value)

Converts a number or string to a date object, without preserving time.

date('2017-05-28T04:39:02+10:00')

date-time(question, expression, or string)

Converts a number or string to a date object.

date-time('2017-05-28T04:39:02+10:00')

decimal-date-time(question, expression, or string)

Converts a date object to a decimal date-time number.

decimal-date-time(${date_question})

decimal-time(question, expression, or string)

Converts a time object to a number representing a fractional day in the device's time zone.

decimal-time(${time_question})

ends-with(string, substring)

Returns true if the given string ends with the substring.

ends-with(${question_one}, 'hand.')

false()

False

false()

format-date()

Fits an existing date or time value to a defined format.

format-date(${previous_time}, '%H:%M')

if(condition, a, b)

If the condition evaluates to true, returns a; otherwise, returns b.

if(selected(${question_one}, 'yes') and selected(${question_two}, 'yes'), 'yes', 'no')

indexed-repeat(question, repeat, index number)

Returns the value from a specific question in a repeat record. For more information, see Repeats.

indexed-repeat(${room_no}, ${floor}, 3)

int(question, expression, or value)

Converts to integer. Conversion varies depending on data type.

Note:

If this function is empty, it will return NaN and the question will remain empty.

int(${question_one})

join(separator, question)

Concatenates all answers to a given question in a repeat, separated by the given separator.

Note:

When used in the Survey123 field app, this function can be placed inside or outside of the repeat. If the function is to be used in the Survey123 web app, it must be placed outside of the repeat. A join value from outside the repeat can be referenced in a calculation inside the repeat.

join(',', ${question_in_repeat})

jr:choice-name(choice_name, 'question')

Used for select_one questions. It returns the label associated with the name of the choice in the given question. Be aware that the question must be defined inside quotes.

jr:choice-name(${select_one}, '${select_one}')

Used for select_multiple questions. It returns the label associated with the name of the choice in the given question. The selected-at() function must be used to extract the label for individual answers. Be aware that the question must be defined inside quotes.

jr:choice-name(selected-at(${select_multiple}, 3), '${select_multiple}')

max(value1, value2, ...)

Returns the maximum value in a given range, or to a single question across repeats.

max(${question_one}, ${question_two})

min(value1, value2, ...)

Returns the minimum value in a given range, or to a single question across repeats.

min(${question_one}, ${question_two})

not(expression)

Returns a false value if the expression would return true, and a true value if the expression would return false.

not(selected(., 'yes'))

now()

Returns a time stamp for this instant. This function is used in time and dateTime questions. It behaves the same as today() in date questions.

now()

number(question, expression, or value)

Converts to number. Conversion varies depending on data type.

Note:

If this function is empty, it will return NaN and the question will remain empty.

number(${question_one})

once()

If a question already has a value, returns the existing value. This function is useful when using random() or uuid() in a repeated question to ensure the value doesn't change when you browse through the repeat records in the form.

once(uuid())

position(..)

Returns the index of the current record in a repeat. For more information, see Repeats.

position(..)

pulldata()

Returns a value from an external CSV file. For more information, see Retrieve a value from CSV.

pulldata('users', 'email', 'name', ${respondent_name})

pulldata("@exif")

Returns a value from the EXIF metadata in an image. For more information, see Extract image metadata.

pulldata("@exif", ${photo}, "GpsLatitude")

pulldata("@geopoint")

Returns a value from a geopoint question. For more information, see Extract geopoint values.

pulldata("@geopoint", ${location}, "horizontalAccuracy")

pulldata("@javascript")

Runs a JavaScript function in the form and returns the result. For more information, see JavaScript functions in survey forms.

pulldata("@javascript", "functions.js", "uniqueID", ${buildings})

pulldata("@json")

Returns a value from a JSON object. For more information, see Retrieve a value from JSON.

pulldata("@json", ${json_output}, "attributes.ZIP_CODE")

pulldata("@layer")

Queries an ArcGIS feature layer, feature table, or query enabled map service and returns the result. For more information, see Query a feature layer.

pulldata("@layer", "getRecordAt", "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/World_Time_Zones/FeatureServer/0", ${location})

pulldata("@property")

Returns information about the device or signed-in user. For more information, see Device and user properties.

pulldata("@property", 'username')

random()

Returns a random value between 0 (inclusive) and 1 (exclusive).

random()

regex()

Applies a regular expression to the question's input. Returns true if the pattern is matched. For more information, see Regular expressions.

regex(., '^\d{5}$')

selected(question, value)

Checks whether answer is selected. This function is used for select_one and select_multiple questions.

selected(${question_one}, 'a')

selected-at(question, number)

Used for select_multiple questions. It returns the name of the choice selected for the given number, counted starting from zero; for example, '2' will return the third selected choice.

selected-at(${question_one}, 2)

starts-with(string, substring)

Returns true if the given string starts with the substring.

starts-with(${question_one}, 'The')

string(question, expression, or value)

Converts to string. Conversion varies depending on data type.

string(${question_one})

string-length(question, expression, or value)

Returns the length of a nonempty string.

string-length(${question_one})

substr(question, start, end)

Returns the substring beginning at the specified start and extends to the character at index end -1, where start and end begin at 0.

substr(${question_one}, 1, 2)

sum(repeat)

Returns the sum of all responses to a given question across repeats. For more information, see Aggregate functions.

Note:

When used in the Survey123 field app, this function can be placed inside or outside of the repeat. If the function is to be used in the Survey123 web app, it must be placed outside of the repeat. A sum value from outside the repeat can be referenced in a calculation inside the repeat.

sum(${question})

today()

Returns today's date, internally stored as local midday. This function is used in date questions.

today()

true()

True

true()

uuid()

Returns a random UUID string.

uuid()

version()

Returns the version of the survey defined in the settings worksheet.

version()

The following mathematical functions are supported in Survey123:

FunctionDescriptionExample

acos(value)

Returns the arc cosine of the value.

acos(${question_one})

asin(value)

Returns the arc sine of the value.

asin(${question_one})

atan(value)

Returns the arc tangent of the value.

atan(${question_one})

atan2(value1, value2)

Returns the arc tangent of the quotient of the values.

atan2(${question_one}, ${question_two})

cos(value)

Returns the cosine of the value as an angle in radians.

cos(${question_one})

sin(value)

Returns the sine of the value as an angle in radians.

sin(${question_one})

tan(value)

Returns the tangent of the value as an angle in radians.

tan(${question_one})

exp(value)

Returns the natural exponent of the value.

exp(${question_one})

exp10(value)

Returns 10 to the power of the value.

exp10(${question_one})

log(value)

Returns the natural logarithm of the value.

log(${question_one})

log10(value)

Returns the base-ten logarithm of the value.

log10(${question_one})

pi()

Returns pi.

pi()

pow(value, power)

Returns the value to the power specified.

pow(${question_one}, 3)

round(value, places)

Returns the rounded value.

round(${question_one}, 5)

sqrt(value)

Returns the square root of the value.

sqrt(${question_one})

Constraints

Adding a constraint to a survey question restricts the accepted inputs for a response. This can include a specific range of numbers, combinations of letters and numbers, or general pattern matching. In your spreadsheet, the constraint expression is entered into the constraint field and informational text is entered into the constraint_message column of the survey worksheet. In the constraint expression, the input for the question is always represented by a period.

For example, you can use the following formula to restrict the input of an integer field to positive numbers only:

.>= 0

This formula, when applied to a date field, prevents the user from entering a value earlier than today:

.>= today()

You can also use calculations in constraints. This formula performs a calculation to only allow the user to select dates between today and 14 days from today:

(.>= today()) and (.<=(today() + (1000 * 60 * 60 * 24 * 14)))

Tip:

To avoid unexpected errors, if your formula includes decimal values between -1 and 1, include a leading zero in your values. Without the leading zero, the decimal can be mistaken for the operation character . (or -.). For example, the following expression will fail:

.> .25 and .< 24.25

The following expression will run as expected:

.> 0.25 and .< 24.25

Regular expressions

A regular expression is a sequence of characters used to match patterns in strings. In Survey123, if the pattern is matched, the expression will return true; otherwise, if the pattern is not matched, the expression will return false.

You can use regular expressions in a variety of ways for pattern matching to constrain valid responses to a given format or to ensure it contains specific content. This example requires that the response to the question include the word road somewhere in it:

regex(., 'road')

The period used at the start of these examples applies the expression to the current field. Adding the name of another field in its place instead applies the regular expression to that field, which is ideal for relevant expressions. The comma acts as a separator between this field definition and the expression.

This regular expression ensures that the response exactly matches the word road, with nothing before or after it:

regex(., '^road$')

Regular expressions are ideal for confining the input of a question to a standard format. This example accepts only the input of a United States five-digit ZIP code:

regex(., '^\d{5}$')

This example matches the response to the current format of Indonesian license plates, as in the following photo:

Standard Indonesian license plate

regex(., '^[A-Z]{1,2}\d{4}[A-Z]{2,3}$')

More loosely standardized formats can require complex regular expressions. This regular expression used by the Survey123 web app constrains the input of a string field to match the format of an email address:

regex(., '^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')

This modification of the above expression constrains input to match the format of an email address, while accepting non-English characters:

regex(., '^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\u0400-\uffff\-0-9]+\.)+[a-zA-Z\u0400-\uffff]{2,}))$')

This example, also using a regular expression from the Survey123 web app, limits a field to only accept responses that match the format of a web address:

regex(., '^((https?|ftps?)\://|)(((?:(?:[\da-zA-Z](?:[-\da-zA-Z]{0,61}[\da-zA-Z])?)\.)+(?:[a-zA-Z](?:[-\da-zA-Z]{0,61}[\da-zA-Z])?)\.?)|localhost)(\:\d+)?(/(?:[^?#\s/]+/)*(?:[^?#\s/]+(?:\?[^?#\s/]*)?(?:#[A-Za-z][\w.:-]*)?)?)?')

For more information about regular expressions, refer to the Mozilla Developer Network documentation. For a list of characters and their functions in regular expressions, see the Reference worksheet in the Survey123 templates or refer to the Quick reference.

Calculations

Calculations are performed in the calculation column for a question. Calculations are often associated with the calculate type of question, but they can also be applied to integer, decimal, text, and select_one questions. The outcome of the calculation can be used to populate relevant or constraint expressions by referring to the field name of the calculate question.

The calculate question type is hidden and doesn't display on a form. This means it can also be used to hold values that don't need to be displayed on the form but are included in the feature layer.

For example, you can create a question of type calculate, name it calc, and insert the following expression in its calculation column:

${question_1} + ${question_2} + ${question_3}

Use the result to set the relevance for the next question:

${calc} <= 100

Calculations can be used with the responses in date fields. This calculation estimates the number of years between a date entered and today, ideal for calculating somebody's age:

int((today() - ${birth_date}) div (1000 * 24 * 60 * 60 * 365.25))

Sometimes you only need part of a value or a truncated version of a complete answer. The substr operator returns only part of a string, defined by the numbers after it. The first character determines the starting point of the selection, while the second value determines the length (if no second value is present, it continues until the end of the string). In this example, the substr operator removes all but the string from characters 10 to 15:

substr(${previous_question}, 10, 15)

When the first number is negative, substr starts counting from the end of the string instead of the beginning. This example returns only the last five characters of the answer:

substr(${previous_question}, -5)

You can use the calculationMode parameter to control when calculations are calculated in the form. For more information, see Calculation mode.

You can also use the calculation column for aggregate functions in repeats. For more information, see Repeats.

Adhere to the following best practices when using calculations:

  • When using random(), consider adding a constant to avoid getting zero (0) as a result, for example, random()+0.5. A value of 0 may result in a blank answer.
  • As with constraints, ensure that all decimal values between -1 and 1 in your formula have a leading 0, as leading with a decimal point causes errors.
  • The data type of a calculation result is dependent on the data type of each element of the calculation. If a calculation is performed on two integers, the calculation result is an integer. If a calculation includes a string data type, you may find that a + operator concatenates values instead of adding them. To avoid unexpected results, use the number() function to ensure string values in a calculation are treated as numbers. For example, the calculation to add question1 (of type integer) to question2 (of type text) is ${question1} + number(${question2}).
Tip:

The XLSForm default binding type for a calculate question is string. To overwrite this default, enter the required type (for example, int or decimal) in the bind::type column for your question. Alternatively, you can use the desired question type (for example, integer or decimal) and set the appearance for this question to hidden.

Caution:

Using mathematical functions or operators with text questions returns a result of NaN in the Survey123 web app. To concatenate text questions, use the concat() function instead of the + operator.

Complex mathematical functions

The calculation column can also handle more complex mathematical operations. This example determines the area of a plot given its radius, using the pi and power functions:

pi() * pow(${plot_radius}, 2)

A common method of measuring the height of a tree is to measure the angle from eye-level at an observation point to the top of the tree, and the distance from the same observation point to the tree base. If the angle to the top of the tree is measured in degrees, the following calculation would be used to convert it to radians:

${angle_to_top_degrees} * (pi() div 180)

With the angle measurement now in radians, the height of the tree (rounded to two decimal places) can be determined with the following calculation:

round(((tan(${angle_to_top_radians}) * ${distance_to_tree}) + ${height_to_eyes}),2)

Date formatting

You can use the format-date function in the calculation field to format date and time values. This can be useful when you want to display portions of dates to users or persist them as strings.

In this example, the value contained in a previous time or dateTime question is returned in 24-hour time:

format-date(${previous_time},'%H:%M')

The qualifiers you can use in the format-date function are as follows:

QualifierDescription

%3

0-padded millisecond ticks (000-999)

%a

Three-letter short text day

%b

Month name abbreviated

%d

0-padded day of month

%e

Day of month

%h

Hour (24-hour time)

%H

0-padded hour (24-hour time)

%m

0-padded month

%M

0-padded minute

%n

Numeric month

%S

0-padded second

%W

Week number

Note:

The %W qualifier can't be used in a format-date function in which the date question uses a calculation. This qualifier works with a date question that has a default.

%y

2-digit year

%Y

4-digit year

Note:

dateTime questions don't support time resolutions below one minute. To capture a time resolution with dates that is lower than one minute, consider using the start and end questions.

Empty values

When using constraints and calculations that refer to other questions, consider what occurs when that question is empty (that is, it has no response). Empty values are represented as follows:

  • NaN (not a number) for integer and decimal questions. This is a special value that represents the absence of a valid value.
  • '' (an empty string) for text questions. The default data type for select_one, select_multiple, rank, and hidden questions is also text. When select_one, select_multiple, and hidden question types are empty, or when a rank question hasn't been altered by the user, they contain an empty string.

Depending on whether the value is a number or text, the behaviors in calculations differ.

In integer or decimal questions, the following behaviors occur:

  • Any mathematical expression with a value of NaN fails to complete, and the question remains empty.
  • The min() and max() functions complete and ignore any NaN values.
  • The NaN value compared to any other value is only true in a calculation of an is not equal value comparison. All other expressions result in false.

In text questions, the following behaviors occur:

  • The concatenation of text questions completes if empty values are present. For example, concat("Hello" + ${firstName}, ", how are you?") results in "Hello , how are you?" when the question firstName is empty.
  • The min() and max() functions complete and ignore any empty strings.
  • An empty text answer is equal to another empty text answer and is always less than any nonempty text.

You can determine whether a question is empty using the string-length function. The string-length function can be used with all question types. For example, string-length(${Question1}) returns 0 if Question1 is empty.

You can also determine whether a select_one or select_multiple question is empty using the count-selected function. For example, count-selected(${question2}) returns 0 if no selection has been made for question2.

Select_multiple and rank questions

The responses to select_multiple and rank question types are stored differently than all other question types. Each checked answer in a select_multiple question is entered in the order it was selected, separated by commas. For example, selecting answers 'A' and 'B' in that order presents the response as 'A,B'. A rank question also stores its answers in a comma-separated list in order from highest to lowest rank at the time of submission.

Some XLSForm features do not work with select_multiple and rank questions. For example, if you enter the answer 'A' in the relevant column of a question referring to your select_multiple question, and the survey response is 'A,B', the response is not considered relevant. In this case, the solution is to use the selected() function, which determines whether any one of the values appears in the list.

The following expression, when used in the relevant column of a question, displays the question if the user has selected 'A' as one of the responses in the referenced select_multiple question. Additional responses in the select_multiple question do not change this behavior.

selected(${previous_question}, 'A')

Retrieve a value from a .csv file

You can use the pulldata() function in the calculation column of a question to preload data from a .csv file. There are two ways to include a .csv file: manually place the file in the survey's media folder or link to a .csv file hosted in ArcGIS.

The pulldata() function requires the following four parameters to be specified in order:

  1. The name of the .csv file that contains the list of values. The name does not include the .csv file name suffix.
  2. The name of the column in the .csv file that contains the value you want to return.
  3. The name of the key field in the .csv file that you will use to look up the value.
  4. The key value to look up in the key field.

These values can be defined directly or through variables defined elsewhere in the survey. In the following example, the calculation returns the email address of somebody named in a previous question from a .csv file named info:

pulldata('info', 'email', 'name', ${respondent_name})

The same pulldata() function also works in the constraints column, preventing the user from submitting answers that are not in the .csv file. In the constraints column, this same formula prevents the form from accepting any values that are not in the .csv file's name column.

There are some limitations to the pulldata() function. The name of the key field has the same limitation as the name column in the choices worksheet, meaning that these values can't have spaces or non-ASCII characters. Additionally, because these are .csv files, using a comma in any of these fields causes the pulldata() function to produce incorrect results.

If values in your .csv file exceed 255 characters, you must enter a higher value in the bind::esri:fieldLength column for both the question you're populating with the .csv content and any questions being used as input to the pulldata() function. If your .csv file includes values that are larger than the maximum length of one of these fields, a survey response fails to submit and displays a Code 1000 error.

Note:

The pulldata() function can't be used to populate the values of select_multiple questions.

When using the pulldata() function, your .csv column names cannot be blank and cannot contain spaces, hyphens, or other special characters.

It is recommended that you encode the .csv file using UTF-8 character encoding. If you're using Microsoft Excel to create your .csv file, save it as CSV UTF-8.

Retrieve a value from JSON

You can use the pulldata("@json") function to extract individual properties from a JSON object. This function is often used to complement other functions, such as pulldata("@javascript") and pulldata("@layer"). The function has the following syntax:

pulldata("@json", <question name>, "<JSON property>")

The parameters for pulldata("@json") are as follows:

  • question name—The name of the question that contains the JSON object, for example: ${json_response}.
  • JSON property—The property you want to retrieve from the JSON. Use periods to specify the location of the property in the JSON structure. For example, to retrieve the City property from the address object, use "address.City".

In the following example, the result of a reverse geocode operation is returned as JSON in a text question named json_response:

XLSForm with pulldata("@json") calculations

A response from the locator similar to the following is returned:

{
    "address": {
        "Match_addr": "Eiffel Tower",
        "LongLabel": "Eiffel Tower, Paris, Île-de-France, FRA",
        "ShortLabel": "Eiffel Tower",
        "Addr_type": "POI",
        "Type": "Historical Monument",
        "PlaceName": "Eiffel Tower",
        "AddNum": "",
        "Address": "",
        "Block": "",
        "Sector": "",
        "Neighborhood": "Paris 07",
        "District": "Paris",
        "City": "Paris",
        "MetroArea": "",
        "Subregion": "Paris",
        "Region": "Île-de-France",
        "RegionAbbr": "",
        "Territory": "",
        "Postal": "",
        "PostalExt": "",
        "CntryName": "France",
        "CountryCode": "FRA"
    },
    "location": {
        "x": 2.294520000000034,
        "y": 48.85832000000005,
        "spatialReference": {
            "wkid": 4326,
            "latestWkid": 4326
        }
    }
}

The pulldata("@json") function is used to retrieve the City property from the address object:

pulldata("@json", ${json_response}, "address.City")

The latitude and longitude are retrieved from the location object:

pulldata("@json", ${json_response}, "location.x")

pulldata("@json", ${json_response}, "location.y")

Note:
A period is used to access individual properties of a parent object. When a period also forms part of a property, it must be enclosed in square brackets [ ]. For example, to retrieve a property named City.Population from the address object, the expression would be pulldata("@json", ${json_response}, "address.[City.Population]").

You can access an object in an array of objects by specifying its position in the array enclosed in square brackets. The index for a JSON array starts at zero. The following is an example of a JSON object returned by smart attributes. It contains a classes array:

{
    "classNames": "person,bottle,keyboard",
    "classes": [
        {
            "name": "person",
            "score": 0.67421875,
            "xmin": 47,
            "ymin": 20,
            "xmax": 1086,
            "ymax": 262
        },
        {
            "name": "bottle",
            "score": 0.7625,
            "xmin": 237,
            "ymin": 469,
            "xmax": 552,
            "ymax": 639
        },
        {
            "name": "keyboard",
            "score": 0.55078125,
            "xmin": 28,
            "ymin": 49,
            "xmax": 1078,
            "ymax": 385
        }
    ]
}

For the example above, the following expression returns the score of 0.67421875 from the first object in the classes array:

pulldata("@json", ${results}, "classes[0].score")

You can use the length property to return the number of objects in an array. For the example above, the following expression returns a length of 3:

pulldata("@json", ${results}, "classes.length")

Query a feature layer

You can use the pulldata("@layer") function to query a feature layer, feature table, or query enabled map service. You can perform an attribute query or a spatial query. An attribute query uses a getRecord or getValue operation:

pulldata("@layer", "getRecord", "<URL>", "<WHERE clause>")
pulldata("@layer", "getValue", "<JSON property>", "<URL>", "<WHERE clause>")

A spatial query uses a getRecordAt or getValueAt operation:

pulldata("@layer", "getRecordAt", "<URL>", <location>, "<WHERE clause>")
pulldata("@layer", "getValueAt", "<JSON property>", "<URL>", <location>, "<WHERE clause>")
Note:

The location specified in a spatial query must be a geopoint question.

The getRecord and getRecordAt operations return a JSON feature object containing a single feature and all of its attributes. The getValue and getValueAt operations return a single value from the feature object, instead of the entire query response.

The parameters for pulldata("@layer") are as follows:

ParameterDescription
JSON property

Required for the getValue and getValueAt operations. The value you want to retrieve from the query response.

Examples:

"attributes.COUNTRY"
"geometry"
location

Required for the getRecordAt and getValueAt operations. The point location you want to query with the feature layer. This must be a geopoint question.

Example:

${location}
URL

Required. The URL of the feature layer or table you want to query. This parameter accepts additional request parameters.

Example:

"https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/World_Countries/FeatureServer/0"
WHERE clause

Optional. A WHERE expression that filters the feature layer or table. When the WHERE clause is not provided, a default of "1=1" is used.

Example:

"COUNTRY='Canada'"
Tip:

The pulldata("@layer") function returns the first record in the query response. Design and test your query to ensure you get the desired results. You can refine your query using a WHERE clause and the additional request parameters described below.

The pulldata("@layer") function caches query responses for efficiency. To defeat the cache and ensure a new request is made each time the function is run, add a time=now parameter to the URL—for example, concat(${layer_url}, "?t=", now()).

The following example queries a polygon feature layer of world time zones and returns the time zone that the geopoint is located in:

XLSForm with pulldata("@layer") calculation

The getRecordAt operation is used to retrieve the time zone that the geopoint intersects using the following syntax:

pulldata("@layer", "getRecordAt", "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/World_Time_Zones/FeatureServer/0", ${location})

The ZONE attribute is then extracted from the query response using the pulldata("@json") function. Alternatively, you can use a getValueAt operation in the pulldata("@layer") calculation to retrieve the ZONE attribute directly, without the need for a separate question to store the query response. See the following example:

pulldata("@layer", "getValueAt", "attributes.ZONE", "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/World_Time_Zones/FeatureServer/0", ${location})

You can use pulldata("@layer") in constraints. For example, you can apply a constraint to a geopoint question to prevent users from submitting locations outside an area of interest.

XLSForm with pulldata("@layer") constraint

The getRecordAt operation returns the JSON feature object for the country that the geopoint is in using the following syntax:

pulldata("@layer", "getRecordAt", "https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/World_Countries/FeatureServer/0", ${location}, "COUNTRY='Canada'")

The name of the country is extracted in a text question using pulldata("@json"). A constraint of ${country}='Canada' is then applied to the geopoint question to ensure the location falls within the region of Canada.

Request parameters

You can refine a pulldata("@layer") query with additional request parameters, such as distance, orderByFields, and resultOffset. For more information on request parameters, see Query (Feature Service/Layer). The pulldata("@layer") function only supports requests that return a feature object.

To include these parameters in a query, append them to the URL after a question mark. Additional parameters are separated by ampersands. In the following example, the orderByFields and resultOffset parameters are appended to the feature layer URL to return the name of the tenth most populous county in California:

pulldata("@layer", "getValue", "attributes.NAME", "https://services5.arcgis.com/jMCHJcLe13FaKCFB/arcgis/rest/services/US_Counties/FeatureServer/1?orderByFields=POPULATION DESC&resultOffset=9", "STATE_NAME = 'California'")

An aggregated query can be used to return statistics on a feature layer using the outStatistics parameter. Statistics that can be calculated with this parameter include count, sum, minimum, maximum, average, standard deviation, or variance.

In the following example, the count of counties in the selected state is returned:

pulldata("@layer", "getValue", "attributes.TotalCount", concat("https://services5.arcgis.com/jMCHJcLe13FaKCFB/arcgis/rest/services/US_Counties/FeatureServer/1", '?outStatistics=[{"statisticType": "count","onStatisticField": "objectId","outStatisticFieldName": "TotalCount"}]'), concat("STATE_NAME = '", ${state_name}, "'"))

In the following example, the sum of the POPULATION field for all counties in the selected state is returned:

pulldata("@layer", "getValue", "attributes.TotalPopulation", concat("https://services5.arcgis.com/jMCHJcLe13FaKCFB/arcgis/rest/services/US_Counties/FeatureServer/1", '?outStatistics=[{"statisticType": "sum","onStatisticField": "POPULATION","outStatisticFieldName": "TotalPopulation"}]'), concat("STATE_NAME = '", ${state_name}, "'"))

Note:

The pulldata("@layer") function supports all request parameters listed in Query (Feature Service/Layer) except the following:

  • f
  • outFields
  • outSR
  • resultRecordCount
  • returnCountOnly
  • returnGeometry
  • returnIDsOnly
  • token

Retrieve a location from a list

You can allow users to retrieve a location from a feature layer, based on their selection from a list of choices in a select_one question. The choice is submitted as text and its corresponding geometry is submitted as the location for the survey response. This approach is equivalent to a location list question in the Survey123 web designer.

To create a list of locations, add a select_one question with search and autocomplete appearances. The search appearance populates the list with values from a feature layer. The autocomplete appearance presents the values in a drop-down list, which is useful when a very long list is returned from the feature layer.

Configure the search() expression to retrieve a list of values from a feature layer. In the geopoint, geoshape, or geotrace question, add a pulldata("@layer") expression to retrieve the geometry for the feature selected from the list.

In the following example, respondents select a water meter from a select_one question named meter_id. The geometry of the water meter is retrieved from the Water Meters feature layer and saved to the geopoint question:

XLSForm with search() and pulldata("@layer") expressions

For more information about the search appearance, see Search.