Select DDP features by location and export selected pages to PDF

Bonus post today – Python time! Often when I create data driven pages for different themes (Water Supply, Sanitation, Transport etc), I have to create several copies of my data driven pages index layer and edit it. This is because certain sections of the study area may not have any features for that particular theme. It’s not good enough to simply skip it, because the scale changes and there are other aesthetic factors to consider.

However, since most of these mapbooks are for asset management, how the map looks is not nearly as important as the data which can be seen, particularly the unique IDs of the features. This is why last night I came up with this script.


#
# @date 13/07/2015
# @author Cindy Williams
#
# Intersects feature layers with the index layer
# for selected data driven export to a multi-page
# PDF with embedded layers.
#
# For use as a standalone script.
#
import arcpy
import os
map_folder = r"C:\Some\Arb\Folder\mxd
pdf_folder = r"C:\Some\Arb\Folder\pdf"
kml_folder = r"C:\Some\Arb\Folder\kml"
# Get all the mxds in the map folder
(_,_, mapdocs) = os.walk(map_folder).next()
for md in mapdocs:
mxd = arcpy.mapping.MapDocument(os.path.join(map_folder, md))
df = arcpy.mapping.ListDataFrames(mxd)[0] # First data frame
ddp = mxd.dataDrivenPages
ddp_lyr = ddp.indexLayer
# Only get the layers in the Data group
data_lyrs = [lyr for lyr in arcpy.mapping.ListLayers(mxd) if lyr.isFeatureLayer and lyr.longName.split("\\")[0] == "Data"]
for lyr in data_lyrs:
# Selects the data driven pages that intersects all feature layers
# in the Data group
arcpy.management.SelectLayerByLocation(in_layer=ddp_lyr,
overlap_type="CONTAINS",
select_features=lyr,
selection_type="ADD_TO_SELECTION")
print("Data driven pages selected: {}.".format(len(ddp.selectedPages)))
pdf_name = os.path.join(pdf_folder, md[:-4] + ".pdf")
# Uses the PDF export function from the DataDrivenPagesClass
ddp.exportToPDF(out_pdf=pdf_name,
page_range_type="SELECTED",
multiple_files="PDF_SINGLE_FILE",
resolution=100,
layers_attributes="LAYERS_AND_ATTRIBUTES",
georef_info="True")
print("Exported " + md)
# Cannot export to KML with basemap in mxd. Remove layer
# first and add back in
kmz_name = os.path.join(kml_folder, md[:-4] + ".kmz")
# Converts the mxd to KML. Only the Data group layers are
# switched on, so only they will be exported. Can enforce
# the layer visibility by lyr.visible = True
arcpy.conversion.MapToKML(in_map_document=mxd,
data_frame=df.name,
out_kmz_file=kmz_name,
map_output_scale=10000)
print("KML conversion complete.")
print("Script complete.")

The DDP index layer is intersected with all the relevant feature layers, to ensure that only pages containing features for that service are selected for export. I also had the chance to use the exportToPDF function of the DataDrivenPages class. In Line 40, it allows for the export of the currently selected DDP pages.

Write all rows in a feature class to a csv file

This is something I use often, although hardly ever in the same way twice.


#
# @date 16/04/2015
# @author Cindy Williams
#
# Writes the contents of a feature class to csv.
# Writing to csv is usually used when quickly
# needing to give file contents to a non-GIS
# person, or in creating a GIS inventory.
#
# For use as a standalone script.
#
import arcpy
import csv
arcpy.env.workspace = r"C:\Some\Arb\Folder"
csv_file = r"output.csv"
# Always create feature layer for faster access
ftr = arcpy.management.MakeFeatureLayer("work.gdb\ftr")
# Exclude all shape fields from output
fields = [field.name for field in arcpy.ListFields(ftr) if not field.name.startswith("Shape")]
with open(csv_file, 'wb') as csvfile:
csvwriter = csv.writer(csvfile)
csvwriter.writerow(fields)
with arcpy.da.SearchCursor(ftr, fields) as cursor:
for row in cursor:
csvwriter.writerow(row)

I’ve included Line 21 because the main reason why you would be using this method in the first place, is because a non-GIS person has requested data from you. Usually, they don’t require any Shape information.

This way, you include only the attribute information. If they do require lengths/coordinates, it’s much easier to specify a Shape token such as SHAPE@LENGTH or SHAPE@XY than the field itself.