Select to view content in your preferred language

Custom Geoprocessing Tool Reporting for ArcGIS online

4626
7
Jump to solution
01-19-2016 01:28 PM
RachelAlbritton
Occasional Contributor III

I've written a basic script that reads through a table stored in an SDE database and reports back on values within a particular field. If the field is equal to 'Report to Manager" the script fetches notes about the issue and includes it in the report. the report is just a simple text file.

I ran the tool on my computer and it runs fine, and then published it as a processioning service. I set one parameter - to let a user define an output directory, but this option does not appear on AGOL. If I execute the tool, it runs but there are no visible results.

How do I get this report to run within AGOL so that the user can get a txt or pdf of the requested report?

import arcpy, os
import time
from datetime import datetime
from datetime import date

arcpy.env.workspace = "C:\\Temp"
arcpy.env.overwriteOutput = True

def outName(input,post="_Output"):
    """Returns output name."""
    outName=os.path.basename(input).split(".")[0]+post
    return outName

folder = arcpy.GetParameterAsText(0) #"C:\\Temp\\DDC_ReportSummary.txt"
inputfile = folder+"/DDC_ReportSummary.txt"
date= date.today()
time = datetime.now().time()

infile = open(inputfile,'w')
infile.write("REPORT SUMMARY: "+str(date)+" "+str(time)+'\n\n')

StopsTable = "C:\\Temp\\DDC_Stops"
ReportsTable = "C:\\Temp\\DDC_Reports_Table"

#Get the status of all stops that where status = "OK" for the current date, recorded within the past 3 hours

sc1=arcpy.SearchCursor(StopsTable)

for row in sc1:
    if row.Stop_Status == "OK":
        infile.write("Stop "+str(row.Stop_Number)+": "+row.Stop_Status+"\n")          
    del row
del sc1

#Get information on any stops that need to be reported to a manager
#In the Reports table, select all the records that have been recorded on the current date, wihtin the past 3 hours

infile.write("\nMANAGER ATTENTION REQUIRED\n\n")
sc2 = arcpy.SearchCursor(StopsTable)

for row in sc2:
    if row.Stop_Status =="Report to Manager":
        infile.write("Stop "+str(row.Stop_Number)+": "+row.Stop_Status+":")
        
        sc3 = arcpy.SearchCursor(ReportsTable)
        for line in sc3: 
            if line.Stop_Num ==row.Stop_Number:
                infile.write(line.Issue+"\n\n")
            del line
        del sc3
    del row
del sc2                     
    

infile.close()
0 Kudos
1 Solution

Accepted Solutions
JamesCrandall
MVP Frequent Contributor

I didn't intend for that to be a literal example, rather you can see there are some elements that you might need to implement.

Are you attempting to write/overwrite the same .txt output with each request of the report?  Or do you hope to get unique output(s)?

It seemed like you are trying to write/overwrite a .txt file from published geoprocessing service requests, rather than generating unique output(s).  I'm not sure of an instance where you'd want that since you'd run into concurrency problems and that's where the scratch workspace can help. Specifically this,

Output_File = os.path.join(arcpy.env.scratchFolder, output)

You will need to construct the "output" variable to match your text file.  It also shows utilizing the scratch workspace --- otherwise, you will run into some concurrency issues if you have multiple users attempting to run the report (which you are writing to a hardcoded destination).  Perhaps I'm misreading how you construct the actual inputfile variable, which if that is not unique to each request it will be overwriting itself for each request (that would be a problem in a multi-user environment).

View solution in original post

7 Replies
JamesCrandall
MVP Frequent Contributor

You can pull some ideas from the Basic Web Map Printing and Exporting example:

Tutorial: Basic web map printing and exporting using arcpy.mapping—Documentation (10.3 and 10.3.1) |...

Essentially, it looks like you are missing the need to use a scratch workspace and an output parameter in your geoprocessing service.

0 Kudos
RachelAlbritton
Occasional Contributor III

Thanks James - but this doesn't seem to be what I need. This all points to being able to print maps to PDF from AGOL, which I understand how to do.

The tool I need to create is to simply print a basic report based on a table within a map, not the map itself.

