ProConcepts Reports - Esri/arcgis-pro-sdk GitHub Wiki

The Reports functionality in ArcGIS Pro is delivered through the ArcGIS.Desktop.Reports namespace in the ArcGIS.Desktop.Layouts assembly. This assembly provides classes and members that support managing reports, report elements and working with the report views. This includes creating new reports and report elements, modifying existing elements, managing selections, and report view control and navigation.

  • ArcGIS.Desktop.Reports namespace in the ArcGIS.Desktop.Layouts.dll
Language:      C#
Subject:       Reports
Contributor:   ArcGIS Pro SDK Team <[email protected]>
Organization:  Esri, http://www.esri.com
Date:          10/06/2024
ArcGIS Pro:    3.4
Visual Studio: 2022

In this topic

Report class

The Report class provides access to basic report properties, report elements, and export methods. Reports are stored within projects as report items (visible in the Catalog pane) and a project can contain many reports. Existing reports appear in the Catalog pane as individual project items, or as open (report) views. There can be multiple views open for a single report, though, same as with all other view types, only one report view can be active at any one time.

Reference an existing report

There are a two ways to reference an existing report in a project: First, reference a report associated with an active report view, assuming there is one open and active in the application. The report is accessible off the ReportView's Report property (eg ReportView.Active.Report). If there is no active report view then "ReportView.Active" will be null.

//Reference a report associated with an active report view
ReportView activeReportView = ReportView.Active;
if (activeReportView != null)
{
  Report report = activeReportView.Report;
}

Second, reports can be accessed via their associated ReportProjectItem, located in the Catalog pane. Use ReportProjectItem.GetReport to return the underlying Report. To activate the report (i.e. open a report view), call ProApp.Panes.CreateReportPaneAsync(report);. This is also covered in the Activate a Report View sub-section.

//Reference a report associated with a report project item
var reportItem = Project.Current.GetItems<ReportProjectItem>()
                             .FirstOrDefault(item => item.Name.Equals("Some Report Name"));

if (reportItem != null)
{
  //Get the report associated with the reportItem
  Report report = await QueuedTask.Run(() => reportItem.GetReport());
  //activate a view
  FrameworkApplication.Panes.CreateReportPaneAsync(report);//Must be called on the UI
}

Create a new report

Summary

Reports are created programmatically via the various ReportFactory.Instance.CreateReport method overloads. When a report is created a report project item is added to the Contents pane but it is not automatically opened in a new report view. Call FrameworkApplication.Panes.CreateReportPaneAsync(report) to activate a new report view, as needed. FrameworkApplication.Panes.CreateReportPaneAsync must be called on the UI thread.

To create a new report with minimum parameters, use the overload that accepts a report name (string) and the ReportDataSource. Use the ReportDataSource class to define properties such as the fields to be displayed in the report as well as a definition query that filters the underlying data. This is described in further detail in the Report Datasource section:

//Create a new report using minimum properties
QueuedTask.Run(() =>
{
  var newReport = ReportFactory.Instance.CreateReport("New Report", reportDataSource);
//TODO use the report
});

You can also create a report with more advanced options by using a specific Report Template, styling options, field statistics, page size and margins. Detailed help on how to work with ReportTemplate, Report Styling and Report Page configurations are provided in the following sections.

   public Report CreateReport( 
   string name,
   ReportDataSource reportDataSource,
   CIMPage page,
   IEnumerable<ReportFieldStatistic> statistics,
   ReportTemplate template,
   string styling
)

Refer to the Sorting and Grouping data section on how to sort and group report fields. You can also generate summary statistics for a report as well.

Report Datasource

A Report is generated as a well-formatted, multipage representation of your data. The ReportDataSource class represents the data source for a report. Use the Report.DataSource property to access its ReportDataSource.

var reportProjItem = Project.Current.GetItems<ReportProjectItem>().First(item => item.Name.Equals("USAReports"));
Report report = reportProjItem.GetReport();
ReportDataSource dataSource = report.DataSource;

To create a ReportDatasource, use one of two available constructors. The first constructor requires: a MapMember, an optional string definition query for features selection in the MapMember (pass an empty string if there is no definition query), and a collection of CIMReportFields to include in the Report. The map member should point to either a standalone table or a feature layer.

//Get the MapMember whose datasource you want to use for the report
var featureLayerToUse = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>()
                                                       .FirstOrDefault(f => f.Name == "NewCities");
if (featureLayerToUse == null) return;
var listOfFields = new List<CIMReportField>
{
  new CIMReportField{Name = "STATE_NAME"},
  new CIMReportField{Name = "CITY_NAME"},
  new CIMReportField{Name = "ELEVATION"}
};
//Create the ReportDatasource using the MapMember, list of fields...
var reportDataSource = new ReportDataSource(featureLayerToUse, "", listOfFields);

The second constructor is similar, but takes a CIMDataConnection instead of a standalone table or feature layer map member. In this example, a CIMDataConnection is defined for a feature class "NewCities" within a local file geodatabase "TestingReports.gdb".

 //Get the file geodatabase
 Geodatabase geodatabase =  new Geodatabase(
                                 new FileGeodatabaseConnectionPath(new Uri(@"C:\Path\TestingReports.gdb")));

 //Build the CIMDataConnection
 CIMStandardDataConnection cimDataConnection = new CIMStandardDataConnection
 {
   WorkspaceConnectionString = geodatabase.GetConnectionString(),
   WorkspaceFactory = WorkspaceFactory.FileGDB,
   Dataset = "NewCities",
   DatasetType = esriDatasetType.esriDTFeatureClass
 };

 //Define fields to use for the ReportDataSource
 var listOfFields = new List<CIMReportField> {
	new CIMReportField{Name = "STATE_NAME"},
	new CIMReportField{Name = "CITY_NAME"},
	new CIMReportField{Name = "ELEVATION"}
  };

 //Create the ReportDataSource using the CIMDataConnection
 var reportDataSource = new ReportDataSource(cimDataConnection, "", false, listOfFields);

Once the ReportDataSource is constructed, call ReportFactory.Instance.CreateReport to generate the new Report:

//Create the ReportDataSource using the CIMDataConnection or MapMember
ReportDataSource reportDataSource = new ReportDataSource(cimDataConnection, "", false, listOfFields);
//Create a report
ReportFactory.Instance.CreateReport(reportName, reportDataSource);

Use the Report.SetDataSource to apply changes to the underlying report data source:

//On the QueuedTask
//Get the MapMember whose datasource you want to use for the report
var featureLayerToUse = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().
						   FirstOrDefault(f => f.Name == "NewCities");
if (featureLayerToUse == null) return;

//Get the report whose datasource will be changed
var reportProjItem = Project.Current.GetItems<ReportProjectItem>().
						First(item => item.Name.Equals("USAReports"));
var report = reportProjItem.GetReport();

var listOfFields = new List<CIMReportField>
{
  new CIMReportField{Name = "STATE_NAME"},
  new CIMReportField{Name = "CITY_NAME"},
  new CIMReportField{Name = "ELEVATION"}
};
//Create the ReportDatasource using the MapMember, list of fields...
ReportDataSource rdsrc = new ReportDataSource(featureLayerToUse, "", false, listOfFields);
//Update the report's datasource
report.SetDataSource(rdsrc);

Sorting and Grouping data

Sorting organizes report records in alphabetical or numerical order based on the values in one or more fields. Grouping gathers together report records using a common value. Sorting and Grouping information is configured on each individual CIMReportField added to the CIMReportField collection. Use the CIMReportField.SortInfo and CIMReportField .SortOrder properties

The collection is either passed to a ReportDataSource when it is being created or applied to an existing report via Report.SetDataSourceFields:

//Must be on the QueuedTask
//Collection of fields where the CITY_NAME field is sorted in Ascending order
 var listOfFields = new List<CIMReportField>
{
  new CIMReportField{Name = "STATE_NAME"},
  new CIMReportField{Name = "CITY_NAME", SortOrder = 1, SortInfo = FieldSortInfo.Asc},
  new CIMReportField{Name = "ELEVATION"}
};

//To sort, either
//Create a ReportDatasource and create a report
var reportDatasource = new ReportDataSource(featureLayerToUse, "", false, listOfFields);
ReportFactory.Instance.CreateReport("report name", reportDatasource);

//Or, apply the sorting to an existing report via SetDataSourceFields
var existingReport = ...;
existingReport.SetDataSourceFields(listOfFields);

Grouping is defined similarly. Report data can be grouped on a common (repeating) value within the given field and is specified via the CIMReportField.Group property. For example, this snippet is grouping a list of cities together based on which State they are in. As before, provide the list of CIMReportFields either as the parameter to a ReportDataSource when creating it or to an existing report via its SetDataSourceFields method:

 var listOfFields = new List<CIMReportField>
{
  new CIMReportField{Name = "STATE_NAME", Group = true}, //group on common state names
  new CIMReportField{Name = "CITY_NAME", SortOrder = 1, SortInfo = FieldSortInfo.Asc},
  new CIMReportField{Name = "ELEVATION"}
};
//To group, either
//Create a ReportDatasource and create a report
var reportDatasource = new ReportDataSource(featureLayerToUse, "", false, listOfFields);
ReportFactory.Instance.CreateReport("report name", reportDatasource);

//Or, apply the sorting to an existing report via SetDataSourceFields
var existingReport = ...;
existingReport.SetDataSourceFields(listOfFields);

Note: when a field is grouped, it is automatically sorted.

Fields on an existing report can also be grouped via the Report.AddGroup method. Grouping can be removed via Report.RemoveGroups passing in a list of one or more field names for which grouping will be removed. An overload of RemoveGroups allows you to specify a/the ReportSection(s) containing the group(s):

 //On the QueuedTask
 //Add a Group.
 existingReport.AddGroup("STATE_NAME", true, true, "");
 //Remove a group
 existingReport.RemoveGroups(new List<string> { "STATE_NAME" });

Design the report

Predefined field placement and text color can be used to define the initial layout of the report upon creation without the need to alter each element individually. ReportTemplates, Report styling, page size, page orientation, and margin space options are available during report creation to expedite the report creation process. Summary statistics can also be defined.

ReportTemplate

Use the ReportTemplateManager class to dictate the location of elements within a report. ReportTemplateManager is a static class that allows you to access five pre-determined ReportTemplates available for use with Pro. Use the GetTemplates method, or its asynchronous equivalent GetTemplatesAsync, to access them. Any one of these ReportTemplate choices can be passed as a parameter to ReportFactory.Instance.CreateReport.

The five templates available with Pro are:

  1. Attribute List: Generates a list of rows, with columns for the chosen attributes. This is the default if no grouping is defined.
  2. Attribute List with Grouping: Generates a list of rows, with columns for the chosen attributes, grouped by a unique field. This is the default if grouping is defined.
  3. Basic Summary: Generates a list of the specified summary statistics. No individual rows are listed.
  4. Basic Summary with Grouping: Generates a list of the specified summary statistics, grouped by a unique field. No individual rows are listed.
  5. Page Per Feature: Generates a separate page for each feature, listing the chosen attributes.
//Create report using the "Attribute List" ReportTemplate option.
var reportTemplate = ReportTemplateManager.GetTemplates().FirstOrDefault(rt => rt.Name == "Attribute List");
ReportFactory.Instance.CreateReport(
               ReportName, reportDataSource, reportCIMPage, reportFieldStats, reportTemplate, "Warm Tones");

Report Styling

With the Reports SDK, it is possible to designate the appearance properties of elements with one of four style options. Any one of these style options can be passed as a "string" to ReportFactory.Instance.CreateReport. The ReportStylingManager static class provides a GetStylings and a GetStylingsAsync method to access Pro's pre-determined styles. These are the four literal strings to use for the pre-determined styles:

  1. No Styling
  2. Black and White
  3. Cool Tones
  4. Warm Tones
//Creates a report with the "Warm Tones" styling option.
ReportFactory.Instance.CreateReport(
            ReportName, reportDataSource, reportCIMPage, reportFieldStats, reportTemplate, "Warm Tones");

Report Page

You can modify the report page's height, width, units, or margins using the CIMPage class. Pass in the configured CIMPage object as a parameter to ReportFactory.Instance.CreateReport:

//Create report using a custom CIMPage configuration.
var reportCIMPage = new CIMPage
{
  Units = LinearUnit.Inches,
  Height = 11,
  Width = 8.5,
  Margin = new CIMMargin { Bottom = 1, Top = 1, Left = .5, Right = .5},         
};
ReportFactory.Instance.CreateReport(ReportName, reportDataSource, reportCIMPage, reportFieldStats, 
                                                                    reportTemplate, "Black and White");

Summary Statistics

Summary Statistics that you can include in the report are:

  • Count: The count of all field values.
  • Minimum: The maximum field value.
  • Maximum: The minimum field value.
  • Range: The difference between the maximum and minimum field values.
  • Sum: The sum of all field values.
  • Mean: The average of all field values.
  • Median: The middle value of all field values.
  • Mode: The most common value of all field values.
  • StandardDeviation: The standard deviation of the field values.

ReportFactory.Instance.CreateReport method provides an overload for including summary statistics in your report. By default, summary statistics will be added to a ReportFooter or ReportGroupFooter section (depending on whether the summary statistics are being computed on a field that is grouped or not).

public Report CreateReport( 
   string name,
   ReportDataSource reportDataSource,
   CIMPage page,
   IEnumerable<ReportFieldStatistic> statistics,
   ReportTemplate template,
   string styling
)

The IEnumerable<ReportFieldStatistic> parameter controls the statistic to generate for a given field. For each field that you need to generate a summary statistic for, a corresponding ReportFieldStatistic item must be provided in the ReportFieldStatistic collection parameter. Use ReportFieldStatistic.Field to define the field name and ReportFieldStatistic.Statistic to define the type of summary statistic to display. Statistic an enum is of type FieldStatisticsFlag.

In the code snippet below, a summary statistic is being generated for the POP2000 field in a report on USA state information.

//Report field statistics
List<ReportFieldStatistic> reportFieldStats = new List<ReportFieldStatistic>{
	//Generate the total (sum) population statistics for the state in 2000
	new ReportFieldStatistic{ Field = "POP2000", Statistic = FieldStatisticsFlag.Sum }
};
//Set ReportDatasource object, style etc....
//Create report using the collection of ReportFieldStatistic
ReportFactory.Instance.CreateReport(ReportName, reportDataSource, null, reportFieldStats,
							reportTemplate, SelectedReportStyle);

To add summary statistics for a field to an existing report, use ReportElementFactory.Instance.CreateFieldStatisticTextElement. The parameters required for this method are:

  • A ReportFooter section of the report (see next section on report sections)
  • An envelope geometry that specifies the location at which to place statistic element on the report view
  • A ReportFieldStatistic object that defines the field and statistics info needed
  • A text symbol to be used to display the information on the report.
 var newReportFieldStatistics = new ReportFieldStatistic
{
  Field = "POP1990",
  Statistic = FieldStatisticsFlag.Maximum
};
//Get the ReportFooter
var mainReportSection = report.Elements.OfType<ReportSection>().FirstOrDefault();
var reportFooter = mainReportSection1?.Elements.OfType<ReportFooter>().FirstOrDefault();
//Create field statistics
var ge = ReportElementFactory.Instance.CreateFieldStatisticTextElement(reportFooter, 
					newFieldEnvelope, newReportFieldStatistics, textSymbol);

Report Sections

Reports are divided into sections and subsections. When created, a report has a single report section containing subsections. Each subsection identifies a particular area of the report section and helps provide structure. Common report subsections include Report Header, Report Footer, Page Header, and Page Footer.

All reports contain a main ReportSection which can be accessed via the Report.Elements property. Retrieve the first element of type "ReportSection":

 //Either
 ReportSection mainReportSection = report.Elements.FirstOrDefault() as ReportSection;
 //or
 ReportSection mainReportSection = report.Elements.OfType<ReportSection>().FirstOrDefault();

The ReportSection contains a collection of child sections including:

These five sections are available in the ReportSection by default. The ReportDetails section is where the attribute contents will be displayed.

UnGroupedReport

If the report is grouped on an attribute, the following two sections also exist in the report:

GroupedReport

Summary statistics for a report are added to either the ReportFooter or the ReportGroupFooter sections. See Sorting and Grouping data for how to group fields in a report and Summary Statistics for how to apply summary statistics.

 //Get the "ReportSection"
 //ReportSection contains the ReportHeader, ReportPageHeader, ReportDetails,
 //ReportPageFooter, ReportFooter sections.
 var mainReportSection = report.Elements.OfType<ReportSection>().FirstOrDefault();

 //Get the ReportHeader
 var reportHeader = mainReportSection?.Elements.OfType<ReportHeader>().FirstOrDefault();

 //Get the ReportHeader
 var reportPageHeader = mainReportSection?.Elements.OfType<ReportPageHeader>().FirstOrDefault();

 //Get the "ReportDetails" within the ReportSection. ReportDetails is where "fields" are.
 var reportDetailsSection = mainReportSection?.Elements.OfType<ReportDetails>().FirstOrDefault();

 //Get the ReportPageFooter
 var reportPageFooter = mainReportSection?.Elements.OfType<ReportPageFooter>().FirstOrDefault();

 //Get the ReportFooter
 var reportFooter = mainReportSection?.Elements.OfType<ReportFooter>().FirstOrDefault();

Create elements in a report section

After obtaining a reference to a report, it can be modified by adding new content elements such as fields and statistics. It is important to understand the structure of a report and the report sections so that content elements can be added to the appropriate section(s). Report elements can be static (such as title or column header text) or dynamic (such as field values and statistics, chart frames, dynamic pictures, or attachments). Dynamic elements update with each report record or groups of records.

Elements are created via the ReportElementFactory (a singleton). The elementContainer parameter on the various ReportElementFactory methods identifies the section within which a particular element will be created. In all cases, when constructing an element, an Envelope that specifies the location of the element on the report must be provided. The ReportElementFactory.Instance provides the following methods for element creation:

  • CreateAttachmentFrame: Creates an attachment frame element on a report from an envelope geometry. If the report data source contains attachments, add an AttachmentFrame to the ReportDetails section. Attachments are stored at the database level.
  • CreateChartFrame: Creates a chartFrame element on a report from an envelope geometry. If the report data source is a map member and a chart frame already exists for the layer, insert a ChartFrame into the Group Header, Group Footer, Report Header, or Report Footer.
  • CreateDynamicPictureGraphicElement: Creates a dynamic picture element on a report from an envelope geometry.
  • CreateFieldStatisticTextElement : Creates a field statistic dynamic text element on a report from an envelope geometry. Field statistics are added to summarize report records (Sum, Mean, Maximum, Count, etc) in the Group or Report Footer section.
  • CreateFieldValueTextElement: Creates a field value dynamic text element on a report from an envelope geometry. Field values are added to the Group Header, Group Footer, or Details section.
  • CreateRectangleParagraphGraphicElement: Creates a graphic rectangle text element on a layout from an envelope geometry. This method allows you to create static text elements to any section of a report. The value does not change as the report records change. In this example, a field will be added to the ReportDetails section:
 //Must be on QueuedTask

 //Creates a new field value text element within the ReportDetails section of a report.
 //Field to add
 var newReportField = new CIMReportField
	{
	  Name = "POP1990",
	};
 //Create a field element in the ReportDetails section
 //Get the "ReportSection"					
 var mainReportSection = report.Elements.OfType<ReportSection>().FirstOrDefault();
 if (mainReportSection == null) return;

 //Get the "ReportDetails" within the ReportSection. ReportDetails is where "fields" are.
 var reportDetailsSection = mainReportSection?.Elements.OfType<ReportDetails>().FirstOrDefault();
 if (reportDetailsSection == null) return;

 Envelope newFieldEnvelope = EnvelopeBuilder.CreateEnvelope(newMinPoint, newMaxPoint);

 //Create field
 var fieldGraphic = ReportElementFactory.Instance.CreateFieldValueTextElement(
                                      reportDetailsSection, newFieldEnvelope, newReportField);

Report element selection and navigation

The Report and ReportView class has several methods for managing report element selection:

Alternatively, you can access report elements through the ReportSection that they are contained in. You can access the ReportSection that contains the element and use the available methods to manipulate its element selection.

When either getting or setting the selection, a collection of one or more elements is used.

 if (ReportView.Active == null)
    return;
 var report = ReportView.Active.Report;

 //Get all elements in the active report.
 var elements = report.GetElementsAsFlattenedList();
 //Select these elements
 report.SelectElements(elements);

 //Clear the selection
 report.ClearElementSelection();

 //Find specific elements in the report based on their Name.
 var reportElementsToFind = new List<string> { "ReportText1", "ReportText2" };
 var textReportElements = report.FindElements(reportElementsToFind);
      
 //Delete elements
 await QueuedTask.Run(() => report.DeleteElements(textReportElements));

 // Find a field graphic in the ReportDetails section and zoom to it.
 //Get the "ReportSection"					
 var mainReportSection = report.Elements.OfType<ReportSection>().FirstOrDefault();
 if (mainReportSection == null) return;

 //Get the "ReportDetails" within the ReportSection. ReportDetails is where "fields" are.
 var reportDetailsSection = mainReportSection?.Elements.OfType<ReportDetails>().FirstOrDefault();
 if (reportDetailsSection == null) return;
   
 var elementsInReportDetails = reportDetailsSection.GetElementsAsFlattenedList();
 reportDetailsSection.SelectElements(elementsInReportDetails);

 //Zoom to selection
 await QueuedTask.Run(() => reportView.ZoomToSelectedElements());

Subreport

As previously mentioned, reports are divided into sections and subsections. You can add multiple report sections to a report; when this is done, each report section is called a subreport.

To add a subreport to an existing report use the AddSubReport method on the Report class. This method requires the following parameters:

  • The new report that is to be added. This should be an existing report in the project. This is the "subreport".
  • Position to add the subreport. If -1, the subreport is added to the end of the report. If 0, the subreport is added to the beginning of the report.
  • A boolean value to adjust the size of the subreport to match main report.
//Note: Call within QueuedTask.Run()
var mainReport = Project.Current.GetItems<ReportProjectItem>().FirstOrDefault(r => r.Name == "USAReports")?.GetReport();

if (mainReport == null) return;
//Add sub report
var vermontReportItem = Project.Current.GetItems<ReportProjectItem>().FirstOrDefault(r => r.Name == "Vermont");
if (vermontReportItem == null) return;
Report vermontReport = vermontReportItem.GetReport();
mainReport.AddSubReport(vermontReportItem, -1, true); //  If -1, the subreport is added to the end of the report.

Subreport datasource

When a report has multiple subreports, use the DataSources property on the Report class to retrieve the datasources for each subreport. This property is a IReadOnlyDictionary<string,ReportDataSource>. The Key is the string name of the report and the value points to the ReportDataSource for that report.

You can modify the datasources of specific subreports by using the SetDataSource property. In order to modify the datasource on a subreport, the new datasource should have the same schema as the existing datasource.

In the code snippet below, the DataSources property is used to retrieve the ReportDataSources for all the subreports. The specific subreport MyReport is then retrieved from the dictionary using the name of the report as the key (MyReport). We then set the datasource for the Report-Vermont using the SetDataSource method.

var dataSources = mainReport.DataSources;
var mainReportDatasource = dataSources["MyReport"]; //retrieve a specific datasource
//Set datasource
 mainReport.SetDataSource(newDataSource, "Report-Vermont"); //Schema has to match

Report View class

Report views are the primary interface used to display, navigate, select, and edit report elements in the report. The report being visualized in the view is accessed via the view's Report property (e.g. ReportView.Active.Report). Note that:

  • Multiple report views can reference the same report.
  • A report view may be open but may not be active.
  • The active view is not necessarily a report view.

Activate a Report View

Assuming a report view is open, but not active, iterate through the pane collection on the FrameWorkApplication class, isolate the report pane of interest, and then active it. To open a new view (either for an existing report or a newly created report) call FrameWorkApplication.Panes.CreateReportPaneAsync method. Pane activation must be called on the UI thread:

 //Assume we want to open a view for a particular report or activate a view if one
 //is already open
 ReportProjectItem reportItem = Project.Current.GetItems<ReportProjectItem>()
                                         .FirstOrDefault(item => item.Name.Equals("some report"));
 if (reportItem != null)
 {
   Report report = await QueuedTask.Run(() => reportItem.GetReport());
        
  //Next check to see if a report view is already open that references the report
  foreach (var pane in ProApp.Panes)
  {
    var reportPane = pane as IReportPane; 

    //if not a report view, continue to the next pane
    if (reportPane == null)  //if not a report view, continue to the next pane
      continue;
    
    //if there is a match, activate the view
    if (reportPane.ReportView.Report == report) 
    {
      (reportPane as Pane).Activate();//Must be called on the UI
      return;
    }
  }
  //No pane found, activate a new one
  ProApp.Panes.CreateReportPaneAsync(report);
}

Report Events

The ArcGIS.Desktop.Reports.Events namespace offers various selection and update events for reports. These events are listed in the table below.

Events Description
ReportAddedEvent Occurs when a Report is added to the project.
ReportDataSourceChangedEvent Occurs when a property of the ReportDataSource changes for a Report or ReportRelateSection.
ReportPropertyChangedEvent Occurs when a name or definition changes occur in a Report.
ReportRemovedEvent Occurs when a Report is removed.
ReportSectionChangedEvent Occurs when different types of sections are added, removed, or reordered in the Report.

Export a report

To export a report to a pdf format, use Report.ExportToPDF. This method requires four parameters:

  • The name of the output pdf file.
  • PDFFormat to specify the options for the generated PDF (including full path).
  • ReportExportOptions to define export options such as page numbering (see below).
  • A boolean parameter to specifying whether to use the current selected set of features.
 //On QueuedTask
 //var report = ...;

 //Create PDF format with appropriate settings
 var pdfFormat = new PDFFormat() {
    Resolution = 300,
    OutputFileName = Path.Combine(Project.Current.HomeFolderPath)
 };

 //Define Export Options
 var exportOptions = new ReportExportOptions {
   ExportPageOption = ExportPageOptions.ExportAllPages,
   TotalPageNumberOverride = 12,
   StartingPageNumberLabelOffset = 0
 };
 var useSelection = true;
 report.ExportToPDF(report.Name, pdfFormat, reportExportOptions, useSelection);

ReportExportOptions has the following options:

  • StartingPageNumberLabelOffset property allows you to customize the starting page number of the exported pages. The reason to customize the starting page number would be if the report PDF is going to be included in a larger report. For instance, if you needed to include a 3 page introduction to your report, the property would be set to 4. The first page of the exported report would start with a page number of 4 instead of 1.
  • TotalPageNumberOverride property will specify the total page number for the report, taking into account the other pages in your larger report.
  • ExportPageOption property allows you to specify the collection of report pages to be exported. Use the ExportPageOptions Enumeration to set the collection type.
ExportPageOptions Description
ExportAllPages Export all pages.
ExportByPageRange Export a custom page range.
ExportEvenPagesOnly Export even pages only.
ExportLastPage Export the last page only.
ExportOddPagesOnly Export odd pages only.
ExportSelectedIndexFeatures Export the selected index features.
ExportSelectedPage Export the selected page.
ExportSelectedTOCPages Export the selected TOC pages.
  • CustomPages property is used in-conjunction with ExportPageOption = ExportPageOptions.ExportByPageRange. Use a hypen "-" to delimit a page range and a comma-delimited list to include multiple pages. The two can be combined. For example, "1-3" would export pages 1-3. The value "1-3,5,9-11" would export pages 1-3, 5, and 9-11.

Related reports

Data sources with defined relates or relationship classes can be added to show additional information about your main report. A report can have multiple related reports. For example, assuming a report about US states, there could be related reports for US counties and US cities included as well. The Report.AddRelatedReport method supports adding a related report. Adding a related report is similar to creating a report, with parameters for the related report data source, field properties, template, and styling.

public void AddRelatedReport( 
   string relateName,
   string relateTitle,
   string insertSectionName,
   CIMReportDataSource reportDataSource,
   CIMReportElementFieldProperties[] statProperties,
   string templatePath,
   string styling
)

Supplemental pages

Supplemental pages provide additional information for the report including a table of contents, an acknowledgment and credits page, or a map. Supplemental pages are Layout views which must already exist in the project. Use Report.AddLayoutPage to insert a supplemental page below the main report section.

Note: Supplemental pages are represented as report sections. When these pages are added to a report, the view updates to show a Report Document view. This view shows a list of all report sections. Unlike the main report, supplemental page sections can be moved. Report.MoveReportSectionElement will move these sections to a new location in the report document.

Supplemental pages are also by-ref. Any updates made to the underlying layouts will be reflected in the final PDF export.

A complete working example

A complete working example of creating a report from a data source and then modifying it to include new attribute fields is provided in this sample: CreateReport

Report Options

Report options corresponding to the report options on the Pro options UI are available in the API via the static ApplicationOptions.ReportOptions property - refer to ProConcepts Content - ApplicationOptions for more information. The available options include:

//Gets and sets the application report options.
public class ReportOptions
{
  // Gets and sets the default path for the location of the custom template paths.
  public string ReportCustomTemplatePath { get; set; }
  // Gets and sets if all pages of the report are previewed.
  public bool PreviewAllPages { get; set; }
  // Gets and sets the number of preview pages in a report.
  public int NumberOfPreviewPages { get; set; }
}

Example:

  //toggle/switch option values
  var options = ApplicationOptions.ReportOptions;

  options.PreviewAllPages = false;
  options.NumberOfPreviewPages = 25;

  options.ReportCustomTemplatePath  = @"c:\temp";
⚠️ **GitHub.com Fallback** ⚠️