Select to view content in your preferred language

Adding Definition Query to For Loop Before Export to PDF

1218
6
Jump to solution
07-11-2023 10:01 AM
Labels (1)
PAGIS
by
New Contributor II

ArcGIS Pro 2.9.

i have a script that creates a cursor on a layer in Pro. Then a for loop to iterate through each of the items in the cursor. Then I am exporting each project that satisfies the If statement to a PDF. My issue is that I only want one project at a time to show up on the export. Almost like a definition query inside of the results of the if statement. If that makes sense. 

 

The main project is centered, but there are surrounding projects that still appear on the PDF. That main project is the only one that I want to show up on the PDF. And then I have dynamic text set up to reflect that project. However, multiple projects are showing up on the export, therefore my dynamic text is going wild showing all of the features from the layout. 

import arcpy

# Parameters
#name of the projects layer in the layout
Projects = 'Proposed Water Project'
#name of the Project Name field in the projects layer
name_field = 'ProjectName'
#name of the WBS# field in the projects layer
wbs_field = "WBS_Number"
#name of the district field in the projects layer
district_field = "District"
#name of the total length field in the projects layer
length_field = 'Total_Length'
#name of the map frame housing the map
main_frame_name = 'Map Frame'
#name of your layout in Pro
template_name = 'Water WOS Layout'
#name of the layout element housing the "title"
title_textbox_name = 'PAGE NUMBER'
#name of the output folder
output_folder = [removed]

# Find all the layout elements
#setting a variable for the ArcGIS Pro project file
aprx = arcpy.mp.ArcGISProject [removed]
#setting a variable to create a list of the layouts in the project
layout = aprx.listLayouts(template_name)[0]
#setting a variable to create a list of elements in the map frame
main_frame = layout.listElements('MapFrame_Element', main_frame_name)[0]
#setting a variable to create a list of text elements in the map frame
title_textbox = layout.listElements('Text_Element', title_textbox_name)[0]

# Define the cursor for the projects and loop through them

cursor = arcpy.da.SearchCursor(Projects, ['SHAPE@', name_field, wbs_field, district_field, length_field])

for map_number, Projects in enumerate(cursor):

   

   
    # Export the PDF using the following format WOS-Project Name-WBS Number-District
   
    outname = output_folder + str(Projects[1]) + '-' + str(Projects[2]) + '-' + str(Projects[3])
    #If the total length of the project is less than 900 feet, the project will be exported using 75 padding at the
    if Projects[4] < 900:
        extent = Projects[0].extent

        padding = 75
   
        new_extent = arcpy.Extent(extent.XMin - padding,
        extent.YMin - padding,
        extent.XMax + padding,
        extent.YMax + padding,
        None, None, None, None,
        extent.spatialReference)
        main_frame.camera.heading = 0
        main_frame.camera.setExtent(new_extent)
        main_frame.camera.scale = 600
       
        layout.exportToPDF(outname)
        print("The project that was just exported in Step 1 was: A) Project Name: " + str(Projects[1]) + " B) WBS Number: " + str(Projects[2]) + " C) District: " + str(Projects[3]))
    else:
        print("This project was not exported in Step 1 was: A) Project Name: " + str(Projects[1]) + " B) WBS Number: " + str(Projects[2]) + " C) District: " + str(Projects[3]))
print("This message concludes the script execution.")
del cursor
0 Kudos
1 Solution

Accepted Solutions
PAGIS
by
New Contributor II

someone on Redditt pointed me to the Page Queries setup within a Map Series. This has gotten me a lot closer to my intended end goal. 

View solution in original post

0 Kudos
6 Replies
RhettZufelt
MVP Notable Contributor

Code formatting will make it easier to follow.

Not exactly sure what you are trying to do, but can't you just put a where clause on the SearchCursor so it only grabs the records you want, then re-establish the cursor for each project?

R_

 

0 Kudos
PAGIS
by
New Contributor II

@RhettZufelt  thank you for the tip on code formatting. I applied to the original post. I'm not sure what you mean by re-establish the cursor? Could you elaborate more on that please?

0 Kudos
RhettZufelt
MVP Notable Contributor

I mean something like this:

 

projectList = ['Project1', 'Project2', 'Project3']
for proj in projectList:
    expression =  f'"ProjectField" = "{proj}"'  
    with arcpy.da.SearchCursor(fc, [name_field, wbs_field, district_field, length_field],expression) as cursor: #only grab rows that match the expression in cursor
        for row in cursor:
            # Do your stuff here    
            

 

That runs the search cursor on it and only grabs the data that matches the project name,  then runs search cursor on it again (next loop) with the next project name, etc.  Using the 'with' as 'cursor' will also release the cursor object so it can be re-established with the new expression.  Also, the fewer fields you add to the cursor, the faster it will run.  Don't see anywhere you need the geometry of each feature, so no need for SHAPE@.

Though, not sure why you are loading a bunch of rows of data into a cursor as I don't see where that cursor would be used later in the script.  Looks like you want to change what features are displayed each iteration, not loading all the table data into a cursor.

Think maybe you are wanting to loop over a list of projects, establish a definition query on the projects layer that only displays the features for that project, export the map, next project in the list, etc.

R_

Also, I moved this post into Python Questions for you rather than the Python API forum so you may get more responses.

0 Kudos
PAGIS
by
New Contributor II

I included SHAPE@ in the cursor because I am setting the extent of the layout using the SHAPE@ in row 47.

My understanding/intention is that I use enumerate and cursor there to create a tuple of the projects. To your point of changing which features are being displayed each iteration, yes. I am attempting to run a conditional statement on those records in the tuple and I'd like to export where each of the records that meet my conditional statement is the only record being shown on the PDF. 

Thank you for moving the post. 

 

0 Kudos
RhettZufelt
MVP Notable Contributor

It's been a while since I've done something like this, and was back when it was still the arcpy.mapping before Pro.

However, when I had to do similar, I had a list of the projects (I used search cursor and set() to get the unique list), I would loop through the list and set a definition query on the layer so that it only shows data for the appropriate project. 

Then, set the extent to the getSelectedExtent of the layer (which sets the extent to the queried features) (buffer/pad as needed), then export to PDF.

the next loop will change the definition query on the layer to the next project,  change to the extent of the features in the layer, export, etc.

I know there has been a lot of changes to the mapping/mp module, but should still be similar functionality to do something similar.

R_

0 Kudos
PAGIS
by
New Contributor II

someone on Redditt pointed me to the Page Queries setup within a Map Series. This has gotten me a lot closer to my intended end goal. 

0 Kudos