ArcGIS Blog

Field Operations

ArcGIS Field Maps

Common calculated expressions for ArcGIS Field Maps

By Doug Morgenthaler and Jeff Shaner

Calculated expressions in ArcGIS Field Maps streamline all kinds of data collection workflows from storing location as an attribute, to pulling attributes from related records or other layers in the map. In this blog post, we’ll walk through some of the most common use cases and provide sample code to get you up and running with calculated expressions in your own forms.

If you’re not familiar with Arcade, you can read the documentation or try using it in the playground. For step-by-step instructions on how to add expressions to the form in Field Maps Designer, see Add calculated expressions. Let’s jump right in and see what’s possible!

1. Fetch an attribute from an underlying polygon

Sometimes, it can be valuable to store the geographic area a feature was collected in. In the past, this could be done manually by selecting the region from a list of values or by post processing the data. Now, this can be streamlined and automatically captured in the field by using a form calculation that performs a spatial intersection of the current location and a layer of polygons representing the geographic areas.

Example: I am recording bird sightings and want to automatically store the region I’m in.



// Create a feature set using the 'Regions' layer in the map
var regions = FeatureSetByName($map, 'Regions', ['name'])

// Intersect the current location with the regions and 
// get the first region
var region = First(Intersects($feature, regions))

// If the current location does intersect a feature, 
// return the name of the region. Otherwise, return null
if (!IsEmpty(region)) {
    return region['name']
} else {
    return null
}

 

Bird Sightings Example

2. Fetch an attribute from a related record

When performing inspections, it’s often necessary to store information about the parent feature such as the address, or type of asset. These attributes can be pulled from the parent layer by querying the related records and accessing the necessary attributes.

Example: I’m inspecting hydrants and need to record the Facility ID with each inspection.


// Get the feature set for the hydrants
var hydrants = FeatureSetByRelationshipName($feature, 'wHydrant', ['facilityid'], true)

// Get the first hydrant (should only be one)
var hydrant = First(hydrants)

// If there was a hydrant, return the facilityid of it,
// Otherwise, return null
if (!IsEmpty(hydrant)) {
    return hydrant['facilityid']
} else {
    return null
}

 

Hydrant Inspections ID

3. Store a user’s name, email address, or username

When performing inspections or collecting new data, editor tracking works great for storing the username of the person who created or edited the feature, but it doesn’t store the user’s full name or email address. Having these extra attributes can make it much easier to understand the data when displayed in reports, maps, and dashboards. This can be accomplished by getting the signed in user’s info via Arcade.

Example: I’m filling out a damage inspection report and need to provide my name.


GetUser($layer).fullName

Note: At version 22.3 of Field Maps, this does not work if the device is offline.

 

Inspectors Name

4. Calculate the current date and time

When performing inspections, it’s often useful to set the inspection date to the current date and time. While the mobile worker can do this in the mobile app with a few taps, it can be more efficient to auto-populate this information using an Arcade expression.

Example: I’m filling out a damage inspection report and need to set the inspection date.


Now()

 

Damage Assessment

5. Store the geometry as an attribute

When integrating with other systems, it can be useful to store aspects of the geometry as separate attributes. This can be done by accessing the feature’s geometry via Arcade.

Example: When working with high accuracy GNSS receivers, the orthometric height is stored in the z-value of the geometry and I need to also store and display the orthometric height as an attribute value for point features collected in the field.

// Get the Z value
var geom = Geometry($feature)
if (IsEmpty(geom)) {
    return null
} else {
    return geom.Z
}

Sometimes, the raw x and y location are not what you need. You might need the latitude and longitude. If your map and data are using Web Mercator Projection you can write code to calculate the latitude and longitude from the x, y meter values.

Example: I need to store the latitude and longitude values to conform to some standard data collection specification.


// Create a function to convert meters to lat, long
// Source: http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/
function MetersToLatLon(geometry) {
    if (IsEmpty(geometry)) {
        return [null, null]
    }
    var originShift = 2.0 * PI * 6378137.0 / 2.0    
    var lon = (geometry.x / originShift) * 180.0
    var lat = (geometry.y / originShift) * 180.0 
    lat = 180.0 / PI * (2.0 * Atan( Exp( lat * PI / 180.0)) - PI / 2.0)    
    return [Round(lat, 6), Round(lon, 6)]
}

// Call the function and return the latitude or longitude value
MetersToLatLon(Geometry($feature))[0]

 

Store Geometry Attributes

When collecting or updating the geometry of a feature, you may want to automatically calculate the length of a line or the area of a polygon as a field value.  Use the AreaGeodetic() function or LengthGeodetic() function. to calculate length or area using the feature geometry instead of using the Shape_Area and Shape_Length fields. Those fields are updated after edits are submitted and your calculations may not reflect changes to the geometry.

Example: I need to store the acreage of a forest stand as an attribute and would like to round the value to 3 decimal places.

// Calculate the area using the geometry
var geom = Geometry($feature)
if (IsEmpty(geom)) {
    return null
} else {
    return Round(AreaGeodetic($feature, 'acres'), 3)
}

6. Calculate a value from other fields

Often, it can be useful to calculate a value based on one or more fields that the mobile user fills out.

Example: I need to calculate the score when doing a damage assessment report. Certain things (e.g., the roof, foundation, habitability.) are scored based on their damage level. I need to sum all these independent scores into a single value to use for filtering and visualization.


$feature["foundation_condition"] + $feature["roof_condition"] + $feature["habitability"]

 

Damage Assessment Score

7. Store info about a nearby feature

When installing new assets or planting trees, it’s often useful to store the nearest address.

