In this article I will explain with an example, how to solve the problem of Print and Export Button of Toolbar not working with Crystal Report Viewer in SAP Crystal Reports in ASP.Net.
Note: The complete reference for the Crystal Reports is available at Crystal Report ASP.Net Example using DataSet or DataTable in C# VB.Net and Visual Studio 2010. Since here we are discussing a problem faced during export only relevant code has been shown.
 
 
The Problem
Crystal Report Viewer Control has option to Export Crystal Reports to different formats PDF, Excel File (XLS) and CSV.
[Solved] Crystal Report Viewer: Print and Export Button of Toolbar not working
 
Once you click the Export Button a dialog appears which allow you to select the format you want to export the report.
[Solved] Crystal Report Viewer: Print and Export Button of Toolbar not working
 
Once you click Export button you will get the following error message that stuns you.
[Solved] Crystal Report Viewer: Print and Export Button of Toolbar not working
 
 

The Cause
After investigating I managed to get to the root of the issue. Actually I placed a break point in the Page_Load event and found that the Crystal Report Viewer Control’s Export Button does a PostBack and if your code to bind the Crystal Report is written in Not IsPostBack condition then the Crystal Report is not set with a DataSource, thus leaving it empty with no data.
[Solved] Crystal Report Viewer: Print and Export Button of Toolbar not working
 
In simple words Crystal Report and Crystal Report Viewer Control both must be provided with DataSource and ReportSource respectively always whenever a call to server is made.
 
 
The Solution
I have two solutions you can go with whichever one as per your application design.
 
Solution 1: Move Crystal Report binding code out of Not IsPostBack condition
Move Crystal Report binding code out of Not IsPostBack condition so that Crystal Report and Crystal Report Viewer Control both are provided with DataSource and ReportSource respectively always.
C#
protected void Page_Load(object sender, EventArgs e)
{
    ReportDocument crystalReport = new ReportDocument();
    crystalReport.Load(Server.MapPath("~/CustomerReport.rpt"));
    Customers dsCustomers = GetData("select * from customers");
    crystalReport.SetDataSource(dsCustomers);
    CrystalReportViewer1.ReportSource = crystalReport;
}
 
private Customers GetData(string query)
{
    string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    SqlCommand cmd = new SqlCommand(query);
    using (SqlConnection con = new SqlConnection(conString))
    {
        using (SqlDataAdapter sda = new SqlDataAdapter())
        {
            cmd.Connection = con;
 
            sda.SelectCommand = cmd;
            using (Customers dsCustomers = new Customers())
            {
                sda.Fill(dsCustomers, "DataTable1");
                return dsCustomers;
            }
        }
    }
}
 
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim crystalReport As New ReportDocument()
    crystalReport.Load(Server.MapPath("~/CustomerReport.rpt"))
    Dim dsCustomers As Customers = GetData("select * from customers")
    crystalReport.SetDataSource(dsCustomers)
    CrystalReportViewer1.ReportSource = crystalReport
End Sub
 
Private Function GetData(query As String) As Customers
    Dim conString As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Dim cmd As New SqlCommand(query)
    Using con As New SqlConnection(conString)
        Using sda As New SqlDataAdapter()
            cmd.Connection = con
 
            sda.SelectCommand = cmd
            Using dsCustomers As New Customers()
                sda.Fill(dsCustomers, "DataTable1")
                Return dsCustomers
            End Using
        End Using
    End Using
End Function
 
 
Solution 2: Preserve Data using ViewState or Session during PostBack
The solution #2 makes use of ViewState variable to preserve the data fetched across PostBack so that there is no need to make calls to the database always.
The Customer records are fetched only once when the page loads for the first time into a DataSet which is then stored into the ViewState variable.
C#
protected void Page_Load(object sender, EventArgs e)
{
    Customers dsCustomers = null;
    if (!IsPostBack)
    {
        dsCustomers = GetData("select * from customers");
        ViewState["Customers_Data"] = dsCustomers;
    }
    ReportDocument crystalReport = new ReportDocument();
    crystalReport.Load(Server.MapPath("~/CustomerReport.rpt"));
    dsCustomers = (Customers)ViewState["Customers_Data"];
    CrystalReportViewer1.ReportSource = crystalReport;
    crystalReport.SetDataSource(dsCustomers);
}
 
private Customers GetData(string query)
{
    string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    SqlCommand cmd = new SqlCommand(query);
    using (SqlConnection con = new SqlConnection(conString))
    {
        using (SqlDataAdapter sda = new SqlDataAdapter())
        {
            cmd.Connection = con;
 
            sda.SelectCommand = cmd;
            using (Customers dsCustomers = new Customers())
            {
                sda.Fill(dsCustomers, "DataTable1");
                return dsCustomers;
            }
        }
    }
}
 
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim dsCustomers As Customers = Nothing
    If Not IsPostBack Then
        dsCustomers = GetData("select * from customers")
        ViewState("Customers_Data") = dsCustomers
    End If
    Dim crystalReport As New ReportDocument()
    crystalReport.Load(Server.MapPath("~/CustomerReport.rpt"))
    dsCustomers = DirectCast(ViewState("Customers_Data"), Customers)
    CrystalReportViewer1.ReportSource = crystalReport
    crystalReport.SetDataSource(dsCustomers)
End Sub
 
Private Function GetData(query As String) As Customers
    Dim conString As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Dim cmd As New SqlCommand(query)
    Using con As New SqlConnection(conString)
        Using sda As New SqlDataAdapter()
            cmd.Connection = con
 
            sda.SelectCommand = cmd
            Using dsCustomers As New Customers()
                sda.Fill(dsCustomers, "DataTable1")
                Return dsCustomers
            End Using
        End Using
    End Using
End Function
 
 
Screenshot
[Solved] Crystal Report Viewer: Print and Export Button of Toolbar not working
 
 
Demo
 
 
Downloads