Print Dynamic Text from a Web Application

11836
27
12-15-2020 04:55 PM

Print Dynamic Text from a Web Application

This document will walk you through how to create a custom print service developed by @TanuHoque  that will print dynamic text from feature layers.

Publishing the Print Service

1.  Create a layout in ArcGIS Pro

2.  Add your Map Frame and any other elements.  Note:  If there is only one map frame on the layout, it will be used to reference the web map by default. If there is more than one map frame on the layout, name the map frame to be used as WEBMAP_MAP_FRAME.

3.  Add dynamic text by going to Insert > Dynamic Text.  Scroll down to Table Attribute > Value

Capture2.PNG

4.  Select the Map Frame, the layer for Table, set Query to Visible Rows, and specify the Field that will display the dynamic text.  Optionally, specify a Delimiter

3.PNG

5.  Draw a rectangle in the layout where you would like the dynamic text to be placed

4.PNG

6.  In the Element pane, click the Text View button

5.png

7.  Change the field to all lower case

6.png

7.png

8.  Once all the dynamic text has been added, remove the layer(s) used to create the dynamic text from the Map Frame

Remove.png

9.  After the layer(s) have been removed, go to Share tab > Layout File and export the .pagx to a folder

10.  In the attached Dynamic Printing.tbx, open the Export Web Map tool.  Specify the Format, choose the folder you exported the .pagx file to in step 9 for Layout Templates Folder, choose a Layout Template, and then Run the tool

9.png

 

11.  In the DynamicPrintService.tbx, open the Get Layout Templates Info tool.   Choose the folder you exported the .pagx file to in step 9 for Layout Templates Folder and then Run the tool

10.png

12.  Click on the Analysis tab > History to open the History pane

11.png

13.  Before proceeding make sure ArcGIS Pro is connected to your ArcGIS Enterprise organization.  Right-click on the Export Web Map tool > Share As > Share Web Tool

12.png

14.  Specify a Name for the print service.  Under Data, choose the option Reference registered data.  Optionally, specify a Portal Folder and share the service (i.e. to your Organization)

13.png

15.  Click Configuration tab.  For Execution Mode specify Synchronous and set the Message Level to Info

14.png

16.  Click the Content tab.  Click the Add Tool and select the Get Layout Templates Info tool

 15.png

17.  Analyze and Publish the service

 

Using the Print Service

The next section will walk you through how to configure the custom print service using ArcGIS Enterprise Web AppBuilder

1.  Create a web map using a feature layer.  If you are working with a Map Service, i.e. https://ags.esri.com/server/rest/services/ConnectionInfo/MapServer, be sure to add the layer to your web map as a feature layer.  To do this, in the web map choose Add > Layer From Web > paste in the URL with the index value.  Ex:  https://ags.esri.com/server/rest/services/ConnectionInfo/MapServer/0

2.  Save the Web Map

3.  Create a Web Application using Web AppBuilder and choose the web map you just created that contains the feature layer

4.  Add the Print widget to your Web Application

5.  For the Service URL, specify the path to your print service including the GPServer/Export%20Web%Map.  Ex:  https://jake2.esri.com/arcgis/rest/services/Dynamic_Print_Service/GPServer/Export%20Web%20Map

Optionally, specify a Default title, Default author, Default copyright, Default format, and Default Layout

16.png

6.  The custom print service will print dynamic text for all visible features.  If you want to limit the extent to a particular feature, you can add the Filter widget and filter based on a unique attribute. 

7.  Open the Print widget, choose the Layout and Format, and then click Print

Print.PNG

Here is an example of an output PDF created with the dynamic text on the left:

17.png

Attachments
Comments

Dear @JakeSkinner ,

Thank you very much for this tutorial.

I just have one question.

How can I add a custom text element and let the user insert its value in the print widget in the web app.

The tutorial Share custom layouts for printing from ArcGIS Pro—ArcGIS Server | Documentation for ArcGIS Enterpris... says that "if you want to insert a custom text element, add a text element and embed the element's name in a set of open and closed curly braces, such as {parcel-id}."

Where should I embed the element name?