0 Kudos
JamesCrandall
MVP Frequent Contributor

I didn't intend for that to be a literal example, rather you can see there are some elements that you might need to implement.

Are you attempting to write/overwrite the same .txt output with each request of the report?  Or do you hope to get unique output(s)?

It seemed like you are trying to write/overwrite a .txt file from published geoprocessing service requests, rather than generating unique output(s).  I'm not sure of an instance where you'd want that since you'd run into concurrency problems and that's where the scratch workspace can help. Specifically this,

Output_File = os.path.join(arcpy.env.scratchFolder, output)

You will need to construct the "output" variable to match your text file.  It also shows utilizing the scratch workspace --- otherwise, you will run into some concurrency issues if you have multiple users attempting to run the report (which you are writing to a hardcoded destination).  Perhaps I'm misreading how you construct the actual inputfile variable, which if that is not unique to each request it will be overwriting itself for each request (that would be a problem in a multi-user environment).

RachelAlbritton
Occasional Contributor III

Thanks James. I'll spend some time with this today. Yes, the txt. output will be over written each time (at least that's my current intention), while all of the historical data will persist in the DB. (I understand that this eventually means I need to build in code to grab only records that fall within a specific time frame).

For the application, there should only be one user at a time, so there shouldn't be any concurrency issues.

My variables are hard coded in for testing purposes, but I usually make them user inputs within the final product. Thank you for your input.

0 Kudos
JamesCrandall
MVP Frequent Contributor

Make sure any and all folders/directories you hope to utilize are registered with ArcGIS Server and appropriate permissions applied.

About registering your data with ArcGIS Server—Documentation (10.3 and 10.3.1) | ArcGIS for Server

Make your data accessible to ArcGIS Server—Documentation (10.3 and 10.3.1) | ArcGIS for Server

RachelAlbritton
Occasional Contributor III

Got it. Thank you. I started with the link you gave me and have been pretty successful so far.

For clarification for anyone else who may be interested -

I  created a new mapping template which is stored in a registered folder for ArcGIS Server.

I then wrote a script that writes the report statuses of interest to a series of text boxes within the map template.

The script was then uploaded to ArcGIS server as a GP tool.

I added a GP tool to my web map. When the GP tool is run by the end user it updates and saves the template. Then the user can print the report using the print widget (which has the REST end point of the MXD template created).

I still have a few things to work out but this is working. Thank you.

KevinHibma
Esri Regular Contributor

A couple things to clear up - you say published to AGOL?  Do you mean your ArcGIS Server (not ArcGIS Online)? You cannot publish GP Services to ArcGIS Online, you can place a reference to them, but the service itself exists on your ArcGIS Server (not arcgis.com)

GP Services dont...lets say "work" with a user defined workspace. A workspace is an unsupported item for a GP Service, as such, it becomes hardcoded when you publish. Thats why you're seeing the user having no choice when they execute the service. If you go back and re-publish the service, inside the Service Editor if you go to that parameter, you'll see its hardcoded. There are ways to deal with providing an input workspace, but looking at your workflow, I dont think this is the path you need (or really want) to go down. Keep in mind, if this were to 'work', whatever directory the user was supplying as input would have to exist on the server itself, not a local path on their computer (I'm sure you can see possible problems here.) So, all that considered, some options:

Looking at your script, my guess is your 'output' in the end is the text file which you're creating inside the directory the user has specified. Instead of asking for a directory to save a text file, you have a few options. You could specify a FILE itself, where the user would provide 'c:\temp\mytext.txt'. Alternatively you could ask for a STRING and use that to build a file and path, c:\temp\USERSTRING.txt. Or, better yet, since GP Services have a well defined pattern of where results get created, just use the options available to you and return the FILE (which you internally create/manage) to the end user.

So (and I cant find the button to make this nicely formatted code....) do something like this:

Code

reportFile = os.path.join(arcpy.env.scratchFolder, "report.txt")

# ... code that puts stuff in the file.

arcpy.SetParameterAsText(0, reportFile)

Tool Param (in the UI)

output file  | type=file | derived output