ComponentOne Reports for WinForms Designer Edition: ComponentOne Reports for WinForms > Working with C1Report > Developing Reports for Web Scenarios > Dynamic Web Reports

Dynamic Web Reports

Dynamic Web reports are created on-demand, possibly based on data supplied by the user. This type of solution typically involves using an ASP.NET page that presents a form to the user and collects the information needed to create the report, then creates a C1Report component to render the report into a temporary file, and returns a reference to that file.

The example that follows is a simple ASP.NET page that allows users to enter some information and to select the type of report they want. Based on this, the ASP code creates a custom version of the NorthWind "Employee Sales by Country" report and presents it to the user in the selected format.

The sample uses a temporary file on the server to store the report. In a real application, you would have to generate unique file names and delete them after a certain time, to avoid overwriting reports before the users get a chance to see them. Despite this, the sample illustrates the main techniques involved in delivering reports over the Web with C1Report.

To implement this type of application, follow these steps:

1.   Start by creating a new Web application with a Web page that looks like this:

 

 

The page has five server controls:

      _1stYear: Contains a list of valid years for which there is data (1994, 1995, and 1996). Note that you can add the items by clicking the smart tag () and selecting Edit Items from the menu. From the ListItem Collection Editor, add three new items.

      _txtGoal: Contains the yearly sales goal for each employee.

      _btnHTML, _btnPDF: Buttons used to render the report into HTML or PDF, and show the result.

      _lblStatus: Displays error information if something goes wrong.

Note: If you run this application with a demo or beta version of the C1Report component, there will be errors when the control tries to display its About dialog box on the server. If that happens, simply reload the page and the problem should go away.

2.   After the page has been set up, you need to add a reference to the C1Report component to the project. Just right-click the project in the Solution Explorer window, select Add Reference and choose the C1Report component.

3.   Add the Nwind.xml to the project in the Data folder. Just right-click the project in the Solution Explorer window, select New Folder and rename the folder Data. Then right-click the folder, select Add Existing Item and browse for the Nwind.xml definition file, which is installed by default in the ComponentOne Samples\C1Report\C1Report\VB\NorthWind\Data directory in the Documents or My Documents folder.

4.   Add a Temp folder to the project. Just right-click the project in the Solution Explorer window, select New Folder and rename the folder Temp.

5.   If you have used traditional ASP, this is where things start to become interesting. Double-clicking the controls will take you to a code window where you can write full-fledged code to handle the events, using the same editor and environment you use to write Windows Forms projects.

Add the following code:

      Visual Basic

Imports C1.C1Report

' handle user clicks

Private Sub _btnHTML_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles _btnHTML.Click

     RenderReport(FileFormatEnum.HTMLDrillDown)

End Sub

 

Private Sub _btnPDF_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles _btnPDF.Click

     RenderReport(FileFormatEnum.PDF)

End Sub

      C#

using C1.C1Report;

// handle user clicks

private void _btnHTML_Click(object sender, System.EventArgs e)

{

   RenderReport(FileFormatEnum.HTMLDrillDown);

}

private void _btnPDF_Click(object sender, System.EventArgs e)

{

   RenderReport(FileFormatEnum.PDF);

}

This is the code that gets executed on the server, when the user clicks either button.

6.   The following code delegates the work to the main routine, RenderReport:

      Visual Basic

Private Sub RenderReport(ByVal fmt As FileFormatEnum)

 

    ' build file names

    Dim rpt As String = "Employee Sales by Country"

    Dim fileIn As String = GetDataPath() & "NWind.xml"

    Dim ext As String = Iif(fmt = FileFormatEnum.PDF, ".pdf", ".htm")

    Dim fileOut As String = GetOutputPath() & rpt & ext

 

    Try

        ' create C1Report component

        Dim c1r As New C1Report()

 

        ' load the report

        c1r.Load(fileIn, rpt)

 

        ' get user parameters

        Dim year As String = _lstYear.SelectedItem.Text

        Dim goal As String = _txtGoal.Text

 

        ' customize the report data source

        Dim sSQL As String = "SELECT DISTINCTROW " & _

            "Employees.Country, Employees.LastName, " & _

            "Employees.FirstName, Orders.ShippedDate, Orders.OrderID, " & _

            "  [Order Subtotals].Subtotal AS SaleAmount " & _

            "FROM Employees INNER JOIN (Orders INNER JOIN " & _

            "  [Order Subtotals] ON Orders.OrderID = " & _

            "  [Order Subtotals].OrderID) " & _

            "  ON Employees.EmployeeID = Orders.EmployeeID " & _

            "WHERE Year(Orders.ShippedDate) = " & year & ";"

        c1r.DataSource.RecordSource = sSQL

 

        ' customize the report's event handlers

        Dim sScript As String = _

            "If SalespersonTotal > " & goal & " Then" & vbCrLf & _

            "  ExceededGoalLabel.Visible = True" & vbCrLf & _

            "  SalespersonLine.Visible = True" & vbCrLf & _

            "Else" & vbCrLf & _

            "  ExceededGoalLabel.Visible = False" & vbCrLf & _

            "  SalespersonLine.Visible = False" & vbCrLf & _

            "End If"

        c1r.Sections(SectionTypeEnum.GroupHeader2).OnPrint = sScript

 

        ' render the report into a temporary file

        c1r.RenderToFile(fileOut, fmt)

 

        ' redirect user to report file

        Response.Redirect("Temp/" + rpt + ext)

 

    Catch x As Exception

 

        _lblStatus.Text = "*** " & x.Message

 

    End Try

