Hello Community!
I am making a thematic map series using definition queries on a single layer. The layout has a map, two charts, and some dynamic text. The script I wrote iterates through an array of distinct values, applies it to the definition query, saves and appends the layout to a .pdf file (I used this thematic map project as a base).
outputFolder = rf"C:\temp\MapSeries\10_Deliverables"
pdfFileName = "SFY25_MapSeries.pdf"
# Reference project
p = arcpy.mp.ArcGISProject(rf"C:\temp\MapSeries\MapSeries.aprx")
# Reference the map and layout
m = p.listMaps("LayoutMap")[0]
lyt = p.listLayouts("MapSeriesLayout")[0]
lyr = m.listLayers("SFY25_1E")[0]
# Create a new PDF pages will be appended into. Remove the file if it already exists
if os.path.exists(os.path.join(outputFolder, pdfFileName)):
os.remove(os.path.join(outputFolder, pdfFileName))
pdf = arcpy.mp.PDFDocumentCreate(os.path.join(outputFolder, pdfFileName))
# Loop through types and apply query
for type in selectedTypes:
iteration = 0
lyr.definitionQuery = rf"type = '{type}'"
print(rf"Exporting and appending: {type}")
lyt.exportToPDF(rf"{outputFolder}{iteration}.pdf")
pdf.appendPages(rf"{outputFolder}{iteration}.pdf")
os.remove(rf"{outputFolder}{iteration}.pdf")
iteration += 1
print("Saving and closing pdf")
pdf.saveAndClose()
print("done")
os.startfile(rf"{outputFolder}\{pdfFileName}")
The script works great as long as I'm in ArcGIS Pro (3.3.2). It doesn't matter if I run it through the python window or a notebook, it exports and appends all .pdf files and the map/text/charts all reflect the correct definition query. However, if I run the script from an IDE such as VSCode or PyCharm, only the map and dynamic layout text update with each .pdf. The charts only reflect the data they were displaying when the project was last saved.
Can anyone think of a reason for this difference? I'm using the same python interpreter in ArcPro as my IDE.
Thank you!
Solved! Go to Solution.
I found a way for this to work. It seems like the charts in the layout don't automatically refresh like the map frame does when the script is run outside of ArcGIS Pro. Since I can't find an arcpy method specifically to refresh layout elements, I manually force the charts to update by changing their associate map frame to a secondary, scratch map frame and then back to the main one. My updated script in case anyone else comes across this roadblock in the future:
selectedTypes = [ <<array of types for definition query>> ]
outputFolder = rf"C:\temp\MapSeries\10_Deliverables"
pdfFileName = "SFY25_MapSeries.pdf"
# Reference project
p = arcpy.mp.ArcGISProject(rf"C:\temp\MapSeries\MapSeries.aprx")
# Reference the map and layout
m = p.listMaps("LayoutMap")[0]
lyt = p.listLayouts("MapSeriesLayout")[0]
lyr = m.listLayers("SFY25_1E")[0]
memChart = lyt.listElements("MAPSURROUND_ELEMENT", "Member Chart")[0]
cntyChart = lyt.listElements("MAPSURROUND_ELEMENT", "County Chart")[0]
mainFrame = lyt.listElements("MAPFRAME_ELEMENT", "Map Frame")[0]
scratchFrame = lyt.listElements("MAPFRAME_ELEMENT", "Scratch Frame")[0]
# Create a new PDF pages will be appended into. Remove the file if it already exists
if os.path.exists(os.path.join(outputFolder, pdfFileName)):
os.remove(os.path.join(outputFolder, pdfFileName))
pdf = arcpy.mp.PDFDocumentCreate(os.path.join(outputFolder, pdfFileName))
# Loop through types and apply query
for type in selectedTypes:
iteration = 0
lyr.definitionQuery = rf"type = '{type}'"
memChart.mapFrame = scratchFrame
memChart.mapFrame = mainFrame
cntyChart.mapFrame = scratchFrame
cntyChart.mapFrame = mainFrame
print(rf"Exporting and appending: {type}")
lyt.exportToPDF(rf"{outputFolder}{iteration}.pdf")
pdf.appendPages(rf"{outputFolder}{iteration}.pdf")
os.remove(rf"{outputFolder}{iteration}.pdf")
iteration += 1
print("Saving and closing pdf")
pdf.saveAndClose()
print("done")
os.startfile(rf"{outputFolder}\{pdfFileName}")
I found a way for this to work. It seems like the charts in the layout don't automatically refresh like the map frame does when the script is run outside of ArcGIS Pro. Since I can't find an arcpy method specifically to refresh layout elements, I manually force the charts to update by changing their associate map frame to a secondary, scratch map frame and then back to the main one. My updated script in case anyone else comes across this roadblock in the future:
selectedTypes = [ <<array of types for definition query>> ]
outputFolder = rf"C:\temp\MapSeries\10_Deliverables"
pdfFileName = "SFY25_MapSeries.pdf"
# Reference project
p = arcpy.mp.ArcGISProject(rf"C:\temp\MapSeries\MapSeries.aprx")
# Reference the map and layout
m = p.listMaps("LayoutMap")[0]
lyt = p.listLayouts("MapSeriesLayout")[0]
lyr = m.listLayers("SFY25_1E")[0]
memChart = lyt.listElements("MAPSURROUND_ELEMENT", "Member Chart")[0]
cntyChart = lyt.listElements("MAPSURROUND_ELEMENT", "County Chart")[0]
mainFrame = lyt.listElements("MAPFRAME_ELEMENT", "Map Frame")[0]
scratchFrame = lyt.listElements("MAPFRAME_ELEMENT", "Scratch Frame")[0]
# Create a new PDF pages will be appended into. Remove the file if it already exists
if os.path.exists(os.path.join(outputFolder, pdfFileName)):
os.remove(os.path.join(outputFolder, pdfFileName))
pdf = arcpy.mp.PDFDocumentCreate(os.path.join(outputFolder, pdfFileName))
# Loop through types and apply query
for type in selectedTypes:
iteration = 0
lyr.definitionQuery = rf"type = '{type}'"
memChart.mapFrame = scratchFrame
memChart.mapFrame = mainFrame
cntyChart.mapFrame = scratchFrame
cntyChart.mapFrame = mainFrame
print(rf"Exporting and appending: {type}")
lyt.exportToPDF(rf"{outputFolder}{iteration}.pdf")
pdf.appendPages(rf"{outputFolder}{iteration}.pdf")
os.remove(rf"{outputFolder}{iteration}.pdf")
iteration += 1
print("Saving and closing pdf")
pdf.saveAndClose()
print("done")
os.startfile(rf"{outputFolder}\{pdfFileName}")