Skip navigation
All Places > Survey123 for ArcGIS > Blog > Author: dlengtonesri-southafrica-esridist

After some valuable inputs I have reworked this example to cater for the GOTCHA where a user deletes an image in the middle of the sequence of photos - lets hope its fool proof now! It definitely isnt perfect but hopefully it gives someone else out there an idea of what can be done - and with a little extra effort make it completely fool proof...


Do you have the requirement that your field workers might want to take/attach multiple photos to a survey but you dont want to use a repeat to capture them, since you know its harder to access those photos later?  Just adding multiple image fields to your survey leaves your user interface cluttered like this:


Thats pretty ugly right?


One solution to unclutter the interface is to show the second photo field only once a user has already taken a photo. And after the user took the second photo, the third photo field becomes available... etc etc...


That can be achieved easily by setting the relevant field of each photo field with a calculation such as checking the value of the previous photo field:



The trick to get this to work when a user decides to delete a photo in the middle of a sequence of photos already added is to do the relevant calculation only once with the help of the once() function.


Doesn't this look much less cluttered:


After taking the first photo, the second one is opened up:

Do you want to create a break-out link from your survey to Twitter, WhatsApp, eMail etc?


Here are a few examples of how the HTML tags should look like to achieve this (just substitute your fields into the examples and paste it into a survey note field):


 Open the device's default mapping application (such as Google Maps) with the coordinates of the survey:

concat('<a href="geo:', ${Lat}, ',' , ${Long}, concat('">Display on the Map</a>'))


 Open Google Maps with driving directions to coordinates:

concat('<a href="', ${Lat}, ',' , ${Long}, concat('&amp;ll=">Directions</a>'))


 Open the device's default email application with a to email address:

concat('<a href="mailto:', ${Email},concat('">', ${Email}))


 Create a Tweet from your survey:

concat('<a href=" tweet sent from Survey123! #ArcGIS','">Create a Tweet</a>')


 Create a WhatsApp message from your survey:

concat('<a href="whatsapp://send?text=This is a WhatsApp message from Survey123!">Create a Whatsapp message</a>')


 Open Collector with a specific web map:

${Collector_Intent} = concat('arcgis-collector://?itemID=68085fc05c401ca5716e5677a6128c')
concat('<a href="',${Collector_Intent},'">Open Collector</a>')

(first create a calculated field named Collector_Intent and then use that field in the second calculated field)


 Open a specific survey (with parameters) from Survey123:

${S123_Intent} = concat('arcgis-survey123://?itemID=887d507cee48d18ad3cdfaf9f081e6&field:Service_Rating=1')
concat('<a href="',${S123_Intent},'">Open specific survey</a>')

(first create a calculated field named S123_Intent and then use that field in the second calculated field)


 Open an SMS (with the coordinates in the body) from Survey123 (this works in Android - not tested on iOS):

concat('<a href="sms:','08212345678','?body=', ${Lat}, ',' , ${Long}, concat('">SMS</a>'))