End Sub

      C#

// render the report

private void RenderReport(FileFormatEnum fmt)

{

   // build file names

   string rpt  = "Employee Sales by Country";

   string fileIn = GetDataPath() + "NWind.xml";

   string ext = (fmt == FileFormatEnum.PDF)? ".pdf": ".htm";

   string fileOut = GetOutputPath() + rpt + ext;

 

   try

   {

   // create C1Report component

   C1Report c1r = new C1Report();

 

   // load the report

   c1r.Load(fileIn, rpt);

 

   // get user parameters

   string year = _lstYear.SelectedItem.Text;

   string goal = _txtGoal.Text;

 

   // customize the report data source

   string sSQL = "SELECT DISTINCTROW " +

   "Employees.Country, Employees.LastName, " +

   "Employees.FirstName, Orders.ShippedDate, Orders.OrderID, " +

   "  [Order Subtotals].Subtotal AS SaleAmount " +

   "FROM Employees INNER JOIN (Orders INNER JOIN " +

   "  [Order Subtotals] ON Orders.OrderID = " +

   "  [Order Subtotals].OrderID) " +

   "  ON Employees.EmployeeID = Orders.EmployeeID " +

   "WHERE Year(Orders.ShippedDate) = " + year + ";";

   c1r.DataSource.RecordSource = sSQL;

 

   // customize the report's event handlers

   string sScript =

   "If SalespersonTotal > " + goal + " Then \n" +

   "  ExceededGoalLabel.Visible = True\n" +

   "  SalespersonLine.Visible = True\n" +

   "Else\n" +

   "  ExceededGoalLabel.Visible = False\n" +

   "  SalespersonLine.Visible = False\n" +

   "End If";

   c1r.Sections[SectionTypeEnum.GroupHeader2].OnPrint = sScript;

 

   // render the report into a temporary file

   c1r.RenderToFile(fileOut, fmt);

   // redirect user to report file

   Response.Redirect("Temp/" + rpt + ext);

   }

   catch (Exception x)

   {

   _lblStatus.Text = "*** " + x.Message;

   }

}

The RenderReport routine is long, but pretty simple. It begins working out the names of the input and output files. All file names are built relative to the current application directory.

Next, the routine creates a C1Report component and loads the "Employee Sales by Country" report. This is the raw report, which you will customize in the next step.

The parameters entered by the user are available in the _lstYear and _txtGoal server-side controls. The code reads these values and uses them to customize the report's RecordSource property and to build a VBScript handler for the OnPrint property. These techniques were discussed in previous sections.

Once the report definition is ready, the code calls the RenderToFile method, which causes the C1Report component to write HTML or PDF files to the output directory. When the method returns, the report is ready to be displayed to the user.

The last step is the call to Response.Redirect, which displays the report you just created on the user's browser.

Note that the whole code is enclosed in a try/catch block. If anything goes wrong while the report is being generated, the user gets to see a message explaining the problem.

7.   Finally, there's a couple of simple helper routines that need to be added:

      Visual Basic

' get directories to use for loading and saving files

Private Function GetDataPath() As String

   Return Request.PhysicalApplicationPath + "Data\"

End Function

 

Private Function GetOutputPath() As String

   Return Request.PhysicalApplicationPath + "Temp\"

End Function

      C#

// get directories to use for loading and saving files

private string GetDataPath()

{

   return Request.PhysicalApplicationPath + @"Data\";

}

private string GetOutputPath()

{

   return Request.PhysicalApplicationPath + @"Temp\";

}

8.   After you enter this code, the application is ready. You can press F5 and trace its execution within Visual Studio.

The following screen shot shows what the result looks like in the browser:

 


Send comments about this topic to ComponentOne.
Copyright © ComponentOne LLC. All rights reserved.