ActiveReports objects and controls are completely accessible at run time. You can modify the properties of any of the report sections or controls to produce a dynamic report. The section Format event allows you to modify the properties of the section and its controls, including height, visibility, and other visual properties. The Format event is the only event in which you can modify the printable area of a section. Once this event has run, any changes to the section's height are not reflected in the report output. This walkthrough illustrates how to create a report layout at run time based on user input.
Note: Add controls dynamically in the ReportStart event. Otherwise, results may be unpredictable. For more information on events, see the Sequence of Events topic. |
This walkthrough is split up into the following activities:
Tip: For basic steps like adding a report to a Visual Studio project and viewing a report, please see the Basic Data Bound Reports walkthrough. |
To complete the walkthrough, you must have access to the Northwind database.
A copy is located at C:\Program Files\GrapeCity\ActiveReports 6\Data\NWIND.MDB (on a 64-bit Windows operating system, a copy is located in C:\Program Files (x86)\GrapeCity\ActiveReports 6\Data\NWIND.MDB).
When you have completed this walkthrough, you will have an application that looks similar to the following.
Form controls
Control | Location | Dock Property | Name | Text |
---|---|---|---|---|
Panel | Windows Form | Left | Panel1 | |
Label | Panel1 | Top | lblSelectFields | Select Fields for Your Report |
Checked ListBox | Panel1 | Fill | clbFields | |
Button | Panel1 | Bottom | btnGenRep | Generate Report |
CheckBox | Panel1 | Bottom | chkGroup | Group By Category ID |
Viewer | Windows Form | Fill | Viewer1 |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste INSIDE the class declaration of the report. |
Copy Code |
---|---|
Private m_arrayFields As ArrayList Private m_useGroups As Boolean 'Create an array to hold the fields selected by the user Public WriteOnly Property FieldsList() As ArrayList Set(ByVal Value As ArrayList) m_arrayFields = Value End Set End Property 'Create a property to hold the user's grouping choice Public WriteOnly Property UseGroups() As Boolean Set(ByVal Value As Boolean) m_useGroups = False m_useGroups = Value End Set End Property Private m_defaultHeight As Single = 0.2F Private m_defaultWidth As Single = 4.0F Private m_currentY As Single = 0.0F 'Set up report formatting and add fields based on user choices Private Sub constructReport() Try Me.Detail1.CanGrow = True Me.Detail1.CanShrink = True Me.Detail1.KeepTogether = True If m_useGroups = True Then 'If the user wants grouping, add a group header and footer and set the grouping field Me.Sections.InsertGroupHF() CType(Me.Sections("GroupHeader1"), GroupHeader).DataField = "CategoryID" Me.Sections("GroupHeader1").BackColor = System.Drawing.Color.Gray Me.Sections("GroupHeader1").CanGrow = True Me.Sections("GroupHeader1").CanShrink = True CType(Me.Sections("GroupHeader1"), GroupHeader).RepeatStyle = RepeatStyle.OnPageIncludeNoDetail 'Add a textbox to display the group's category ID Dim txt As New TextBox txt.DataField = "CategoryID" txt.Location = New System.Drawing.PointF(0.0F, 0) txt.Width = 2.0F txt.Height = 0.3F txt.Style = "font-weight: bold; font-size: 16pt" Me.Sections("GroupHeader1").Controls.Add(txt) End If Dim i As Integer For i = 0 To m_arrayFields.Count - 1 'For all fields selected by the user (except CategoryID) create a label and a textbox If m_arrayFields(i).ToString <> "CategoryID" Then Dim lbl As New Label 'Set the label to display the name of the selected field lbl.Text = m_arrayFields(i) + ":" 'Set the location of each label '(m_currentY gets the height of each control added on each iteration) lbl.Location() = New System.Drawing.PointF(0.0F, m_currentY) lbl.Width = 0.9F lbl.Height = m_defaultHeight Me.Detail1.Controls.Add(lbl) Dim txt As New TextBox 'Set the textbox to display data txt.DataField = m_arrayFields(i) 'Set the location of the textbox txt.Location = New System.Drawing.PointF(1.0F, m_currentY) txt.Width = m_defaultWidth txt.Height = m_defaultHeight Me.Detail1.Controls.Add(txt) 'Set the textbox to use currency formatting if the field is UnitPrice If m_arrayFields(i) = "UnitPrice" Then txt.OutputFormat = "$#.00" End If 'Increment the vertical location by adding the height of the added controls m_currentY = m_currentY + m_defaultHeight End If Next Catch ex As Exception System.Windows.Forms.MessageBox.Show("Error in Report-constructReport: " + ex.Message, "Project Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error) End Try End Sub |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste INSIDE the class declaration of the report. |
Copy Code |
---|---|
private ArrayList m_arrayFields; //Create an array to hold the fields selected by the user public ArrayList FieldsList { set{m_arrayFields = value;} } private bool m_useGroups = false; //Create a property to hold the user's grouping choice public bool UseGroups { set{m_useGroups = value;} } float m_defaultHeight = .2f; float m_defaultWidth = 4f; float m_currentY = 0f; //Set up report formatting and add fields based on user choices private void constructReport() { try { this.detail.CanGrow = true; this.detail.CanShrink = true; this.detail.KeepTogether = true; if(m_useGroups) { //If the user wants grouping, add a group header and footer and set the grouping field this.Sections.InsertGroupHF(); ((GroupHeader)this.Sections["GroupHeader1"]).DataField = "CategoryID"; this.Sections["GroupHeader1"].BackColor = System.Drawing.Color.Gray; this.Sections["GroupHeader1"].CanGrow = true; this.Sections["GroupHeader1"].CanShrink = true; ((GroupHeader)this.Sections["GroupHeader1"]).RepeatStyle = RepeatStyle.OnPageIncludeNoDetail; this.Sections["GroupFooter1"].Height = 0; //Add a textbox to display the group's category ID TextBox txt = new TextBox(); txt.DataField = "CategoryID"; txt.Location = new System.Drawing.PointF(0f,0); txt.Width =2f; txt.Height = .3f; txt.Style = "font-weight: bold; font-size: 16pt;"; this.Sections["GroupHeader1"].Controls.Add(txt); } for(int i=0;i<m_arrayFields.Count;i++) { if(!m_useGroups || (m_useGroups && m_arrayFields[i].ToString() != "CategoryID")) //'For all fields selected by the user (except CategoryID) create a label and a textbox { Label lbl = new Label(); //Set the label to display the name of the selected field lbl.Text = m_arrayFields[i].ToString() + ":"; //Set the location of each label //(m_currentY gets the height of each control added on each iteration) lbl.Location = new System.Drawing.PointF(0f,m_currentY); lbl.Width =.9f; lbl.Height = m_defaultHeight; this.detail.Controls.Add(lbl); TextBox txt = new TextBox(); //Set the textbox to display data txt.DataField = m_arrayFields[i].ToString(); //Set the location of the textbox txt.Location = new System.Drawing.PointF(1f,m_currentY); txt.Width = m_defaultWidth; txt.Height = m_defaultHeight; this.detail.Controls.Add(txt); //Set the textbox to use currency formatting if the field is UnitPrice if (m_arrayFields[i].ToString().Equals("UnitPrice")) { txt.OutputFormat = "$#.00"; } //Increment the vertical location by adding the height of the added controls m_currentY = m_currentY + m_defaultHeight; } } } catch(Exception ex) { System.Windows.Forms.MessageBox.Show("Error in Report-constructReport: " + ex.Message,"Project Error",System.Windows.Forms.MessageBoxButtons.OK,System.Windows.Forms.MessageBoxIcon.Error); } } |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste INSIDE the class declaration of the form. |
Copy Code |
---|---|
Dim i As Integer Dim c As Integer Dim m_arrayField As New ArrayList() Private Sub fillCheckBox() For i = 0 To Me.NwindDataSet1.Tables.Count - 1 For c = 0 To Me.NwindDataSet1.Tables(i).Columns.Count - 1 Me.clbFields.Items.Add(Me.NwindDataSet1.Tables(i).Columns(c).ColumnName) Next Next End Sub Private Sub launchReport() Dim rpt As New rptRunTime() Dim dataAdapter As New NWINDDataSetTableAdapters.ProductsTableAdapter Try rpt.FieldsList = m_arrayField rpt.UseGroups = chkGroup.Checked dataAdapter.Fill(NwindDataSet1.Products) rpt.DataSource = Me.NwindDataSet1.Products Viewer1.Document = rpt.Document rpt.Run() Catch ex As Exception System.Windows.Forms.MessageBox.Show(Me, "Error in launchReport: " + ex.Message, "Project Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste INSIDE the class declaration of the form. |
Copy Code |
---|---|
ArrayList m_arrayField = new ArrayList(); private void fillCheckBox() { for(int i = 0; i < this.nwindDataSet1.Tables.Count; i++) { for(int c = 0; c < this.nwindDataSet1.Tables[i].Columns.Count; c++) { this.clbFields.Items.Add(this.nwindDataSet1.Tables[i].Columns[c].ColumnName); } } } private void launchReport() { try { rptRunTime rpt = new rptRunTime(); rpt.FieldsList = m_arrayField; rpt.UseGroups = chkGroup.Checked; NWINDDataSetTableAdapters.ProductsTableAdapter dataAdapter = new NWINDDataSetTableAdapters.ProductsTableAdapter(); dataAdapter.Fill(this.nwindDataSet1.Products); rpt.DataSource = this.nwindDataSet1.Products; this.Viewer1.Document = rpt.Document; rpt.Run(); } catch(Exception ex) { MessageBox.Show(this,"Error in launchReport: " + ex.Message,"Project Error",MessageBoxButtons.OK,MessageBoxIcon.Error); } } |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste JUST ABOVE the Detail Format event. |
Copy Code |
---|---|
Dim m_count As Integer |
Visual Basic.NET code. Paste INSIDE the Detail Format event. |
Copy Code |
---|---|
If m_count Mod 2 = 0 Then Me.Detail1.BackColor = System.Drawing.Color.SlateGray Else Me.Detail1.BackColor = System.Drawing.Color.Gainsboro End If m_count = m_count + 1 |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste JUST ABOVE the Detail Format event. |
Copy Code |
---|---|
int m_count; |
C# code. Paste INSIDE the Detail Format event. |
Copy Code |
---|---|
if(m_count % 2 == 0) { this.detail.BackColor = System.Drawing.Color.SlateGray; } else { this.detail.BackColor = System.Drawing.Color.Gainsboro; } m_count++; |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste INSIDE the ReportStart event. |
Copy Code |
---|---|
constructReport() |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste INSIDE the ReportStart event. |
Copy Code |
---|---|
constructReport(); |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste INSIDE the button click event. |
Copy Code |
---|---|
Me.m_arrayField.Clear() For i = 0 To Me.clbFields.CheckedItems.Count - 1 m_arrayField.Add(Me.clbFields.CheckedItems(i).ToString) Next launchReport() |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste INSIDE the button click event. |
Copy Code |
---|---|
this.m_arrayField.Clear(); for(int i = 0; i < this.clbFields.CheckedItems.Count; i++) { m_arrayField.Add(this.clbFields.CheckedItems[i].ToString()); } launchReport(); |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste INSIDE the SelectedIndexChanged event. |
Copy Code |
---|---|
If Me.clbFields.CheckedItems.Count < 0 Then Me.btnGenRep.Enabled = False Else Me.btnGenRep.Enabled = True End If |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste INSIDE the SelectedIndexChanged event. |
Copy Code |
---|---|
if(this.clbFields.CheckedItems.Count>0) { this.btnGenRep.Enabled = true; } else { this.btnGenRep.Enabled = false; } |
To write the code in Visual Basic.NET
The following example shows what the code for the method looks like.
Visual Basic.NET code. Paste INSIDE the Form Load event. |
Copy Code |
---|---|
Try fillCheckBox() Catch ex As Exception System.Windows.Forms.MessageBox.Show(Me, "Error in Form1_Load: " + ex.Message, "Project Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try |
To write the code in C#
The following example shows what the code for the method looks like.
C# code. Paste INSIDE the Form Load event. |
Copy Code |
---|---|
try { fillCheckBox(); } catch(Exception ex) { MessageBox.Show(this,"Error in Form1_Load: " + ex.Message,"Project Error", MessageBoxButtons.OK,MessageBoxIcon.Error); } |