Reports for WinForms | ComponentOne
Working with C1Report / Developing Reports for Web Scenarios / Dynamic Web Reports
In This Topic
    Dynamic Web Reports
    In This Topic

    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\WinForms Edition\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:

      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.

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

      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.

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

      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\";        
      }
      
    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: