ActiveReports is designed to run reports as quickly a possible, so generally reports are generated and displayed on the viewer in no time. Since there is no benchmark defined in regards to the length of a report, it could vary from a very small report to a very large report. When working with a very large report, the report generation may take a while; however the user has no option to check on the report progress. Well, though this is not integrated within the viewer itself, the amazing flexibility of ActiveReports allow us to hook it up with a Progress Bar and show the report generation progress. This blog article guides on how this functionality can be achieved with Section Based Reports and this is how our final output will look like: The Progress Bar at the top displays the current progress Once we are done with adding an ActiveReports file and the viewer control, we need to get a control which can show us the report generation progress. The Windows forms ProgressBar control is best suited for this purpose. In addition to this, we will also place a label control next to the ProgressBar which will display the percentage of the completed process and notify once the report is completely generated. The first thing we need to determine is the number of records in our report, so that we can use that value to set the Maximum for the ProgressBar. ActiveReports supports many types of datasources, so we will need to figure out the type of datasource being used and get the number of records accordingly. The code sample below creates a function "GetNoOfRecords" to calculate the number of records for some commonly used datasource types:

public int GetNoOfRecords(object ds)  
{  
    int noOfRecs = 0;  

    if (ds.GetType().ToString() == "GrapeCity.ActiveReports.Data.SqlDBDataSource")  
    {  
       GrapeCity.ActiveReports.Data.SqlDBDataSource ods = (GrapeCity.ActiveReports.Data.SqlDBDataSource)ds;  
       SqlConnection con = new SqlConnection(ods.ConnectionString);  
       SqlCommand com = new SqlCommand("Select count(*) as totalRecs from (" + ods.SQL + ")", con);  
       con.Open();  
       SqlDataReader sdr = com.ExecuteReader();  
       sdr.Read();  
       if (sdr.HasRows)  
       {  
          noOfRecs = Convert.ToInt32(sdr[0]);  
       }  
       con.Close();  
    }  
    else if (ds.GetType().ToString() == "GrapeCity.ActiveReports.Data.OleDBDataSource")  
    {  
       GrapeCity.ActiveReports.Data.OleDBDataSource ods = (GrapeCity.ActiveReports.Data.OleDBDataSource)ds;  
       OleDbConnection con = new OleDbConnection(ods.ConnectionString);  
       OleDbCommand com = new OleDbCommand("Select count(*) as totalRecs from (" + ods.SQL + ")", con);  
       con.Open();  
       OleDbDataReader odr = com.ExecuteReader();  
       odr.Read();  
       if (odr.HasRows)  
       {  
          noOfRecs = Convert.ToInt32(odr[0]);  
       }  
       con.Close();  
    }  
    else if (ds.GetType().ToString() == "GrapeCity.ActiveReports.Data.XMLDataSource")  
    {  
       GrapeCity.ActiveReports.Data.XMLDataSource xds = (GrapeCity.ActiveReports.Data.XMLDataSource)ds;  
       noOfRecs = xds.NodeList.Count;  
    }  
    else if (ds.GetType().ToString() == "System.Data.DataTable")  
    {  
       System.Data.DataTable dtds = (System.Data.DataTable)ds;  
       noOfRecs = dtds.Rows.Count;  
    }  
    else  
    {  
       GrapeCity.ActiveReports.Data.ListDataSource lds = (GrapeCity.ActiveReports.Data.ListDataSource)ds;  
       noOfRecs = lds.List.Count;  
    }  
    return noOfRecs;  
}

Once we have the number of records we will set its value as the maximum for the ProgressBar and run ActiveReports in a separate thread. Running the report in a separate thread allows the report to run in the background and allows us to check the report progress. We will define a variable "recordCount" whose value will be incremented in the FetchData event and will control the ProgressBar movement. The value will be periodically checked by a Timer. So the function to check the progress will look like:

private void CheckProgress(object sender, EventArgs e)  
{  
    if (progressBar1.Maximum > recordCount)  
    {  
       progressBar1.Value = recordCount;  
       label1.Text = ((int)((progressBar1.Value * 100) / progressBar1.Maximum)).ToString() + "%";  
    }  
    else  
    {  
       timer1.Enabled = true;  
       label1.Text = "Done!";  
       progressBar1.Value = progressBar1.Maximum;  
       StopTimer();  
    }  
}

The "label1" control in the code above is used to display the percentage progress made. Once the report generation completes, it shows a blinking text "Done!", marking the end of the process. The form containing the viewer also contains buttons to stop and restart the report generation. Sample applications in both C# and VB.NET can be downloaded from the links below: Download C# Sample Download VB.NET Sample