Thank you very much.

You you do something like this based off a selection instead of visible content.  For example if I see a water main and water line services.  I would want to only show the data for one of hose water line services.  The way that some service lines start out they are in the same vicinity and then veer off from each other.  So doing only extent will always grab both.

I don't know if the filter will work, because they will randomly go from house to house and not exactly know what filters to use.

@LindseyStonecurrently this will only work with the visible content.  You could filter by the OBJECTID of the water line service.  For example, click on the feature you wish to show the information for and copy the OBJECTID from the pop-up, then use this OBJECTID in a filter. 

Dear @JakeSkinner ,

Thank you very much for this tutorial.

I just have one question.

How can I add a custom text element and let the user insert its value in the print widget in the web app.

The tutorial Share custom layouts for printing from ArcGIS Pro—ArcGIS Server | Documentation for ArcGIS Enterpris... says that "if you want to insert a custom text element, add a text element and embed the element's name in a set of open and closed curly braces, such as {parcel-id}."

Where should I embed the element name?

Thank you very much.

@MHasan 

Sorry I didn't see this message from Jan, 2021. In case you still need the answer or someone in the future looking for an answer for this....

 

To allow your end user insert an value for a dynamic text, here is what you need to do:

  1. Add a custom text element in your layouts. As you saw that in the tutorial you mentioned above.
  2. On the web app side, you need use Web Application Builder Print Widget.
    • on the print widget, click Advanced button and you will see the custom text element you defined in your layout.
    • all you end users need at this point is to enter a value in the text box and click Print.
      TanuHoque_1-1626202572415.png

 

Please note that when you publish your print service, you MUST have Get Layout Templates Info task in your print service.

Also, I had written a blog a while back talking about this. Only thing is that it was written in context of ArcMap being your authoring app, but at the high level the concept is still applicable when you publish from ArcGIS Pro.

https://www.esri.com/arcgis-blog/products/arcgis-enterprise/mapping/printing-popups-from-web-applica...

 

Where should I embed the element name?

I'm not sure I understand this part though. Please let me know what you meant.

 

Thanks

Tanu

Thanks for sharing this. The Export Web Map script provided uses the first feature layer found in the web map. Is there a way to specify which layer is being used? My map has multiple feature layers that I cannot reorder, so it's printing attributes from a different layer than the one I want. Thank you!

@BB_GIS try the following:

1.  Open the ExportWebMap.py in an IDE or text editor

2.  Replace the updateDynElmSrc function (line 90) with the following:

def updateDynElmSrc(result):
    arcpy.AddMessage("updateDynElmSrc...")
    p = result.ArcGISProject
    m = p.listMaps()[0] #assuming for now that there is only one map in the current project
    l = p.listLayouts()[0] #there is always only one layout in this case

    #getting the source layer's cim path for the first feature layer in the map
    lyr = None
    for lyr in m.listLayers():
        if lyr.name == 'Parcels':
            layerName = lyr.name
            lyr_uri = lyr.getDefinition('V2').uRI
            arcpy.AddMessage("cim_path for " + layerName + " is " + lyr_uri)
            for txtElm in l.listElements('TEXT_ELEMENT'):
              arcpy.AddMessage("Original: textElement.text = '" + txtElm.text + "'")
              txtElm.text = txtElm.text.replace('mapMemberUri=""', 'mapMemberUri="'+ lyr_uri +'"')
              arcpy.AddMessage("Modified: textElement.text = '" + txtElm.text + "'")

 

3.  In line 10 above, replace 'Parcels' with the name of the feature layer.  

4.  Republish the print service

 

@JakeSkinner - thanks for the reply! I gave this a try, but it didn't print the dynamic text. They layer I wanted to print from is an in memory feature layer that is produced by running a geoprocessing service through the GP widget in web appbuilder. Could that be the reason it doesn't work? Thanks!

@BB_GISyes, that is most likely the reason.  I will have to run some tests to see how this will work with an In Memory feature layer.

@TanuHoque 