(to get the coordinates - just use the pulldata() function)


 Open a local file (such as a PDF help file or an image located in your survey's media folder) from Survey123 - this works and has been tested on Android:

concat('<a href="file:///storage/emulated/0/ArcGIS/My Surveys/549c05bae0f14e388000486ce4de950c/esriinfo/media/Example.pdf" class="link external button button-raised button-fill color-blue">Demo</a>')

(549c05bae0f14e388000486ce4de950c will be different for each survey. It refers to the survey item id)



I will add more examples as the need arises 



This blog post provides a solution for:

    Capturing multiple locations per survey

    Calculating straight-line distances between a base location point in the survey and other repeating locations         captured


Consider the scenario where your survey must assist in the administration of new liquor licence applications and the law stipulates: New liquor premises must be located at least five hundred meters (500m) away from schools, places of worship, recreation facilities, rehabilitation or retreat centers, residential areas and public institutions.


For this requirement Survey123 can be a valuable tool and in this blog post I will show you how you can enable this functionality in a Survey123 form:


Step 1: Create a new survey with Survey123 Connect

Step 2: Create a geopoint field in the main survey which will be used to capture the location of the new licence premises (the base point or new_licence_location field in the survey below)

Step 3: Create a repeat section to capture the occurrences of nearby schools, places of worship etc. Each with a premise type and a geopoint (the nearby_location field in the survey below)


Your survey design should look similar to this:



Step 4: Now, split both the coordinates sets into their x,y pairs and convert them to radians:



Do the same for the nearby_location geopoint field:


Step 5: Use the X, Y (lat,long) pairs to perform the distance calculation (in meters) with the Haversine formula:

acos(sin(${gps_lat_end})*sin(${gps_lat}) + 
cos(${gps_lat_end})*cos(${gps_lat})*cos(${gps_long}-${gps_long_end}) ) * 6371000


After making some cosmetic enhancements (and adding the 500m stipulation) your survey should look like this:



The user can add multiple locations (Nearby Premises) at will in the repeat section and each will have it's own distance calculation to the base point (New Licence Location).

The Survey123 Excel Design file is attached to this blog. 

Feel free to use and adapt as you require!


A customized but "Out-of-the-Box" Progress /  Increment bar for Survey123


For a recent survey that I designed I wanted to give the user visible feedback of a risk factor calculation. Have a look at the video below to see how striking the end result is:



Let's break the Progress / Increment Bar down into it's capabilities:

    A color ramp to visualize the score (similar to the score distress bar)

    A progress / increment indicator (■■■■■■■□□□)

    Expand and contract the bar according to the score


How was the end result achieved? Let's look at the three components needed to make this work:

1. Color Ramp

The color ramp changes from green to red according to the score entered, which runs from 0 to 10 in this case. We could sit down and pretend to be graphic artists and create a color ramp from scratch, or we can use one of the handy websites which creates beautiful color ramps for us!


Let's head to RGB Gradient Generator or any RGB gradient generator of your choosing.


Now choose your start color and your end color for your ramp (in my case green to red) and choose the number of steps required (in this case 11, which corresponds with our allowable score values):


Next you need to choose a generated gradient and copy the gradient indexes and corresponding hex values to Notepad++ in order to create a CSV file which will act as a color value lookup which is based on the score calculated:




Now we have a handy way to color the bar according to the score calculated. To retrieve the color for each score, we simply have to use the pulldata() function of Survey123:

${color} = pulldata('ColorLookup', 'hexvalue', 'colorvalue', string(int(${score})))

In order to use this hex color we need to use some html magic:

<font color="#',${color},'">

2. Progress Indicator

The progress indicator is actually a string of HTML Unicode characters (UTF-8).

Let's go shop for a pair of Unicode characters to use for the progress bar at UTF-8 Geometric Shapes

You can play around with the various character options but in essence you need a pair of Unicode characters; one to show up as "filled" and colored in, and one that seems to be "empty":



I found it useful to add the character pair strings to a CSV file since it abstracts the solution:



In the CSV file I simply Copied & Pasted each character 10 times to make two strings that are each 10 characters long.


Item 1 in the CSV then represents the filled in section of the progress bar (e.g. 10/10 ■■■■■■) and Item 2 represents the "empty" part of the progress bar (e.g 0/10 □□□□□□□□□□).


We now have two strings of 10 characters each and we can access them in our survey with the pulldata() function:

${barString} = pulldata('CharStringLookup', 'textvalue', 'item', '1')
${emptyString} = pulldata('CharStringLookup', 'textvalue', 'item', '2')

3. Expanding and Contracting the Bar

Now we can color our progress bar and we can visually differentiate between the "filled" in part and the "empty" part of the progress bar by using our Unicode character pair. All that is left is to cut our strings to size (according to the score e.g. 1/10) and combine and color it according to the color ramp already calculated.


Our score in the survey can run from 0 to 10 so the progress bar should mimic that by filling up from 0 to 10. We can achieve this by using the SubStr(<string>,<start>,<end>) function on each of our character strings. When the filled in part expands, the empty part should contract, so there is an inverse relation between their lengths.


Using two substring functions we can easily cut our two strings to size:


Now all we need to do is to set the color of the filled in section to our ramp color and then concatenate the strings together with the concat() function:

concat('<font color="#',${color},'">',
   '<font color="black">', 
   string(${score}), ' / ' ,${scoremax})

The second font color setting colors the empty part of the progress bar in black for a nice contrast in colors.


The source files can be found here:  AGOL Resource


Thank you for reading this Blog!

As always, feel free to use and adapt as needed!