Generate Survey123 Report

1750
25
Jump to solution
11-28-2018 09:56 AM
Highlighted
MVP Regular Contributor

Really excited about the latest Python API update. Would like to be able to export survey responses as reports with Python. I'm currently stuck at this part. I can see that the reports get generated and I can download them (image below from Survey123 website), but I receive an error in the code: KeyError: 'results' (see attachment). I'm also curious if you can access the generated reports directly with Python after making them.

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
MVP Regular Contributor

Update: I put in a support ticket and there is an existing bug:

   BUG-000119057 : The Python API 1.5.2 generate_report method of the arcgis.apps.survey123 module, generates the following error: KeyError: 'results'

I was playing with a workaround, where you basically just search for the generated reports in your organization and download them. I also delete them after downloading them so future runs wouldn't re-download them.

#this script generates the KeyError: 'results' but still works

from arcgis.gis import GIS
import os
from zipfile import ZipFile
from arcgis.apps.survey123._survey import SurveyManager, Survey

gis = GIS("https://YOURORGANIZATION.maps.arcgis.com","USERNAME","PASSWORD") #fill in 3 strings here
survey_mgr = SurveyManager(gis)
letslearn = survey_mgr.get("id for survey form item in AGO") #fill in 1 string here
print(letslearn.report_templates) #see all available print templates for this survey
choice = letslearn.report_templates[0] #the print template you want to use (0 = first); fill in 1 number here
print(choice)

#example syntax for generate report for some features: letslearn.generate_report(choice, {"where":"fieldname='fieldvalueyouwant'"})
letslearn.generate_report(choice, "1=1") #generates report for all features

#print(letslearn.reports)
for x in letslearn.reports: #finds all Microsoft Word doc files in AGO with you as their owner and "Survey 123" in the tags. Could upload a Word document that wasn't a generated report, add that tag, and it would be found with this
   #print(x.description) remove "#" if you want to see them listed
   if x.description: #if it exists.. (some of my old generated reports had null descriptions)
      if 'id for survey form item in AGO' in x.description: #fill in 1 string here
         id = x.id #get id of that Word doc
         data_item = gis.content.get(id) #get Word doc as an item from AGO
         data_item.download(save_path = r'C:\where\ever\you\want\it') #fill in 1 string here; downloads that Word doc
         data_item.delete() #deletes that Word doc in AGO

View solution in original post

Reply
0 Kudos
25 Replies
Highlighted
New Contributor III

Chelsea, I wondered if you or anyone else had made any further progress with this. I encountered the same error (although the outputted Word documents seem OK), and I'm also having a hard time figuring out the syntax to use in place of '1=1' if I'm trying to only generate records for a subset of the features in the feature layer. Any pointers / examples appreciated!

Reply
0 Kudos
Highlighted
MVP Regular Contributor

Glad to hear someone else is trying to do this. I haven't found a solution yet. Are you saying the output was fine from the Survey123 website? You aren't able to access the output in Python, are you?

Reply
0 Kudos
Highlighted
New Contributor III

Hi, no I'm not able to access the output in Python. For my workflow I'm OK with having the resulting reports be available in AGOL, but I would like to be able only run it for a subset of the features, not all of them. 

Reply
0 Kudos
Highlighted
MVP Regular Contributor

I think I figured your issue out. By default with 1=1 (aka always true), I'm generating 3 reports because there are 3 completed surveys. The error I posted above shows that we're calling _survey.py to run generate_report(). In that .py, it says if where == "1=1": where = {"where":"1=1"} then it uses it like that. So when I put in my code a where statement that was valid and returned only 1 record when using Query under Supported Operations on the Service URL (link on the item's page in AGO), like this in my code: letslearn.generate_report(choice, {"where":"brandname='Fan'"}), only 1 report was generated. Still got my KeyError: 'results', but on the Survey123 website under Report>Recent Tasks>only 1 record in the last task.  Hope that helps.

Highlighted
New Contributor III

Yes!!! Thank you, that worked for me. I'm still getting the KeyError: 'results' but this did the trick for the 'where' part. Thanks for delving deeper into it, much appreciated.

Reply
0 Kudos
Highlighted
MVP Regular Contributor

Update: I put in a support ticket and there is an existing bug:

   BUG-000119057 : The Python API 1.5.2 generate_report method of the arcgis.apps.survey123 module, generates the following error: KeyError: 'results'

I was playing with a workaround, where you basically just search for the generated reports in your organization and download them. I also delete them after downloading them so future runs wouldn't re-download them.

#this script generates the KeyError: 'results' but still works

from arcgis.gis import GIS
import os
from zipfile import ZipFile
from arcgis.apps.survey123._survey import SurveyManager, Survey

gis = GIS("https://YOURORGANIZATION.maps.arcgis.com","USERNAME","PASSWORD") #fill in 3 strings here
survey_mgr = SurveyManager(gis)
letslearn = survey_mgr.get("id for survey form item in AGO") #fill in 1 string here
print(letslearn.report_templates) #see all available print templates for this survey
choice = letslearn.report_templates[0] #the print template you want to use (0 = first); fill in 1 number here
print(choice)

#example syntax for generate report for some features: letslearn.generate_report(choice, {"where":"fieldname='fieldvalueyouwant'"})
letslearn.generate_report(choice, "1=1") #generates report for all features

#print(letslearn.reports)
for x in letslearn.reports: #finds all Microsoft Word doc files in AGO with you as their owner and "Survey 123" in the tags. Could upload a Word document that wasn't a generated report, add that tag, and it would be found with this
   #print(x.description) remove "#" if you want to see them listed
   if x.description: #if it exists.. (some of my old generated reports had null descriptions)
      if 'id for survey form item in AGO' in x.description: #fill in 1 string here
         id = x.id #get id of that Word doc
         data_item = gis.content.get(id) #get Word doc as an item from AGO
         data_item.download(save_path = r'C:\where\ever\you\want\it') #fill in 1 string here; downloads that Word doc
         data_item.delete() #deletes that Word doc in AGO

View solution in original post

Reply
0 Kudos
Highlighted
New Contributor III

Hi Chelsea,

Firstly thank you for the code sample, this led me in the right direction for automating report creation with Python. 

I took your code and added more functionality to it, which now generates reports for submissions from the last 24hrs, downloads the docx files, retrieves email addresses collected via survey, and sends a copy of the relevant docx file to the recipient as an email attachment.  It also has a workaround try/except block for the known bug.

I'm sharing it here as others may find it useful:

https://github.com/nzjs/Automated-Survey123-Reports

Cheers,

John

Highlighted
New Contributor III

Hi! I really love your work, but I have a question

Could you please explain to us how works the block try/except/finally to omit the KeyError?

Thanks

Reply
0 Kudos
Highlighted
New Contributor III

Hello, the try/except/finally block is built into Python as a way of handling exceptions.

In this instance we expect the KeyError exception bug (try/except) and tell the script to continue on after it occurs (finally). 

Cheers.

Reply
0 Kudos