Summary
Exports a formatted, tabular report using data from layers or stand-alone tables in a map document along with the report template information that is provided in a report layout file (.rlf).
Discussion
TheExportReport function provides a mechanism to automate the generation of reports using layers or tables authored in a map document (.mxd) or layers in a layer file (.lyr). A report layout file authored in ArcMap is a template that stores information about the content and placement of the items in a report. The report layout file is used along with the source data in a map document to create output reports. The source data can also have associated joins and related table information that is used within the report.
The source data must exist in a map document (.mxd) or layer file (.lyr), and the dataset field names must match those in the report layout file in order for ExportReport to execute properly. A report layout file can be used with different data sources provided that the data source has the same dataset field names. If the data is similar but the data source field names are different, then the field_map parameter can be used to remap the report layout file fields to different field names in the source dataset.
There are numerous elements authored in a report layout file within ArcMap that are not directly exposed through the ExportReport function. It may be necessary to author a collection of specific templates for generating and exporting different report scenarios.
The reporting tools in the ArcMap user interface have a button called Dataset options. This allows the author to choose only one of four ways in which records will be processed: All, Selected Set, Visible Extent, and Definition Query. Thedataset_option parameter serves this same purpose and takes a keyword. A dataset_option of ALL or SELECTED will process the appropriate records. If the dataset_option is set to DEFINITION_QUERY, then a valid string needs to be provided for the report_definition_query parameter. If the dataset_option is set to EXTENT, then a valid Extent object needs to be provided for the extent parameter.
Similar to the user interface, it is only possible to use one dataset_option keyword at a time. For example, in the user interface, it is not possible to process only the selected set of records and only those in the visible extent. The same rule applies to the ExportReport function; only one parameter can be set at a time. If more than one of these parameters is set, they will overwrite each other. However, standard ArcPy attribute and spatial query functions can be combined together and coupled with a value of SELECTED for the dataset_option parameter to generate the final, desired report. An example is provided below.
The page_range parameter allows you to generate a report for only a subset of pages. This can be a continuous group of pages (5-12) or even a discontinuous set of pages (3,7). In these cases, when you generate a report and the starting_page_number is set to 1, the printed page numbers will match what you've entered (Page 3, Page 7). This was designed for scenarios where only a selected number of pages will be reprinted and inserted into already existing reports. If the scenario requires that the output page numbers be continuous, for example (Page 1, Page 2), then you must set the starting_page_number to equal the page number of interest, and set the page_range to be a single page. This means that ExportReport will need to be executed once for each page, for example, once with starting_page_number = 3, page_range="3" and again with starting_page_number = 7, page_range="7".
The field_map parameter is only needed if the dataset field names are different between the source_data and the field names used to build the report layout file. When creating the field_map, only the fields used in the report need to be added to the dictionary. If fields are dropped from the field map dictionary, those fields will be dropped from the report. The mapped fields must have identical data types, and the field names in the field_map are case sensitive.
It is possible to use arcpy.mapping to build reports so you can put a map in your report. Pictures in a report have a property called Source Image. Arcpy.mapping does not have access to this value, but if the source image value is pointing to a path on disk, arcpy.mapping can update the file on disk using an export operation, and the report engine will use whatever image is currently available. In a Data Driven Pages example, you could change the picture based on the current extent, for example, with arcpy.mapping before calling the next page. An example is provided below.
For more information about reporting in ArcGIS, see the following introductory topics:
Syntax
ExportReport (report_source, report_layout_file, output_file, {dataset_option}, {report_title}, {starting_page_number}, {page_range}, {report_definition_query}, {extent}, {field_map})
Parameter | Explanation | Data Type |
report_source | Object | |
report_layout_file | A string that represents the path and file name of the report layout file (.rlf). | String |
output_file | A string that represents the path and file name of the output file. The specified file extension controls the output format. The following extensions/formats are supported: .htm, .html, .pdf, .rtf, .tif, .tiff, .txt, and .xls. | String |
dataset_option | A keyword that specifies which dataset rows will be processed in the output report. This value will override the Dataset Options value stored in the report layout file which is found in the Report Properties dialog box. If the dataset_option parameter is not set, it will default to the value stored in the report layout file. If the dataset_option is set to DEFINITION_QUERY, then a valid string needs to be provided for the report_definition_query parameter. If the dataset_option is set to EXTENT, then a valid Extent object needs to be provided for the extent parameter. Because the dataset_option keyword controls which additional parameter to use, only one of these parameters can be set at a time, just like in the user interface.
(The default value is USE_RLF) | String |
report_title | A string that represents the report's title, which appears in the report layout file header section. | String |
starting_page_number | A number that represents the printed page number for the first page of the output report. This value is useful for offsetting page numbers for reports that get appended to the end of existing documents. (The default value is 1) | Long |
page_range | A string that identifies the report pages to be exported to file (for example, 1, 3, 5–12). | String |
report_definition_query | A string that represents a valid definition query that controls which rows will be exported to the output report. This parameter can only be set if the dataset_option parameter is set to DEFINITION_QUERY.This value will overwrite any settings stored in the report layout file. If the report_source layer or table has an existing definition query, then the report_definition_query will be applied to the existing subset of records. | String |
extent | A geoprocessing Extent object. This parameter can only be set if the dataset_option parameter is set to EXTENT. When an extent object is passed into this parameter, the rows will be based on those features that intersect the extent. | Extent |
field_map | This parameter allows you to use a report layout file with a data source that has similar data types but different field names. A dictionary of mapped field names is used to remap the fields used in the report layout file with the new fields in the data source. The following shows an example of the field_map dictionary structure:
| Dictionary |
Code sample
ExportReport example 1
The following script will export a report to a PDF file using the layer's selected features in the map document. Because other optional parameters are being skipped, the extent parameter name is explicitly entered.
import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Transportation")[0]
lyr = arcpy.mapping.ListLayers(mxd, "Accidents", df)[0]
arcpy.mapping.ExportReport(lyr,
r"C:\Project\Project.rlf",
r"C:\Project\Output\ProjectReport.pdf",
"EXTENT",
extent=df.extent)
del mxd
ExportReport example 2
The following script is similar to the one above but uses a layer in a layer file as a reference.
lyr = arcpy.mapping.Layer(r"C:\Project\Layers\Transportation.lyr")
arcpy.mapping.ExportReport(lyr,
r"C:\Project\Project.rlf",
r"C:\Project\Output\ProjectReport.pdf",
"EXTENT",
extent=df.extent)
del mxd
ExportReport example 3
The following script extends the example above to demonstrate how to combine a spatial selection and an attribute selection to generate the desired report. This is required because only one dataset_option can be used at a time. The results are combined into a single selection and uses a value of SELECTED for the dataset_option parameter.
import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Transportation")[0]
lyr = arcpy.mapping.ListLayers(mxd, "Accidents", df)[0]
#The DataFrame extent object is converted into a polygon feature so it can be used with the SelectLayerByLocation function.
dfAsFeature = arcpy.Polygon(arcpy.Array([df.extent.lowerLeft, df.extent.lowerRight, df.extent.upperRight, df.extent.upperLeft]),
df.spatialReference)
arcpy.SelectLayerByLocation_management(lyr, "INTERSECT", dfAsFeature, "", "NEW_SELECTION")
arcpy.SelectLayerByAttribute_management(lyr, "SUBSET_SELECTION", "\"Accidents\" > 3")
arcpy.mapping.ExportReport(lyr,
r"C:\Project\Project.rlf",
r"C:\Project\Output\ProjectReport.pdf",
"SELECTED")
del mxd
ExportReport example 4
The following script uses an existing report layout file against a different dataset with different field names. A new title is used to overwrite the report layout file's title, and the fields are remapped using the field_map parameter.
import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Transportation")[0]
lyr = arcpy.mapping.ListLayers(mxd, "Traffic Lights", df)[0]
arcpy.mapping.ExportReport(lyr,
r"C:\Project\Project.rlf",
r"C:\Project\Output\ProjectReport.pdf",
report_title="Traffic Light Coordinates",
field_map={'Accidents':'LightID','X':'Longitude','Y':'Latitude'})
del mxd
ExportReport example 5
The following script demonstrates how to insert a map into a report. A multipage report will be generated. Each page has a large picture that displays the current data frame extent and a report that provides information about the features within the extent. After each data frame extent is changed, the data frame is exported to an .emf file, and ExportReport is used to create a single PDF. All pages are combined into a single, final PDF.
import arcpy, os
path = os.getcwd() #a relative path allowing for easy packaging
#Create PDF and remove if it already exists
pdfPath = path + r"\States_SubRegions.pdf"
if os.path.exists(pdfPath):
os.remove(pdfPath)
pdfDoc = arcpy.mapping.PDFDocumentCreate(pdfPath)
subRegionList = ["East North Central", "East South Central", "Middle Atlantic",
"Mountain", "New England", "Pacific", "South Atlantic",
"West North Central", "West South Central"]
mxd = arcpy.mapping.MapDocument(path + r"\States_SubRegions.mxd")
df = arcpy.mapping.ListDataFrames(mxd)[0]
lyr = arcpy.mapping.ListLayers(mxd, "States")[0]
pageCount = 1
for region in subRegionList:
#Generate image for each sub region
whereClause = "\"SUB_REGION\" = '" + region + "'"
lyr.definitionQuery = whereClause
arcpy.SelectLayerByAttribute_management(lyr, "NEW_SELECTION", whereClause)
df.extent = lyr.getSelectedExtent()
arcpy.SelectLayerByAttribute_management(lyr, "CLEAR_SELECTION")
arcpy.mapping.ExportToEMF(mxd, path + "\RegionalPicture.emf", df) #single file
#Generate report
arcpy.mapping.ExportReport(report_source=lyr,
report_layout_file=path + r"\States_SubRegions.rlf",
output_file=path + r"\temp" + str(pageCount) + ".pdf",
starting_page_number=pageCount)
#Append pages into final output
pdfDoc.appendPages(path + r"\temp" + str(pageCount) + ".pdf")
os.remove(path + r"\temp.pdf")
pageCount = pageCount + 1
pdfDoc.saveAndClose()
del mxd