Select to view content in your preferred language

Survey123 Tricks of the Trade: Print web maps in reports

408
4
a month ago
ZhifangWang
Esri Regular Contributor
5 4 408

Survey123 report capabilities allow you to generate high-quality reports in PDF or Word document formats based on survey data, including attributes, geographic features, and attachments. A report uses a Word document with placeholders as a template. The Survey123 report API replaces these placeholders with actual data when the report is printed.

If you're not familiar with Survey123 reports, you can learn the basics from the following resources:

 

In Survey123 reports you can include text, tables, images, and - of course - maps! In this blog, we will discuss several methods available for printing maps in reports.

 

Print a single feature on a map

If your survey includes a map question (geopoint, geotrace, or geoshape), you can easily print the specific feature on a map. For example, select a record on the Data page of the Survey123 website:

  • ${geopoint1 | size:400:300} - prints the feature in a 400 * 300 pixel map image, using the web map configured for the geopoint1 question.
  • ${geopoint1 | map:"dc0722c1c56c47268da4c1e046516b21" | size:400:300} - prints the feature on top of a specific web map.

 

Print multiple features on a map (where method)

In a summary section of report, you may want to display multiple features on a single map. To achieve this, make sure to include multiple records as the input for the report. For example, select all the records you want to print in the summary report on the Data page of the Survey123 website:

  • ${geopoint1 | where:"1=1" | size:400:300} - prints all features from the input on a single map, using the web map configured for the geopoint1 question.
  • ${geopoint1 | where:"STATE_NAME='California'" | map:"dc0722c1c56c47268da4c1e046516b21" | size:400:300} - only prints features of input records where the attribute STATE_NAME equals "California", on top of a specific web map.

 

Print features using the $shape keyword

In some cases, a survey may be created from an existing feature layer without including a map question. For instance, in an asset inspection survey, there might not be a map question to prevent altering the asset's location. In such cases, the $shape keyword, which represents the geometry of the feature, can be used to print features in a report.

  • ${$shape | size:400:300} - prints the feature of the input record.
  • ${$shape | where:"1=1" | map:"dc0722c1c56c47268da4c1e046516b21" | size:400:300} - prints all input features on top of a specific web map in a single map image.

 

There are several additional methods to control the look and feel when printing a map:

  • ${geopoint1 | mapScale:100000} - mapScale:<scale> controls the scale of the map, which will always center on the feature or features in the input.
  • ${geopoint1 | mapExtent:116.440:39.955:116.468:39.971} - mapExtent:<xmin>:<ymin>:<xmax>:<ymax>:<wkid> sets a fixed extent when printing a map. If WKID is omitted, 4326 will be used. This is an alternative to using mapScale, allowing you to control the map center regardless of where the input feature is.
  • ${geopoint1 | drawingInfo:"currentLayer"} - drawingInfo can override the default symbology (e.g., the blue pin for a geopoint) used by the report engine with the drawing information defined in the feature layer JSON. "currentLayer" refers to the layer where geopoint1 resides. You can also reference any feature layer by replacing "currentLayer" with a feature layer URL (e.g., https://.../FeatureServer/0). Note: this only works for input features to the report and does not affect any features or symbology defined in a web map.

 

One important note for all the above methods is that the specified web map is printed as a reference background under the input features. If a web map includes layers that contain the survey data, features printed by a survey question could conflict with features on the web map. To resolve this, you can use the $map keyword and the mapFilters method introduced in the September 2024 update for ArcGIS Survey123.

 

Print a web map without referencing a map question in the survey ($map keyword)

Previously, displaying a web map in a report required either referencing a map question in the survey or using the $shape keyword. The $map keyword enables you to print a predefined web map directly in your report without needing to reference a map question. For example:

  • ${$map | map:"dc0722c1c56c47268da4c1e046516b21" | size:400:300} - prints the specified web map as is.

 

Filter features in operational layers of a web map (mapFilters method)

A layer in a web map may contain more data than necessary for your report. To filter the features of a feature layer within the operational layers of a web map, you can use the mapFilters:"<parametersForQueryOperation>" method. The parameters can include common /query operation parameters such as where, objectIds, orderByFields, and resultRecordCount. Use = to assign a value to a parameter, and the & symbol to combine multiple parameters.

For example, if a web map contains a single operational layer with all cities in the USA:

  • ${$map | map:"7f2ef03be73a4b51b9e0480df46de7b1" | mapFilters:"where=STATE_NAME='California'"} - prints only the cities where the STATE_NAME attribute equals "California". Note that the text in the where clause must be enclosed in single quotation marks ' '.
    • 1. cities in California.png
  • ${$map | map:"7f2ef03be73a4b51b9e0480df46de7b1" | mapFilters:"where=1=1&orderByFields=POP2000 DESC&resultRecordCount=10"} - prints the first 10 cities with the highest population in the USA on the map.
    • 2. 10 cities with most population.png

       

 

If a web map contains multiple operational layers and you want to filter each one, you need to specify the layer id in web map JSON for each feature layer and concatenate all layers using a colon `:`. The format is {... | map:"<itemId>" | mapFilters:"'<layerId1inWebMapJSON>':<parametersForQueryOperation>":"'<layerId2inWebMapJSON>':<parametersForQueryOperation>":...}.

For example, imagine a web map that contains two layers: a layer of states and a layer of cities in the USA, where the cities layer is related to the states layer via the parentGlobalID field. In the web map JSON:

3. layer id in web map JSON.png

 

1918fe218e1-layer-5 is the layer ID for states, and 1918f9f547a-layer-4 is the layer ID for cities. e4a6f9ce-bc61-428c-8c26-202ff62e509e is the global ID of California in the states layer.

  • ${$map | map:"7f2ef03be73a4b51b9e0480df46de7b1" | mapFilters:"'1918fe218e1-layer-5':where=GlobalID='e4a6f9ce-bc61-428c-8c26-202ff62e509e'":"'1918f9f547a-layer-4':where=parentGlobalID='e4a6f9ce-bc61-428c-8c26-202ff62e509e'"} -  prints the state of California and all cities related to it on the map.
    • 4. state and cities of California.png

       

  • You can replace the static global ID value with its field name in the states layer. In this case, when you select any state as the input for the report, its global ID value will be dynamically replaced in the placeholder, allowing the map to display the selected state and its cities: ${$map | map:"7f2ef03be73a4b51b9e0480df46de7b1" | mapFilters:"'1918fe218e1-layer-5':where=GlobalID='"+GlobalID+"'":"'1918f9f547a-layer-4':where=parentGlobalID='"+GlobalID+"'"}

 

Other considerations and tips for filtering features in a web map

  • To keep the syntax in the report template simple, it's recommended to filter only one layer in the web map.
  • If you need to filter multiple layers, you must inspect the /data of a web map to identify the ID for each layer to be filtered. Each layer ID should be enclosed in single quotation marks ' '.
  • If you encounter a syntax error when uploading a report template or printing a report, check the related syntax to ensure that there are no missing double quotation marks, single quotation marks, or colons.

 

Other resources

4 Comments
abureaux
MVP Frequent Contributor

Nice guide, thank you.

I'll have to keep these in mind.

Blevins_Mark
Frequent Contributor

I am calculating a mapextent value in my surveys table based on input from another question. I then call that mapextent value when I am building the map in the feature report. When I do this, the map extent does not change and the extent is not correct. If I just add the map extent value to the report it is correct. Is it not possible to populate the map extent with a value from the surveys feature attribute in this manner?

ZhifangWang
Esri Regular Contributor

Hi @Blevins_Mark ,

Can you please share more details about what the expected map extent is or how the expected map extent relates to "another question"?

When printing either a single feature or multiple features on a map in the report, the report engine will automatically center to the feature(s) unless you specify the mapExtent parameter. For example: ${geopoint1 | mapExtent:116.440:39.955:116.468:39.971}.

Blevins_Mark
Frequent Contributor

Hi @ZhifangWang 

Thanks for your reply. This will be a bit long winded but...

Essentially I want the map in my report to center on and show the entirety of the permit area staff are collecting data in. So based on their answer to the question of what permit they are in, I am calculating a mapextent question in my survey. This step works as expected, ie the calculation happens and gets passed to the feature layer.

capt1.JPG

capt5.JPG

In my report, I am calling the mapextent value to generate the map as so:

${location | map:”205ad2f36b95451db9b6743d0378a5cd” | size:640:0 | mapExtent:mapextent1}

However, when the map gets generated it ignores the map extent piece, and looks as so:

capt2.JPG

However, if in my report, i just call the map extent values explicitly, the map generates as expected.

${location | map:”205ad2f36b95451db9b6743d0378a5cd” | size:640:0 | mapExtent: -90:35:-81:37}

Capt3.JPG

So that is how we are currently doing it, just adding an if statement in the report to go through the different permits and their explicit extent values and build the map based on which permit area is selected.

 

But my question is why the report is ignoring the mapextent1 field from my table when i try to call it from the table...am i not calling the field correctly?

Thanks