pythonarcgisarcpy

How to convert Extent, Scale and RefreshView from ArcMap to ArcPro using Python


I used an Python (2.7) ArcMap script for years and now I am trying to convert it to use with ArcPro (Python 3). I have converted half of my ArcMap script to ArcPro (with Visual Studio) but am stuck on modifying my code to zoom to the extent of the layer after modifying its definition query.

The map name is "Mailing List Map".

The layout I want to use to export my pdf maps from is called:"Irrigation_Services_Maps"

The table name I am changing the map title of is a variable called irrStats. It has two columns, Customer Name and Frequency (number of customer names-each record represents an irrigation point. A single customer can have many irrigation points)

I want to create a map with the customer name as the title and all the irrigation points associated with that customer and export it as a pdf.

Can someone please guide me as to rewrite this. I have spent all day reviewing this with no discernable solution. You would think it was easier than this.

Issues with code start at line that begins #####. I could not figure out how to add line numbers.

Thanks

import arcpy, os
from datetime import datetime
startTime = datetime.now()

print ((datetime.now() - startTime))

irrFile = arcpy.GetParameterAsText(0)  # Gets the irrigation file with the data in it
pdfFolder = arcpy.GetParameterAsText(1)  # Asks for folder location to put the pdf output files
arcpy.AddMessage(pdfFolder)
pdflist = [f for f in os.listdir(pdfFolder) if f.endswith(".pdf")]
for f in pdflist:
    os.remove(os.path.join(pdfFolder, f))
arcpy.env.overwriteOutput = True  # Allows us to run the script repeatedly without deleting the intermediate files
aprx = arcpy.mp.ArcGISProject("CURRENT")
aprxMap = aprx.listMaps("Mailing List Map")[0]
lyt=aprx.listLayouts("Irrigation_Services_Maps")[0]
scratchDir = pdfFolder + "\\scratch"  # Temporary folder to store temp data
arcpy.AddMessage(scratchDir)

if not os.path.exists(scratchDir):
   os.makedirs(scratchDir)
arcpy.env.workspace = scratchDir

arcpy.env.overwriteOutput = True
tempFGDB = arcpy.CreateFileGDB_management(scratchDir, "scratchGDB").getOutput(0)

arcpy.AddMessage(tempFGDB)
arcpy.env.workspace = tempFGDB
irrStats = "irr_stats"
if arcpy.Exists(irrStats):
   arcpy.Delete_management(irrStats)

arcpy.Frequency_analysis(irrFile, irrStats, "cus_name")
with arcpy.da.SearchCursor(irrStats, ("FREQUENCY", "cus_name")) as rows: # Goes through the irrStats table
   for row in rows:
      cusName = row[1]
      cusFreq = row[0]
      if len(cusName) > 1:
         arcpy.AddMessage(cusName)
         lyr = aprxMap.listLayers(irrFile)[0]
         lyr.definitionQuery = ""       
         lyr.definitionQuery = "\"cus_name\" = " + "'" + cusName + "'"
         for xyz in aprx.listLayouts():   
             for elm in xyz.listElements("TEXT_ELEMENT"):
                if elm.name == "customer":
                    elm.text = (cusName) # and changes the title (text element "Customer") to selected name in table 
                    
###### Don't know how to code Extent, Scale and Refresh View for ArcPro
###### Old ArcMap code needing rewrite below this point

        pdfMap = pdfFolder + "\\" + cusName + ".pdf"
         if cusFreq == 1:  # if there is only one customer record
            arcpy.AddMessage("Name : " + cusName)
            ext = lyr.getExtent()
            df.extent = ext
            arcpy.RefreshActiveView()  # redraw the map
            df.scale = 1000   # set the scale to 1000
            arcpy.RefreshActiveView()  # redraw the map
            arcpy.mapping.ExportToPDF(mxd, pdfMap)
         elif cusFreq > 1:  # if there is more than 1 record
            arcpy.AddMessage("Name2 : " + cusName)
            ext = lyr.getExtent() # Find out the extent
            df.extent = ext # zoom to it
            arcpy.RefreshActiveView()  # redraw the map

            if df.scale < 1000: #set the scale to 1000 is extent is < 1000
               df.scale = 1000
            else:
               df.scale = df.scale * 1.2  # otherwise make the scale 1.2 times the layers extent

            arcpy.RefreshActiveView()  # refresh the map
            arcpy.mapping.ExportToPDF(mxd, pdfMap) # export the map 
            arcpy.AddMessage("more than one")
         else:
            arcpy.AddMessage("Name3 : " + cusName)
         lyr.definitionQuery = ""    

Solution

  • There are a few things you have to look out for.

    1. RefreshActiveView

    With ArcGIS Pro and the "CURRENT" project, all changes to the arcpy.mp-API result in a direct update in ArcGIS Pro, so there is no need to call a refreshActiveView-function.

    1. Layer Extent

    Properties of data elements, such as layers, can be retreived using arcpy.Describe:

        desc = arcpy.Describe(lyr)
        etxent = desc.extent
    
    1. MapFrame/MapView

    In ArcGIS Pro you don't work with DataFrames anymore, instead use the classes MapFrame (Page Layout element) and MapView (active Map). On both of these classes you have a property camera which gives you access to the scale:

        map_view = aprxMap.activeView
        camera = map_view.camera
        
        #get current extent:
        current_extent = camera.getExtent()
        
        #set extent
        camera.setExtent(extent)
    
    1. Scale

    The scale is also a property of the camera-class (read and write) :

        camera = map_view.camera
        
        #read
        scl = camera.scale
        
        #write
        camera.scale *= 1.5
    

    Mayber you can narrow down the problems you have converting to ArcGIS Pro using this.