In your reply back on how to print user input, I have tried doing as you mentioned. However, I am unable to find the option to add in the input under the advanced print option in the web application. Potentially, I am adding in the wrong custom text element or entering in the text the wrong way in the layout before publishing. Could you update your article on the process in ArcMap to ArcGIS Pro or at least walk me through the first step of adding in the text element in ArcGIS Pro to get it to show up for user input in the web application?

Thanks!

@JakeSkinner 

For the dynamic text to work, does the data/folder have to be registered to the server or can I just copy the data when publishing the tool?

@AspenN the data should not have to be registered.

Anonymous User

@TanuHoque 

From @AspenN 's follow up question on Sept 23... I also am having this same issue with not being able to get the customTextElement to show up in the print widget.  Is there some specific code that we need to put in the TEXT parameter of the custom text element in the layout in Pro?

When I run the Get Layout Templates Info job on the print service, it does recognize that my "Notes" customTextElement is there, but it never shows up in the Print Widget still..

deamer89_0-1641494921372.png

 

deamer89_1-1641494974089.png

 

 

 

Thanks!

@TanuHoque 

Where can I define <please enter parcel id> field from the picture above? I'm creating a template in ArcGIS Pro, and everything else works fine. I can't find where to define text that will be shown in this custom field as a predefined value.

@TanuHoque and @JakeSkinner

Is it possible to insert the title of the used WebMap as dynamic text?

I expected the following to work:
<dyn type="mapframe" name="WEBMAP_MAP_FRAME" property="metadata" attribute="title" preStr="Title " newLine="true" emptyStr=""/>

But no success, the used placeholder stays empty when I print within my WebApp.

Cheers

@best 

sorry for the delay.

this is how the dyn text element should be defined

<dyn type="layout" property="metadata" attribute="title" emptyStr=""/>

ref: https://enterprise.arcgis.com/en/server/latest/publish-services/windows/tutorial-publish-additional-...

please let me know if you have any question.

 

 

@JakeSkinner and @TanuHoque 

This is fantastic and useful functionality - I was able to get the dynamic print service to work!

I noticed one weird behavior that I am hoping someone may be able to help with ---- Oddly, when the layer that I am using for the dynamic text has labels turned on, the dynamic text does not function.

Has anyone else noticed this and/or found a solution?

Thank you!!

@KristinaMarkocevic 

The documentation for adding a custom text element in ArcGIS Pro layouts can be sourced here:

The curly braces need to be around the text element's name in the Contents pane under the Drawing Order of ArcGIS Pro.

ref: https://community.esri.com/t5/arcgis-web-appbuilder-questions/add-custom-text-element-to-print-layou...

@TanuHoque and @JakeSkinner 

This is exactly what I'm looking for to provide a report function to the client. Unfortunately I can't get it to extract the attribute values in the webapp. The layout is there but no data. My data resides in an SDE database on our server and is a feature service within the portal. Not sure how to configure the dynamic text so it looks for the layers that are service features. 

@TeresaSmithson One thing I noticed is that in order to get the dynamic txt to work, I have to have labels turned OFF on the layer that I am using for the dynamic txt. 

So, for example, my layout uses dynamic txt from a parcel layer. The dynamic txt in the report comes from attributes in the parcel data (assessment data). I published the parcel layer as a service from ArcPro. I then added that that parcel service in a webmap. I discovered after adding the parcel service to a webmap that at this point, I cannot have labels turned on. So, I ended up creating pre-made fixed labels via the mapservice; and nixed having any labels via the webmap.

I don't know if this may be your same problem, but this is what finally got my dynamic txt to work!

 

Thanks @LisaCasey 

My data resides in an SDE database on our server and is a feature service within the portal. Not sure how to configure the dynamic text so it looks for the layers that are service features.

@TeresaSmithsonI'd like to add a quick note in addition to what Lisa suggeted. Please see a function named updateDynElmSrc  in the py file. There is where you might need to add some logic to find the layer of your interest and update the dynamic text element's definition to point to the correct layer.

