Sunday, 30 July 2017

Automating entire map production in ArcMap using ArcPy/ArcObjects?



I am trying to gather some information on how to create maps based on an existing base map I have. The basemap has all the data loaded. So the user will enter data into a form and the would do a save as, query data in the map, create the map and export to PDF.


I know python is for automation of workflows, but what I need is a way to have my users enter information into a form and have the map created automatically based on a save as of an existing map, some inputs, queries and data in my basemap. I see lots of examples for automating workflows, but I am looking to deploy a solution that non-GIS users could create maps quickly based on some information in arcmap.


Would I do this with ArcObjects or can it in fact be done with Python? Has anyone tried automating the entire map process?


I just need to know which method I would use to create this project? And if I can complete with Python and/or ArcObjects?



Answer



What you are asking can be done using arcpy/python. Below is a script that I compiled to create an mxd and update map element with user inputs. Feel free to use the script, I never took it further than making an mxd.


The script relies on having an mxd already set up as a template. Additionally, in order for the script to work, you need to assign the map elements (text boxes, legends, North Arrows etc)a unique name. e.g. If you open the properties of a text box and click the Size and Position tab, there should be a field called Element Name. Enter the unique name of the element there. See image below.



enter image description here


In the code below, arcpy.GetParameterAsText(0) to (4) are used to compile the file name for the mxd. The other arcpy.GetParameterAsText(*) are the users inputs to add to the map elements. The line "for txtElement in txtElements:" is where the code starts assigning the users inputs to the map elements. Hope this makes sense.


import arcpy, sys, traceback, datetime, os, shutil, getpass
from arcpy.mapping import *

groupDesigLetter = arcpy.GetParameterAsText(0)
# Designates map is generated by the certain team (e.g. G = Geospatial)

mapNumber = arcpy.GetParameterAsText(1)
# The next map in sequence.


workingOrSubmittal = arcpy.GetParameterAsText(2)
# If it is a working document or final document.

projectNumber = arcpy.GetParameterAsText(3)
# This is the project number.

versionNo = arcpy.GetParameterAsText(4)
# v1. One digit sub-version number. 0 or blank denotes a map that has been issued.
# “1,2,3…” denotes internal, intermediate revisions of map before releasing the map

# to an external party.

mapDescription = arcpy.GetParameterAsText(5)
# Description of the map and contents should include page size, orientation, title etc

mapFormat = arcpy.GetParameterAsText(6)
# This is the size and orientation of the map.

mapTitle = arcpy.GetParameterAsText(7)
# This is the tile of the map


mapSubTitle = arcpy.GetParameterAsText(8)
# This is the sub title of the map

figureNumber = arcpy.GetParameterAsText(9)
# This is the figure number of the map.

mapProjection = arcpy.GetParameterAsText(10)

saveMXD = arcpy.GetParameterAsText(11)

# This is the location where the new mxd is saved

newMXDFileName = "{}{}_{}_{}_v{}_{}_{}.mxd".format(groupDesigLetter, mapNumber, workingOrSubmittal, projectNumber, versionNo, mapDescription, mapFormat[:2])
# New file name for the .mxd

newMXDFullPath = os.path.join(saveMXD, newMXDFileName)
# Variable to store the full directory path to the new mxd.

mxdLocation = os.path.join("D:\Templates", mapFormat +".mxd")
# Location of the mxd template


mxdAuthor = getpass.getuser()
# Gets the current user name

mxdTitle = "{} - {}".format(mapTitle,mapSubTitle)
# Compiles the mxd title

mxdCredits = "XXXXXXXXX {}".format(datetime.date.today().year)

try:


arcpy.AddMessage("...Creating Copy of Template...")
# Prints message to screen.

shutil.copy(mxdLocation, saveMXD)
# Copies template .mxd to the save location.

arcpy.AddMessage("...Renaming Copied MXD...")
# Prints message to screen.


rename = os.rename(os.path.join(saveMXD, mapFormat + ".mxd"), os.path.join(saveMXD, newMXDFileName))
# Renames the copies .mxd to the new file name

mxd = MapDocument(newMXDFullPath)
# Variable to store the location to the working map document.

mxd.author = mxdAuthor
# Assigns the current user as the author

mxd.title = mxdTitle

# Assigns the attribute for the mxds title property

mxd.description = mapDescription
# Assigns the attribute for the mxds description property

mxd.relativePaths = True
# Sets the relative path to true.

mxd.credits = mxdCredits


dataFrame = ListDataFrames(mxd, "Layers")[0]

dataFrame.spatialReference = mapProjection

txtElements = ListLayoutElements(mxd,'TEXT_ELEMENT')
# variable to store the list of text elements within the working map document.

for txtElement in txtElements:
# Loop for the text elements within the working map document.


if txtElement.name == 'Title_Block':
# if statement to select the title block map element

txtElement.text = "{}\r\n {}".format(mapTitle.upper(), mapSubTitle)
# Populates the tilte block's text properties

elif txtElement.name == 'Project_Number':
# If statement to select the project number map element.

txtElement.text = projectNumber

# Populates the project number text properties.

elif txtElement.name == 'Version_Number':
# If statement to select the version number map element.

txtElement.text = "v{}".format(versionNo)
# Populates the version number text properties.

elif txtElement.name == 'Figure_Number':
# If statement to select the figure number map element.


txtElement.text = 'Map\r\n{}'.format(figureNumber)
# Populates the figure number text properties.

elif txtElement.name == 'Projection':
# If statement to select the figure number map element.

if mapProjection[8:25] == "XXXXXX":

txtElement.text = 'XXXXXXX {}'.format(mapProjection[26:28])

# Populates the figure number text properties.

elif mapProjection[8:20] == "XXXXXXX":

txtElement.text = "XXXXXXX"

else:

txtElement.text = "Unknown"


else:

continue
# Continues with the loop

arcpy.AddMessage(mapProjection)

arcpy.AddMessage(mapProjection[8:20])

arcpy.AddMessage("...Saving MXD...")

# Prints message to screen.

mxd.save()
# Save the above changes to the new mxd

arcpy.AddMessage("...Finished Creating Map...")
# Prints message to screen.


except:



tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n " + str(sys.exc_type) + ": " + str(sys.exc_value) + "\n"
msgs = "ARCPY ERRORS:\n" + arcpy.GetMessages(2) + "\n"

arcpy.AddError(msgs)
arcpy.AddError(pymsg)


print msgs
print pymsg

arcpy.AddMessage(arcpy.GetMessages(1))
print arcpy.GetMessages(1)

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...