Select to view content in your preferred language

Repetitive Tasks: Save a copy of APRX, Rename Copied APRX, Query a layer, Set scale of map frame

215
3
08-06-2024 02:13 PM
CiaraMarleneKeenan
Occasional Contributor

Calling all Developers! I do NOT want to do something manually lol Or trying to do the least amount of repetitive tasks as possible.

I need a script that would allow me to

1. Save a copy of an APRX template

2. Rename the copied APRX x 50

3. Query a polygon layer based on a name field x 50

4. Set scale of map frame x ?

5. Pan to & center polygon feature in map frame x 50

 

Unfortunately, I am not able to use a map series for this particular project because there are too many different scales for the features to make the maps look nice. I need to make about 50 maps so the more I can do with python will be greatly appreciated.

0 Kudos
3 Replies
TonyAlmeida
Frequent Contributor

Here is a little something to get you started.

Untested.

import arcpy
import os

template_aprx_path = r"C:\your\template.aprx"  # Path to your APRX template
output_folder = r"C:\output\folder"  # Folder to save the copies
polygon_layer_path = r"C:\path\to\your\polygon_layer"  # Path to your polygon layer
name_field = "Name"  # Field used for querying
map_frame_name = "Layers Map Frame"  # Name of the map frame to modify
scale = 50000  # Desired scale for the map frame

# Ensure output folder exists
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

# Create copies of the APRX template and process each
for i in range(1, 51):  # Loop 50 times
    # Define the new APRX file path
    new_aprx_path = os.path.join(output_folder, f"Project_{i}.aprx")
    
    # Copy the APRX template to the new file
    arcpy.management.Copy(template_aprx_path, new_aprx_path)
    
    # Open the APRX file
    aprx = arcpy.mp.ArcGISProject(new_aprx_path)
    
    # Get the map
    map_obj = aprx.listMaps()[0]
    
    # Get the map frame
    map_frame = map_obj.listLayers(map_frame_name)[0]
    
    # Query the polygon layer and process each feature
    with arcpy.da.SearchCursor(polygon_layer_path, [name_field]) as cursor:
        for row in cursor:
            feature_name = row[0]
            
            # Select the polygon feature based on the name
            arcpy.management.SelectLayerByAttribute(polygon_layer_path, "NEW_SELECTION", f"{name_field} = '{feature_name}'")
            
            # Get the selected feature's extent
            selected_features = arcpy.management.MakeFeatureLayer(polygon_layer_path, "temp_lyr", f"{name_field} = '{feature_name}'")
            extent = arcpy.Describe(selected_features).extent
            
            # Zoom polygon feature in the map frame
            map_frame.camera.setExtent(extent)
            map_frame.camera.scale = scale
            
            # Save changes
            aprx.save()
    
    # Release the APRX object
    del aprx

print("Processing completed.")

 

 

0 Kudos
CiaraMarleneKeenan
Occasional Contributor

Hi Tony,

I am getting this error...

 

Traceback (most recent call last):
File "<string>", line 30, in <module>
IndexError: list index out of range

 

Also am I supposed to put quotes around the map name on line 27?

Thank you.

0 Kudos
TonyAlmeida
Frequent Contributor

The following code loops through the "CITY" field, processing each unique city. For each city, it creates a feature class in the geodatabase, zooms into that city's area, and generates a new .aprx file named after the city. I believe this code will do what you are asking. You may need to make adjustments to fit your specific requirements, hope it helps.

 

 

project.save()
import arcpy
import os

# Define paths
gdb_path = r"C:\your\template.gdb" # Path to your geodatabase location
polygon_layer_path = r"C:\your\template.gdb\layer" Path to your polygon layer

# Get the current project and map
project = arcpy.mp.ArcGISProject("CURRENT")
map = project.listMaps()[0]  # Adjust if necessary to select the correct map
lyt = project.listLayouts('Layout')[0]  # Adjust if necessary to select the correct layout, THIS IS SUPPER IMPORTANT, IF YO DON'T CHANGE IT TO MATCH YOURS,THE CODE WILL NOT CREATE THE APRX.
mf = lyt.listElements("MAPFRAME_ELEMENT", '*')[0]  # Get the first map frame element

# Make a feature layer from the feature class
arcpy.management.MakeFeatureLayer(polygon_layer_path, "city_limits_layer")

# Access the feature layer
city_limits_layer = "city_limits_layer"

# Get unique values from the CITY field
city_names = set()
with arcpy.da.SearchCursor(city_limits_layer, ["CITY"]) as cursor:
    for row in cursor:
        city_names.add(row[0])

# Loop through each unique city and create a feature class in the geodatabase
for city_name in city_names:
    # Create a feature layer for the city
    arcpy.management.MakeFeatureLayer(polygon_layer_path, "temp_city_layer", f"\"CITY\" = '{city_name}'")
    
    # Define the path for the new feature class in the geodatabase
    city_feature_class = os.path.join(gdb_path, f"{city_name.replace(' ', '_')}_fc")
    
    # Copy the feature layer to the geodatabase
    arcpy.management.CopyFeatures("temp_city_layer", city_feature_class)
    
    # Add the feature class to the map
    map.addDataFromPath(city_feature_class)
    
    # Get the new layer from the map
    new_layer = map.listLayers(f"{city_name.replace(' ', '_')}_fc")[0]
    
    # Get extent using arcpy.Describe()
    desc = arcpy.Describe(new_layer)
    ext = desc.extent
    
    # Zoom to the extent of the layer
    mf.camera.setExtent(ext)
    
    # Set the scale to 1:24,000
    mf.camera.scale = 24000
    
    # Create a new project for each city
    new_project_path = os.path.join(r"C:|Tenp\CityLimits", f"{city_name.replace(' ', '_')}.aprx") # Folder to save the copies
    new_project = arcpy.mp.ArcGISProject("CURRENT")
    new_project.saveACopy(new_project_path)

# Save the original project (optional)
#project.save()

 

 

0 Kudos