@TanuHoque @JakeSkinner @LisaCasey @TeresaSmithson Just thought I would chime in in case this helps anyone:  I found I could not get this to work if the layer in the webmap that I wanted to grab attributes from is an editable feature service, but it works if it's a map service (same service - it produced 2 rest endpoints when I published with feature access).  This behavior stayed the same even after trying the updateDynElmSrc  update.  So I'm thinking I have to have both layers in my web map - one editable so people can add their points and attributes, and one map service so they can print the map with the attributes showing.

Hello,

I am finding that this works for me, except that it doesn't reflect the filter that I'm using on the dynamic text layer. It's displaying all of the values that *would be* visible in the map extent, if the filter weren't applied.

tahunt01_0-1695414917877.png 

tahunt01_1-1695414934609.png

The blue outline area is the layer I'm using for dynamic text, it's filtered to show just this one, but the text is still listing all the projects in this area.

One thing that I noticed that is different between your dynamic text element and mine is that yours points to a .xml path whereas mine points to .json. 

tahunt01_2-1695415062772.png

Is it possible that it has something to do with that?

Thank you for this helpful post.

 

@JakeSkinner  and @TanuHoque 

Thanks for posting this, 

I am also wondering if there is a way to display attributes from the first record only, when the filter widget is designed to return multiple records?  

I think the answer currently is no... In ArcMap, when setting the dynamic text, you can choose between All rows | Visible rows | Custom query.  Your steps advise to use 'Visible rows" which means it will only work properly as long as only 1 feature is selected.  I had a look at Custom query but all my attempts at an SQL statement failed eg SELECT Top 1 * FROM <mytable> WHERE OBJECTID IS NOT NULL 

Many thanks for getting me this far. 

Thanks @MoyaCalvert_01 

You are right, we don't have such option.

So, you want to see attributes from the 1st row even when the feature is not visible?

SELECT Top 1 * FROM <mytable> WHERE OBJECTID IS NOT NULL 

the above sql is very specific to SQL Server database. If your data are stored in a SQL Server, then you can write a query like this in the query builder...

objectid IN (SELECT TOP 1 objectid FROM NEWENGLAND_COUNTIES order by STATE_NAME)

 

if your underlying database is Oracle, or PostgreSQL or FileGDB or something else then this syntax might look different. 

Here is a screenshot of a dynamic text element that shows state-name from the first row. Pls note in my layer, I only had data from 3 different states from the New England region.

TanuHoque_0-1706668317139.png

 

pls let me know if you have any questions.

@TanuHoque 

Thanks for replying so quickly.  I'm using a hosted service from ArcGIS online, so I think that is PostgreSQL??   Can you help with syntax?  My attempts at SQL all fail...

You asked: "you want to see attributes from the 1st row even when the feature is not visible?"   No - I only want to get the first record from a filtered set of records (using the filter widget in the online map app). 

Will this query get the first row from the entire dataset and ignore the filter?

@TanuHoque Some brainier GIS people in my organisation have been looking at this.  ArcGIS Pro 3.2 has fixed the arcade expression distinct($feature.name) - (which didn't work in previous versions, it was a bug)  but this expression returns a unique value from a set of values.  

I'll have to wait though - our portal server is still at 2.9 and due to be upgraded later this year.   We are using Pro 3.1.2 atm, I had to find an older 2.9 machine to create the layout and publish.  In the meantime I'm hacking around it by putting in extra long space in the delimiter field and sizing my text box accordingly, so the text box only displays the first value.

Thanks for your help with this and for the detailed explanation of how to publish dynamic text, its been really useful.

@MoyaCalvert_01 

  I'm using a hosted service from ArcGIS online, 

that kind of where clause won't work with services that is because where clause with sub-queries are not supported by either enterprise or agol map/feature services.

 

 

thanks for telling me the workaround that you implemented. And your future plan with 3.2. As you might have already aware that you need to upgrade your poral/server to 11.2 for the arcade fix.

speaking of 11.2, print service has been upgraded to have better support with dynamic text elements. You'd not need to write any arcpy based solution. That said, for now you'd need to use custom js api based app to take advantage of this; out of the box apps like Map Viewer or Experience Builder print widget doesn't support these current. 

Version history
Last update:
‎12-15-2020 04:55 PM
Updated by: