DEV Community

Cover image for How to Schedule and Automate C# .NET Reports
Chelsea Devereaux for MESCIUS inc.

Posted on • Originally published at developer.mescius.com

How to Schedule and Automate C# .NET Reports

What You Will Need

  • ActiveReports.NET
  • Visual Studio
  • SMTP server (optional)
  • Windows Task Scheduler (optional)

Tutorial Concept

Transform manual reporting tasks into an efficient, error-free process by leveraging ActiveReports.NET with C# .NET. This guide demonstrates how to schedule C# .NET reports and automate report generation, exporting, and distribution, providing timely insights to stakeholders seamlessly.


Section 1: Introduction

In today’s fast-paced development world, manual workflows can slow down reporting processes and lead to missed opportunities or delays in critical business insights. For development teams using .NET environments and ActiveReports.NET, automation presents a strategic advantage, allowing reports to be generated, scheduled, and distributed seamlessly. This blog explores best practices and techniques to help you implement automated report generation and distribution, improving your reporting workflow's efficiency and reliability.

Automating and scheduling

Why Automate Reporting?

Automated reporting offers several benefits:

  • Increased Efficiency: Automated workflows remove the need for repetitive manual tasks, freeing up time for more strategic work.
  • Enhanced Accuracy: Reducing manual steps helps eliminate human error, making report delivery more reliable.
  • Timely Insights: Scheduled reports ensure that stakeholders receive up-to-date data when needed, enabling faster and more informed decision-making.

By automating reporting processes with ActiveReports.NET, you gain better control over report timing, customization, and distribution while keeping manual intervention to a minimum.

What You'll Learn

This guide covers:

With these tools and techniques, you can automate your reporting processes and deliver timely, data-rich insights directly to stakeholders.

Required Tools and Libraries

To create and run the automated report solution, you’ll need the following:

1. ActiveReports.NET (The free trial is adequate for testing!)

  • ActiveReports.NET is the core reporting library for creating, rendering, and exporting reports in various formats like PDF, Excel, Word, and more.
  • Steps to add NuGet packages (covered in the guide sections).
    • Installation (optional): You can download and install ActiveReports.NET from the MESCIUS website.
  • If you are not a licensed customer, the free trial will suffice. Everything will work as expected, but exports will have watermarks.

2. Development Environment

  • Visual Studio: Visual Studio is the only officially supported IDE for ActiveReports.NET.
  • .NET SDK: Ensure that you have the appropriate .NET SDK installed (this guide assumes .NET 5 or later).

3. SMTP Access (optional)

  • To send reports via email, you’ll need access to an SMTP service, along with the credentials and port information.
  • If you’re testing locally, services like Mailtrap (free) or Gmail SMTP can be configured for development purposes.

4. Windows Task Scheduler (optional)

  • This guide will use Windows Task Scheduler, but you can easily use another task-scheduling solution to run applications and pass in arguments.

Section 2: How-To Guide - Simplified Automation Code

This section provides a streamlined guide using minimal code to demonstrate only the essential ActiveReports.NET API calls. We will cover how to load an RDLX report, set a parameter, render it as a PDF, and export it to a specified directory.

This example is ideal if you want to quickly understand how ActiveReports.NET can be used for basic report automation without additional features like command-line parsing or email integration.

You can also download our pre-built simplified report automation sample.

2.1 Essential Code Snippets

The code to perform a simple report load, parameter setting, rendering, and export process is as follows:

    using GrapeCity.ActiveReports;
    using GrapeCity.ActiveReports.Document;

    // Provide the RDLX report you want to render
    var reportName = "TestReport";
    var rptPath = new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Reports", $"{reportName}.rdlx"));
    var pageReport = new PageReport(rptPath);
    var runTime = new PageDocument(pageReport);
    Console.WriteLine("Loaded " + reportName);

    // Set the parameter value
    var parameterName = "SortBy";
    var parameterValue = "StockValue";

    runTime.Parameters[parameterName].CurrentValue = parameterValue;

    // Create an output directory
    var outputDirectory = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Exports"));
    outputDirectory.Create();

    // Provide settings for your rendering output
    var pdfSettings = new GrapeCity.ActiveReports.Export.Pdf.Page.Settings();

    // Set the rendering extension and render the report
    var pdfRenderingExtension = new GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension();

    var outputProvider = new GrapeCity.ActiveReports.Rendering.IO.FileStreamProvider(outputDirectory, Path.GetFileNameWithoutExtension(reportName))
    {
        // Overwrite output file if it already exists
        OverwriteOutputFile = true
    };

    pageReport.Document.Render(pdfRenderingExtension, outputProvider, pdfSettings);
    Console.WriteLine("Exported " + reportName);
Enter fullscreen mode Exit fullscreen mode

2.2 Key Code Sections Explained

1. Loading the Report

The report file (TestReport.rdlx) is loaded using PageReport. The runTime variable creates a PageDocument instance, which is required to render and export the report.

2. Setting the Parameter

In this example, we set a parameter named SortBy with the value StockValue. This allows you to control report filtering or sorting dynamically at runtime.

3. Creating an Output Directory

The code checks if the Exports folder exists, and if not, creates it. This is where the exported PDF will be saved.

4. Setting Rendering Options and Exporting the Report

  • We configure the pdfSettings and define pdfRenderingExtension to specify that the report should be rendered as a PDF.
  • FileStreamProvider handles the output file, saving it in the Exports folder with the report name (TestReport.pdf).
  • Finally, pageReport.Document.Render processes and saves the report in the chosen format.

2.3 How to Run the Code

  1. Save this code in a new console application.
  2. Ensure the Reports and Exports folders exist in the executable directory.
  3. Place a .rdlx report file named TestReport.rdlx in the Reports folder.
  4. Run the console application. It will load the report, set the parameter, render it, and export it as a PDF in the Exports folder.

That’s all you need to know to get started with creating your own report automation application! In the next section, we’ll dive deeper, covering how to expand this application with command-line argument parsing, multi-format exporting, and email integration.


Section 3: Comprehensive Guide - Fully Functional Report Automation Console Application

Input Output

Example Input/Output of Report Automation Sample Application

This section expands on the simplified example by breaking down a fully functional report automation console application. This version includes advanced features like command-line argument parsing, multi-format exporting, and email distribution. Each component of the application is broken down to help you understand how everything works together.

You can download the full, heavily commented, pre-built sample application to follow along.

If you decide to follow along and build it yourself, much of the code will be broken until everything is put in place (due to breaking it down for the sake of creating this guide), but everything will come together by the end!

3.1 Project Structure and Initial Setup

1. Create the Project

  • In Visual Studio, create a new Console Application project.

2. Create Resource Folders

  • To keep the project organized, open the project in File Explorer and add two specific folders: Reports and Exports.
  • In our project, we’ve configured the folder paths to exist in the same directory as the executable file so that after deployment, all of them will be in the same directory.
    • In our case, this directory is ReportAutomation\bin\Debug\net8.0.
    • Feel free to place them somewhere else—just remember to change the paths in the code as well!

3. Add NuGet Packages

Open the NuGet Package Manager and browse for the following ActiveReports.NET NuGet packages:

  • MESCIUS.ActiveReports
  • Any ActiveReports export dependencies that you wish to include, such as:
    • MESCIUS.ActiveReports.Export.Excel
    • MESCIUS.ActiveReports.Export.Html
    • MESCIUS.ActiveReports.Export.Pdf
    • MESCIUS.ActiveReports.Export.Word
    • MESCIUS.ActiveReports.Export.Excel

4. Add Using Statements

  • Add the System/.NET and ActiveReports.NET using statements to the beginning of Program.cs:
    using System.Text;
    using System.Net;
    using System.Net.Mail;
    using System.Collections.Specialized;
    using GrapeCity.ActiveReports;
    using GrapeCity.ActiveReports.Extensibility.Rendering;
Enter fullscreen mode Exit fullscreen mode

3.2 Defining the Workflow in the Main Method

The Main method is where everything comes together. It takes the command-line arguments, processes them, and uses each of the methods we’ll cover in the following sections to complete the report generation, export, and emailing tasks. This method acts as the control center for the application, handling the sequence of operations and checking for conditions (like email addresses) before proceeding with each step.

Below is the full Main method from Program.cs:

    static void Main(string[] args)
    {
        // Inject arguments for testing if no arguments are provided
        InjectTestArguments(ref args);

        // Extract the report name from the arguments
        string reportName = args[0];

        // Extract the report parameters and email addresses from the arguments
        var parameters = new Dictionary<string, object>();
        var emails = new List<string>();

        // Define default export type as PDF
        string exportType = "pdf";

        // Parse the arguments to extract parameters, emails, and export type
        ParseArguments(args, parameters, emails, ref exportType);

        // Set rendering extension and settings based on export file format defined in args
        IRenderingExtension renderingExtension;
        NameValueCollection settings;
        GetRenderingSettings(exportType, out renderingExtension, out settings);

        // Define the date and time of report rendering beforehand to ensure that the same time is used in all places
        var currentDateTime = DateTime.Now;

        // Define what the exported file will be called
        var exportFileName = reportName + " " + currentDateTime.ToString("yyyy-MM-dd HH.mm.ss");

        // Call method to process the report: load, set parameters, and export
        var (report, reportRunTime) = LoadReport(reportName);
        SetReportParameters(reportRunTime, parameters);
        CreateOutputDirectory();
        RenderAndExportReport(report, exportFileName, renderingExtension, settings);

        // Check if any emails were provided. If so, call the method to send out emails
        if (emails.Count > 0)
        {
            var exportedFilePath = Path.Combine(GetAppDirectory(), "Exports", exportFileName + "." + exportType.ToLower());
            EmailReport(reportName, exportedFilePath, currentDateTime, emails, parameters);
        }
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the Main Method

We will cover each of these in more detail with code examples in the following sections as we dive into the methods called by Main.

1. Inject Test Arguments

  • The InjectTestArguments method is called if no arguments are provided. This is useful for development and testing purposes, allowing the application to run with preset arguments instead of requiring input every time.
  • For production use, arguments would typically be supplied when executing the application, bypassing this function.

2. Extracting the Report Name

  • The first argument (args[0]) is always assumed to be the report name. This name is used to locate the report file in the Reports directory.
  • The report name also serves as the basis for the export file name, making it easy to identify exports.

3. Initializing Parameters and Email Lists

  • parameters and emails dictionaries are initialized to hold parsed command-line arguments for report parameters and email addresses.

4. Setting Default Export Type

  • The exportType variable is initialized to "pdf" as the default format. If the format argument is supplied, this value will be overwritten in the next step.

5. Parsing Arguments

  • The ParseArguments method processes args, updating parameters, emails, and exportType based on the provided values.
  • After parsing, the application has all the details it needs to configure the report, including specific parameters, the export format, and email recipients.

6. Defining Rendering Extension and Settings

  • Based on the exportType, the GetRenderingSettings method sets the appropriate renderingExtension and settings. These determine how the report is rendered (PDF, Excel, CSV, etc.).

7. Setting the Export File Name with a Timestamp

  • currentDateTime is captured before rendering to ensure consistency in timestamps.
  • exportFileName combines the report name and date-time stamp, helping prevent overwrites and aiding version tracking.

8. Loading the Report

  • The LoadReport method loads the specified .rdlx file and returns both the PageReport instance (report definition) and PageDocument (runtime instance).
  • These instances are needed to configure the report with dynamic parameters and export it.

9. Setting Parameters

  • SetReportParameters applies any parsed parameters to the report. This step customizes the report’s data, filtering, or sorting based on the user’s input.

10. Creating the Output Directory

  • The CreateOutputDirectory method ensures that the Exports folder exists, so the export can be saved without errors.

11. Rendering and Exporting the Report

  • RenderAndExportReport handles the actual rendering and saving of the report, using the configured renderingExtension, settings, and exportFileName.
  • This step completes the report generation and saves the output to the Exports directory.

12. Sending the Exported Report via Email

  • After exporting, the method checks if any email addresses were provided.
  • If there are recipients in the emails list, EmailReport is called to send the exported file to each address.
  • exportedFilePath is constructed to specify the exact location of the exported report file, which is attached to the email.

3.3 Command-Line Argument Parsing

Our application will accept arguments for various report settings, making it flexible and easy to integrate with other systems. These command-line arguments let users specify:

  • The report name to load
  • Report parameters
  • Email addresses for report distribution
  • The export format (PDF, Excel, etc.)

The code for parsing command-line arguments, as seen in the Program.cs file, is as follows:

    static void ParseArguments(string[] args, Dictionary<string, object> parameters, List<string> emails, ref string exportType)
    {
        for (int i = 1; i < args.Length; i++)
        {
            // Isolate emails from arguments
            if (args[i].StartsWith("email:", StringComparison.OrdinalIgnoreCase))
            {
                // Add email addresses
                var email = args[i].Substring("email:".Length);
                emails.Add(email);
            }
            // Isolate export format from arguments
            else if (args[i].StartsWith("format:", StringComparison.OrdinalIgnoreCase))
            {
                // Set export format type
                exportType = args[i].Substring("format:".Length);
            }
            else
            {
                // Process as parameter in the form "ParameterName=Value1,Value2"
                var paramParts = args[i].Split('=');
                if (paramParts.Length == 2)
                {
                    var paramName = paramParts[0];
                    var paramValue = paramParts[1];

                    // Check for multi-value parameter (comma-separated)
                    if (paramValue.Contains(','))
                    {
                        parameters[paramName] = paramValue.Split(','); // Store as array for multi-value
                    }
                    else
                    {
                        parameters[paramName] = paramValue; // Store as single value
                    }
                }
                else
                {
                    Console.WriteLine($"Invalid parameter format: {args[i]}");
                }
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of Argument Parsing Code

1. Extracting Emails

Each argument that starts with "email:" is identified as an email address. The application strips the "email:" prefix and adds the email address to a list of recipient addresses.

2. Determining Export Format

The "format:" prefix is used to specify the export type (e.g., PDF, Excel, CSV). If this argument is present, the application sets the exportType variable to the specified format.

3. Setting Report Parameters

Other arguments, structured as ParameterName=Value, are assumed to be report parameters. If a parameter contains multiple values separated by commas (e.g., Categories=Beverages,Seafood), it’s stored as an array. Single values are stored as strings.

4. Error Handling

If an argument isn’t in the expected format, the application logs a warning to indicate that it couldn’t parse the argument correctly.

Example of Command-Line Usage

Below is an example of how to pass command-line arguments to the application:

    ReportAutomation.exe TestReport Categories=Beverages,Seafood SortBy=StockValue email:example@example.com format:pdf
Enter fullscreen mode Exit fullscreen mode

In this example:

  • TestReport: Specifies the report name.
  • Categories=Beverages,Seafood: Sets the Categories parameter with multiple values.
  • SortBy=StockValue: Sets the SortBy parameter to StockValue.
  • email:example@example.com: Adds an email address to the recipient list.
  • format:pdf: Sets the export format to PDF.

This flexible argument parsing enables users to customize each report generation without modifying the code, making the application adaptable to various workflows and easy to integrate with existing task scheduling tools.


3.4 Loading the Report and Setting Parameters

Once the application parses the command-line arguments, the next step is to load the specified report and set any provided parameters. This section focuses on handling the report file and configuring it with dynamic parameters to customize the data presented in each export.

Loading the Report

The application loads the report using the PageReport and PageDocument classes from ActiveReports.NET. This setup allows the application to handle .rdlx report definition files and render them in various formats.

    static (PageReport report, GrapeCity.ActiveReports.Document.PageDocument reportRunTime) LoadReport(string reportName)
    {
        Console.WriteLine(reportName);
        // Provide the Page report you want to render.
        var reportPath = new FileInfo(Path.Combine(GetAppDirectory(), "Reports", $"{reportName}.rdlx"));
        var report = new PageReport(reportPath);
        var reportRunTime = new PageDocument(report);
        Console.WriteLine(" - Loaded");
        return (report, reportRunTime);
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the LoadReport Method

1. Report Path Construction

  • The report’s path is generated by combining the base directory with the Reports folder and the report file name (e.g., TestReport.rdlx).
  • This allows the application to load different reports based on the reportName argument passed.

2. PageReport and PageDocument Instances

  • PageReport loads the .rdlx file, while PageDocument provides a runtime instance that enables rendering.
  • This setup is essential for loading, rendering, and exporting the report.

3. Return Values

  • The method returns a tuple with the PageReport and PageDocument instances, making them accessible for rendering and setting parameters in subsequent steps.

Setting Report Parameters

Once the report is loaded, the application can configure parameters that control the report's filtering, sorting, or data customization. The SetReportParameters method takes the parameters dictionary (parsed from the command line) and applies these to the report.

    static void SetReportParameters(GrapeCity.ActiveReports.Document.PageDocument reportRunTime, Dictionary<string, object> parameters)
    {
        // Set parameters in the report
        foreach (var param in parameters)
        {
            if (reportRunTime.Parameters.Contains(param.Key))
            {
                var parameter = reportRunTime.Parameters[param.Key];

                // Check if the parameter value is a string[] (multi-value) or a single value
                if (param.Value is string[] multiValueArray)
                {
                    // Set multi-value parameter
                    parameter.CurrentValue = multiValueArray;
                }
                else if (param.Value is string singleValue)
                {
                    // Set single-value parameter
                    parameter.CurrentValue = singleValue;
                }
                else
                {
                    Console.WriteLine($"Parameter '{param.Key}' not found in the report.");
                }
            }
            else
            {
                Console.WriteLine($"Parameter '{param.Key}' not found in the report.");
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the SetReportParameters Method

1. Iterating Over Parameters

  • The method iterates through each key-value pair in the parameters dictionary. Each entry represents a report parameter specified via the command line.

2. Checking for Valid Parameters

  • For each parameter, the application checks if it exists in the report (reportRunTime.Parameters.Contains(param.Key)). If it does, it retrieves the corresponding parameter object.

3. Handling Multi-Value Parameters

  • If the parameter’s value is an array (e.g., Categories=Beverages,Seafood), it’s treated as a multi-value parameter. This enables filtering or sorting based on multiple criteria.

4. Setting Single-Value Parameters

  • If the parameter’s value is a single string, it’s assigned directly to CurrentValue of the report parameter. This supports simple, single-value filtering (e.g., SortBy=StockValue).

5. Error Messages for Missing Parameters

  • If a parameter specified in the command-line arguments is not found in the report definition, the application logs a message to the console. This helps identify issues with incorrect or outdated parameter names.

Example Scenario

Suppose you want to generate a report with the following parameters:

    Categories=Beverages,Seafood SortBy=StockValue
Enter fullscreen mode Exit fullscreen mode

The application will:

  • Find the Categories parameter in the report and set it with multiple values: Beverages and Seafood.
  • Locate the SortBy parameter and set it to StockValue.

3.5 Defining Export Formats and Rendering the Report

In this section, we’ll define how the application handles multiple export formats. ActiveReports.NET supports a variety of formats (PDF, Excel, Word, etc.), and this flexibility is essential for generating reports that meet different requirements.

The GetRenderingSettings method in the code configures the rendering settings based on the specified format. This function selects the appropriate ActiveReports.NET rendering extension and applies custom settings as needed.

Supported Export Formats

The application can export reports in the following formats:

  • PDF (pdf)
  • Excel (xlsx)
  • CSV (csv)
  • Word (docx)
  • HTML (MHT) (mht)
  • JSON (json)

Setting the Rendering Extension and Settings

Below is the code for configuring the rendering extension and settings based on the selected export format:

    static void GetRenderingSettings(string exportType, out IRenderingExtension renderingExtension, out NameValueCollection settings)
    {
        var exportTypeLower = exportType.ToLower();
        switch (exportTypeLower)
        {
            case "pdf":
                // Use PDF rendering extension and settings
                renderingExtension = new GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension();
                settings = new GrapeCity.ActiveReports.Export.Pdf.Page.Settings();
                break;
            case "xlsx":
                // Use Excel rendering extension and settings
                renderingExtension = new GrapeCity.ActiveReports.Export.Excel.Page.ExcelRenderingExtension();
                var excelSettings = new GrapeCity.ActiveReports.Export.Excel.Page.ExcelRenderingExtensionSettings()
                {
                    FileFormat = GrapeCity.ActiveReports.Export.Excel.Page.FileFormat.Xlsx
                };
                settings = excelSettings.GetSettings();
                break;
            case "csv":
                // Use CSV rendering extension and settings
                settings = new GrapeCity.ActiveReports.Export.Text.Page.CsvRenderingExtension.Settings()
                {
                    ColumnsDelimiter = ",",
                    RowsDelimiter = "\r\n",
                    QuotationSymbol = '"',
                    Encoding = Encoding.UTF8
                };
                renderingExtension = new GrapeCity.ActiveReports.Export.Text.Page.CsvRenderingExtension();
                break;
            case "docx":
                // Use Word rendering extension and settings
                renderingExtension = new GrapeCity.ActiveReports.Export.Word.Page.WordRenderingExtension();
                settings = new GrapeCity.ActiveReports.Export.Word.Page.Settings() { FileFormat = GrapeCity.ActiveReports.Export.Word.Page.FileFormat.OOXML };
                break;
            case "mht":
                // Use HTML rendering extension with MHT settings
                renderingExtension = new GrapeCity.ActiveReports.Export.Html.Page.HtmlRenderingExtension();
                settings = new GrapeCity.ActiveReports.Export.Html.Page.Settings() { MhtOutput = true, OutputTOC = true, Fragment = false };
                break;
            case "json":
                // Use JSON rendering extension and settings
                settings = new GrapeCity.ActiveReports.Export.Text.Page.JsonRenderingExtension.Settings() { Formatted = true };
                renderingExtension = new GrapeCity.ActiveReports.Export.Text.Page.JsonRenderingExtension();
                break;
            default:
                // Default to PDF rendering extension and settings if none of the above cases are satisfied
                renderingExtension = new GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension();
                settings = new GrapeCity.ActiveReports.Export.Pdf.Page.Settings();
                break;
        }
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the GetRenderingSettings Method

1. Handling Different Formats

  • Each case in the switch statement corresponds to a different export format.
  • Based on the value of exportType, the application selects the correct rendering extension and settings.

2. Rendering Extensions and Settings

  • Each format has a unique RenderingExtension class (e.g., PdfRenderingExtension, ExcelRenderingExtension) and settings.
  • The settings allow for additional customization, such as defining delimiters for CSV, setting encoding for JSON, or specifying the file format for Excel.

3. Default Format

  • If an unsupported or unspecified format is provided, the application defaults to PDF.

Rendering and Exporting the Report

Once the appropriate rendering extension and settings are configured, the application can proceed to render and export the report. The RenderAndExportReport method performs this task by combining the rendering extension, settings, and output file provider.

    static void RenderAndExportReport(PageReport report, string exportFileName, IRenderingExtension renderingExtension, NameValueCollection settings)
    {
        // Configure the output provider to handle the exported file
        var outputDirectory = new DirectoryInfo(Path.Combine(GetAppDirectory(), "Exports"));
        var outputProvider = new FileStreamProvider(outputDirectory, Path.GetFileName(exportFileName))
        {
            // Overwrite output file if it already exists
            OverwriteOutputFile = true
        };

        // Render the report and export it to the specified format
        report.Document.Render(renderingExtension, outputProvider, settings);
        Console.WriteLine(" - Exported");
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the RenderAndExportReport Method

1. Output Directory and FileStreamProvider

  • The FileStreamProvider is set up to store the exported file in the Exports folder.
  • The OverwriteOutputFile property ensures that if an existing file has the same name, it will be replaced with the new export.

2. Rendering and Exporting

  • report.Document.Render takes the configured renderingExtension, outputProvider, and settings and generates the output file in the specified format.
  • A confirmation message is logged to indicate that the export was successful.

Example of Specifying Export Formats

When running the application, you can specify the format using the format argument. For example, setting the format to PDF:

    ReportAutomation.exe TestReport format:pdf
Enter fullscreen mode Exit fullscreen mode

3.6 Exporting the Report

Exports folder

Exports Dumped to Exports Folder

Once the rendering settings are configured, the application proceeds to export the rendered report. This section focuses on setting up the output directory, defining the export file name, and saving the exported report in the correct location.

Creating the Output Directory

The application uses the CreateOutputDirectory method to ensure that the designated export folder exists. If the folder doesn’t exist, the method creates it automatically. This setup keeps exports organized and centralized.

    static void CreateOutputDirectory()
    {
        var outputDirectory = new DirectoryInfo(Path.Combine(GetAppDirectory(), "Exports"));
        outputDirectory.Create();
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the CreateOutputDirectory Method

  • Directory Path
    • The output directory is created inside the application’s base directory under a folder named Exports.
    • This directory structure makes it easy to locate exported files, as all exports are saved in a consistent location.
  • Folder Creation
    • If the Exports folder already exists, nothing changes; otherwise, it creates the folder.

File Naming and Storage

The application constructs a unique file name for each export using the report name and current date-time. This ensures that each export file is timestamped and easy to identify.

    var currentDateTime = DateTime.Now;
    var exportFileName = reportName + " " + currentDateTime.ToString("yyyy-MM-dd HH.mm.ss");
Enter fullscreen mode Exit fullscreen mode
  • Date-Time Stamp
    • Including the date and time in the filename (formatted as yyyy-MM-dd HH.mm.ss) ensures uniqueness, preventing accidental overwrites of previous exports.
    • This also helps with version tracking, as each exported file reflects the exact time it was generated.

Full Export Code

The RenderAndExportReport method, covered in Section 3.4, handles the actual export process, saving the rendered report file in the Exports directory with the appropriate format and name.


3.7 Emailing the Report

TestReport

Test Email Received in Mailtrap.io

After exporting the report, the application can send the exported file to specified recipients via email. This is done using the EmailReport method, which uses SMTP to send an email with the report attached.

Setting Up SMTP for Email

To send reports by email, you need access to an SMTP server, along with credentials, server address, and port. For this example, we’ll use placeholders that you should replace with your own SMTP server details. The code is as follows:

    static void EmailReport(string reportName, string exportedFilePath, DateTime currentDateTime, List<string> emails, Dictionary<string, object> parameters)
    {
        // Build the email body with report details
        var emailBody = new StringBuilder();
        emailBody.AppendLine("Report: " + reportName);
        emailBody.AppendLine("Executed at: " + currentDateTime.ToString());

        if (parameters.Count > 0)
        {
            emailBody.AppendLine("Parameters:");

            foreach (var param in parameters)
            {
                if (param.Value is string[])
                {
                    emailBody.AppendLine($" - {param.Key}: {string.Join(", ", (string[])param.Value)}");
                }
                else
                {
                    emailBody.AppendLine($" - {param.Key}: {param.Value}");
                }
            }
        }

        // Provide information and credentials for SMTP
        using (var smtpClient = new SmtpClient("smtp.yoursmp.com") // Set your SMTP server
        {
            Port = 587,
            Credentials = new NetworkCredential("YourUsername", "YourPassword"), // Set your credentials
            EnableSsl = true
        })
        {
            foreach (var email in emails)
            {
                using (var mailMessage = new MailMessage("yoursender@email.com", email) // Set your sender address
                {
                    Subject = reportName + " - " + currentDateTime.ToString(),
                    Body = emailBody.ToString(),
                })
                {
                    // Try to send the email
                    try
                    {
                        Console.WriteLine(" - sending to " + email);
                        mailMessage.Attachments.Add(new Attachment(exportedFilePath));
                        smtpClient.Send(mailMessage);
                        Console.WriteLine(" - " + reportName + " sent to " + email);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(" - Error: " + e.Message);
                    }
                }
            }
        }
        // Preview email content in console
        Console.WriteLine("");
        Console.WriteLine("-------------------------------");
        Console.WriteLine("");
        Console.WriteLine("Email Content:");
        Console.WriteLine("");
        Console.WriteLine("Subject:");
        Console.WriteLine(reportName + " - " + currentDateTime.ToString());
        Console.WriteLine("");
        Console.WriteLine("Body:");
        Console.WriteLine(emailBody);
    }
Enter fullscreen mode Exit fullscreen mode

Explanation of the EmailReport Method

1. Constructing the Email Body

  • The StringBuilder object (emailBody) contains information about the report, including its name, execution date-time, and any parameters used during generation.
  • Each parameter is formatted as a list item, allowing recipients to review the report’s context easily.

2. SMTP Client Configuration

  • The SmtpClient is configured with the server address (sandbox.smtp.mailtrap.io), port (587), and credentials.
  • Note: Replace the SMTP server and credentials with your own settings before deploying.

3. Creating and Sending the Email

  • For each email in the emails list, the application creates a MailMessage object and attaches the exported report file.
  • The email subject includes the report name and execution date-time for easy identification.
  • Each email is sent individually within a try-catch block. If an error occurs during sending, it’s logged to the console.

4. Console Preview of Email Content

  • A preview of the email content (subject and body) is printed to the console for debugging purposes. This can help ensure that the email content is correct before deployment.

Testing and Using the Email Feature

To test the email feature, run the application with the email argument, specifying one or more recipient addresses:

    ReportAutomation.exe TestReport email:example1@example.com email:example2@example.com
Enter fullscreen mode Exit fullscreen mode

This command:

  • Exports TestReport and emails it to both example1@example.com and example2@example.com.
  • Ensures that each email contains the report, parameters, and other details as specified in the body.

Section 4: Integrating With a Task Scheduling Application to Schedule Reports

Automating your report generation workflow can save time and ensure that reports are generated and sent out at regular intervals. This sample application was designed to be compatible with almost any task scheduling solution, but for our example, we will use Windows Task Scheduler as it is easily available to anyone using Windows.

Windows Task Scheduler is a powerful tool for scheduling applications to run automatically on a recurring basis. By integrating your report automation application with Task Scheduler, you can schedule tasks to run daily, weekly, monthly, or at custom intervals.

This section provides step-by-step instructions for setting up a scheduled task to execute your report automation application.

4.1 Configuring Task Scheduler

Task Scheduler

Creating a Task

1. Open Windows Task Scheduler

  • Press Win + S, type “Task Scheduler,” and press Enter to open the Windows Task Scheduler.

2. Create a New Task

  • In the Task Scheduler window, select Action > Create Task.
  • Give your task a meaningful Name (e.g., “Monthly Sales Report”) and Description.
    • Note: You can also create Folders in Task Scheduler, which we recommend if you plan to ultimately have several report automation tasks to facilitate easier tracking of them.

3. Setting Task Security Options

  • Under the General tab, select the Run whether user is logged on or not option to ensure the task runs in the background, even if the user is logged out.
  • Optionally, select Run with highest privileges if your application requires elevated permissions.

4.2 Setting the Trigger

Trigger

Setting a Trigger

The Trigger defines when and how frequently the task runs. You can set this based on your report distribution needs (e.g., daily, weekly, monthly).

1. Add a Trigger

  • Go to the Triggers tab and click New.
  • Set the Begin the task dropdown to On a schedule.

2. Define the Schedule

  • Choose Daily, Weekly, or Monthly based on your requirements.
  • For example, if you want to generate a report daily at 8:00 a.m., select Daily, then set the Start time to 8:00 a.m.
  • Customize the recurrence interval as needed.

3. Optional: Add Multiple Triggers

  • If you need the task to run at different times, you can add multiple triggers.

4.3 Configuring the Action

Action

Configure the Action

1. Define the Action

  • Go to the Actions tab and click New.
  • In the Action dropdown, select Start a program.

2. Specify the Program Path

  • In the Program/script field, enter the path to your report automation executable (e.g., C:\path\\to\ReportAutomation.exe).
  • You can find this path by right-clicking the application in Windows Explorer, selecting Properties, and copying the Target path.

3. Add Arguments

  • In the Add arguments (optional) field, specify any arguments required for the report. This includes:
    • The report name
    • Any parameters or sorting options
    • The export format
    • Email addresses if you want the report to be emailed automatically

For example:

    TestReport Categories=Beverages,Seafood SortBy=StockValue email:example1@example.com format:pdf
Enter fullscreen mode Exit fullscreen mode

This example will run the task to:

  • Generate TestReport
  • Filter by Categories (Beverages, Seafood) and sort by StockValue
  • Export it as a PDF
  • Email it to example1@example.com

Example of a Complete Command with Arguments

If the executable is located in C:\ReportAutomation\ReportAutomation.exe, and you want to generate a report named SalesReport and export it as an Excel file every Friday at 5:00 p.m., the setup in Task Scheduler would look like this:

  • Program/script: C:\ReportAutomation\ReportAutomation.exe
  • Arguments: SalesReport format:xlsx email:stakeholder@example.com

4.4 Testing and Troubleshooting the Scheduled Task

1. Run the Task Manually

  • After configuring the task, you can test it by selecting the task in Task Scheduler and clicking Run in the Actions pane.
  • This lets you verify that the task works as expected and allows you to troubleshoot any issues before scheduling it for production.

2. Checking Task History and Logs

  • Go to the History tab to view task logs. Task Scheduler logs each execution attempt, along with any errors or warnings.
  • Review the logs if the task fails to run or does not perform as expected.

3. Common Issues and Solutions

  • File Path Issues: Ensure the executable path and arguments are correct. Incorrect paths are a common cause of failure.
  • Permission Issues: If the task requires elevated permissions, ensure Run with highest privileges is selected.
  • Network or SMTP Issues: If emailing fails, check SMTP settings, firewall settings, and internet connectivity.

4. Enable Logging in the Application (Optional)

  • You can add logging to your application (e.g., by writing to a log file) to capture details about each execution, which can help with troubleshooting any unexpected behavior.

By configuring Windows Task Scheduler with these steps, you’ll have a fully automated report generation and distribution system. The Task Scheduler will run the application on the specified schedule, generating the report, exporting it, and optionally emailing it to stakeholders.

This setup completes the automation loop, allowing your reports to be generated and distributed on a recurring basis without any manual intervention.


Conclusion

In this guide, we’ve walked through the process of creating a fully automated report generation and distribution system using ActiveReports.NET and Windows Task Scheduler. With the solution we’ve built, you can:

  • Automate Report Generation: Run reports on a set schedule, ensuring that stakeholders receive timely insights without any manual effort.
  • Customize Reports with Parameters: Use dynamic parameters to tailor each report based on user input, giving you control over data filtering, sorting, and presentation.
  • Export to Multiple Formats: Export reports in PDF, Excel, Word, CSV, and more to meet different reporting needs and preferences.
  • Email Reports to Stakeholders: Automatically email exported reports to specified recipients, making report distribution seamless and efficient.

Key Benefits of Report Automation

Automating reports saves time, minimizes errors, and ensures consistency in data reporting. Whether you’re generating daily operational reports, monthly financial summaries, or customized client reports, automation lets you focus on analysis and decision-making rather than repetitive tasks.

Further Customization

The solution presented in this blog is just the foundation of what’s possible with ActiveReports.NET. Below are a few ideas for expanding its capabilities:

  • Add More Export Formats: Explore ActiveReports.NET’s range of formats and choose those that best fit your needs.
  • Advanced Scheduling: Use Task Scheduler’s options for more complex scheduling scenarios, such as conditional execution based on specific events.
  • Enhanced Logging and Error Handling: Implement robust logging to monitor each run of the automation application and capture details about export times, email success or failures, and any issues encountered.
  • Integrate with Other Applications: Consider integrating this solution with other applications or services, such as a CRM or data visualization tools, to further streamline reporting workflows.

Final Thoughts

Automated reporting is a powerful way to make sure that accurate and up-to-date information reaches the right people at the right time. With the flexibility of ActiveReports.NET and the scheduling power of Windows Task Scheduler, this solution is adaptable to a wide range of business needs. By following this guide, you can build a custom report automation solution tailored to your unique workflow.

Feel free to explore more features of ActiveReports.NET, experiment with additional report customization options, and adjust this solution to best suit your organization’s needs.

Happy automating!

Top comments (0)