1

I've got a map containing several layers, and a layout set up that uses this map. What I'd like to do is set up a script so that, when the user inputs a "block" (integer) and a map layout (the map will eventually contain several layouts), the script will use the main layer's definition query to display only that, and this will then be exported to PDF using the layout.

Here's what I've got so far. It's a bit bulky, there's a lot of code I could quite easily get rid of but I'm keeping for the moment as they could be good samples to use later:

import arcpy
import arcpy.mp

# This will use the current ArcGIS project, and all layers and layouts within
aprx = arcpy.mp.ArcGISProject("CURRENT")

# Set up variables for which layout and which block we want
RequestedLayout = "MyLayout"
RequestedBlock = 22

# Handy code to list all the maps and layers within those maps, not really necessary
for m in aprx.listMaps():
    print("Map: " + m.name)
    for lyr in m.listLayers():
        print("  " + lyr.name)
        # Is this a layer we want to change and zoom to?
        if lyr.name == "MyMainLayer":
            lyr.definitionQuery = "Blk = " + str(RequestedBlock)
            myLyr = lyr

# Handy code to list all the layouts. We also look for the desired layout here and export it to pdf
print("Layouts:")
for lyt in aprx.listLayouts():
    print(f"  {lyt.name} ({lyt.pageHeight} x {lyt.pageWidth} {lyt.pageUnits})")
    # Is this the layout we want? If so, export to pdf
    if lyt.name == RequestedLayout:
        mapframe = lyt.listElements("MAPFRAME_ELEMENT", "MyMapFrame")[0]
        layer_extent = mapframe.getLayerExtent(myLyr, False, True)
        print(layer_extent)
        mapframe.camera.setExtent(layer_extent)
        print("Exporting")
        lyt.exportToPDF("C:\\temp\\mylayout.pdf")

A simpler, cleaner example could be:

import arcpy
aprx = arcpy.mp.ArcGISProject("CURRENT")

RequestedBlock = 22

m = aprx.listMaps("Map")[0]
lyr = m.listLayers("MyMainLayer")[0]
lyr.definitionQuery = "Blk = " + str(RequestedBlock)
lyt = aprx.listLayouts("MyLayout")[0]
mf = lyt.listElements("mapframe_element", "MyMapFrame")[0]
mf.camera.setExtent(mf.getLayerExtent(lyr, False, True))
lyt.exportToPDF("C:\\temp\\mylayout2.pdf")

Now, whilst the definition query is indeed being changed on the layer I want, the map is not being zoomed to the extent. The print(layer_extent) shows that the extent IS being retrieved from the layer, but for some reason isn't being applied in the mapframe.camera.setExtent line.

Any ideas?

From searching, some people say that this behaviour isn't supported, while others say that I also have to apply the extent to the map.

This is part of a Notebook in ArcGIS Pro. I'm using ArcGIS Pro 2.9.2 and ArcPy 2.9.

0

1 Answer 1

0

Answering my own question - it appears that you do have to set the map's camera as well, though I was having trouble with the code. With credit to https://community.esri.com/t5/python-questions/zoom-map-to-the-extent-of-a-layer-in-arcpy-mp/td-p/279247 I adjusted it. Essentially my new (clean) code is:

import arcpy
aprx = arcpy.mp.ArcGISProject("CURRENT")

RequestedBlock = 22

m = aprx.listMaps("Map")[0]
lyr = m.listLayers("LUR")[0]
lyr.definitionQuery = "Blk = " + str(RequestedBlock)
lyt = aprx.listLayouts("MyLayout")[0]
mf = lyt.listElements("mapframe_element", "MyMapFrame")[0]
mf.camera.setExtent(mf.getLayerExtent(lyr, False, True))
m.defaultCamera = mf.camera
lyt.exportToPDF("C:\\temp\\mylayout2.pdf")

With the new line (which sets the map camera to the same as the mapframe camera) being the second-to-last line:

m.defaultCamera = mf.camera

Not the answer you're looking for? Browse other questions tagged or ask your own question.