Example: I’m planting new trees in a neighborhood and want to store the nearest address using existing parcel data.


// If feature doesn't have geometry return null
if (IsEmpty(Geometry($feature))) { return null }

// Get the parcels layer
var parcels = FeatureSetByName($map, 'Parcels')

// Buffer the current location and intersect with parcels
var bufferedLocation = Buffer($feature, 100, 'feet')
var candidateParcels = Intersects(parcels, bufferedLocation)

// Calculate the distance between the parcel and the current location
// Store the feature and distance as a dictionary and push it into an array
var featuresWithDistances = []
for (var f in candidateParcels) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'feet'),
            'feature': f
        }
    )
}

// Sort the candidate parcels by distance using a custom function
function sortByDistance(a, b) {
    return a['distance'] - b['distance']
}
var sorted = Sort(featuresWithDistances, sortByDistance)

// Get the closest feature
var closestFeatureWithDistance = First(sorted)

// If there was no feature, return null
if (IsEmpty(closestFeatureWithDistance)) { return null }

// Return the address
return `${closestFeatureWithDistance['feature']['ADDNUM']} ${closestFeatureWithDistance['feature']['ADDRESSNAM']}`
Nearest address

Summary

We’ve shown quite a few different examples here, there’s so much more that you can do with Arcade and form calculations though! If you have any questions or would like to share how you use form calculations please post in the ArcGIS Field Maps Community forum or email us at arcgisfieldmaps@esri.com.

Share this article

Subscribe
Notify of
17 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Frank Martin(@fratin)
May 19, 2022 12:04 pm

Are these calculated expressions available in Enterprise 10.9.1? If not, is there a timeline for updating Enterprise to include this functionality?

Thanks,
Frank

Jeff Legato(@jlegato_prcity)
March 10, 2023 7:48 am
Reply to  Aaron Pulver

These expressions will make our experience so much better. Can you confirm they are available for Enterprise 11?

Christopher Bride(@cpbride2020)
June 9, 2022 10:40 am

I am toying with the first technique and even though it tests fine, the field it is supposed to populate does not populate. I got the X/Y thing to work so this is a mystery to me. One thing that is a little funny is that the $map in Globals is referring to the layer, not the name of the map, and that cannot be edited. I got the X/Y to work, but those are functions. What do you recon I’m doing wrong? var regions = FeatureSetByName($map, ‘Somaliland_And_Puntland’, [‘Region’]) // Intersect the current location with the regions and // get… Read more »

Christopher Bride(@cpbride2020)
June 10, 2022 12:45 pm

if a field already has a domain attached to it, will that affect the ability to auto-populate the fields in a created feature? The reason I ask is that my test runs (in the editor), but it does not work in practice.

Borderlands Restoration(@borderlandsrestorationnetwork)
August 10, 2022 8:47 am

Thank you! This is so helpful. I have a question though. I’m trying auto-populate one field with lat and one with long. I used the code for this under item 5, and this gives the latitude perfectly. However, I’m having trouble figuring out how to edit the code so that it displays longitude. Does anyone know how to do this? Any help would be greatly appreciated 🙂

Danielle Lacouture(@d-lacouture_ufl)
August 24, 2022 11:12 am

Hello, did you find the answer? I am having the same issues. Thanks

Danielle Lacouture(@d-lacouture_ufl)
August 29, 2022 10:19 am

Ok I just changed it so that the return line only includes longitude:

return[Round(lon,6)]

Andrew Hargreaves(@ahargreaves_fw)
October 19, 2022 7:43 am

Hey Aaron/Josh,
How can I recreate #7 but using a reverse geocoder to auto populate the nearest address?

Andrew Bowne(@abowne)
January 18, 2023 10:29 am

Is there an expression that can be used to fetch intersecting attributes using Floor-Aware data? For instance – capturing point features and automatically capturing the intersecting facility, level, unit?

Amy Ortner(@aortner_usfs)
February 15, 2023 7:40 am

When will calculating user information work while collecting data offline?

Chris Hamilton(@chris-h)
March 5, 2023 7:36 pm

I’m interested to know whether example #7 would work if the “nearest feature” was a tracklog being captured by Quick Capture (same user / same device) that was still actively capturing data?

Our requirement would be to obtain a project identifier from the track log and apply it to inspection records collected in Field Maps (closest track log by the same user on the same day).

Hunter Ray(@hmray_cloudpointgeo)
March 7, 2023 7:18 am

Suggested Edit for Example #2: The last parameter of the FeatureSet for ‘includeGeometry’ should be set to false instead of true for the example of only needing to get the parent feature’s FaciliytID value.

The expression execution time will increase when the geometry is not returned in the FeatureSet.

Last edited 2 years ago by Hunter Ray
Cara Moore(@cara_moore)
July 18, 2023 12:23 pm

Do any of these methods consume credits?

Rob Ward(@data-officer)
July 27, 2023 9:53 am

Hi, I have just been testing GetUser($layer).fullName to populate a name field, but it returns an error in the app “Failed to calculate”. When testing in FieldMaps designer it works fine, but fails in the app. Any way to get this to work?

Doug Browning(@dougbrowning)
March 19, 2025 10:30 am

Note many of these samples need a fix. See *** below. // Create a feature set using the ‘Regions’ layer in the map var regions = FeatureSetByName($map, ‘Regions’, [‘name’]) // Intersect the current location with the regions and  // get the first region // *** right here this will fail if Intersects does not find anything. It is better to get the Intersects results then check that for IsEmpty or Count(). This is getting posted on the Esri Community boards all the time and now I know where they are getting this code. I suggest updating this code and others… Read more »