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:
The page has five server controls:
Add the following code:
To write code in Visual Basic
Visual Basic |
Copy Code
|
---|---|
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 |
To write code in C#
C# |
Copy Code
|
---|---|
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.
To write code in Visual Basic
Visual Basic |
Copy Code
|
---|---|
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 |
To write code in C#
C# |
Copy Code
|
---|---|
// 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 a RenderToFile, 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.
To write code in Visual Basic
Visual Basic |
Copy Code
|
---|---|
' 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 |
To write code in C#
C# |
Copy Code
|
---|---|
// get directories to use for loading and saving files private string GetDataPath() { return Request.PhysicalApplicationPath + @"Data\"; } private string GetOutputPath() { return Request.PhysicalApplicationPath + @"Temp\"; } |
The following screen shot shows what the result looks like in the browser: