Crystal Reports Online Training

Learn Online, Anytime, Anywhere

Step-by-step online tutorials.

15.08 Modifying the Grouping and Sorting Objects

Programming the Grouping and Sorting Objects

The sorting and grouping objects in a report can be modified during runtime. You can use a form to have the user enter criteria to modify the default properties of a report and your program can change the report to meet these criteria. Modifying the objects during runtime is very powerful, but it requires you to understand what the limitations are.

Just like you learned at the beginning of the chapter, you can’t add new report objects to the report. Secondly, only certain properties can be modified. The properties with a + can be modified and the ones with a – are read-only.

The SortField class controls how the fields are sorted. You can modify the SortDirection property to set whether it is ascending or descending. Listing 15-13 shows how to modify the SortDirection property.

Although the Groups collection appears to give you complete access to the group objects, it is missing the sort direction. You can’t use the Groups collection exclusively and find out the whether the group is being sorted ascending or descending. You have to use the SortFields collection to modify a group’s sort order.

Listing 15-13. Changing the sort direction of a field
[VB.NET]
Private Sub btnModifySorting_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnModifySorting.Click
Dim myReport As New CrystalReport1()
Dim crSortFields As CrystalDecisions.CrystalReports.Engine.SortFields
Dim crSortField As CrystalDecisions.CrystalReports.Engine.SortField
'Modify the sort order of the OrderDate field to be Descending
'Access the fields by traversing the sort fields collection
crSortFields = myReport.DataDefinition.SortFields
For Each crSortField In crSortFields
If crSortField.Field.Name = "Order Date" Then
'There are two differnt sorts with this field name.
'Make sure its a record sort
If crSortField.SortType = _
CrystalDecisions.[Shared].SortFieldType.RecordSortField Then
crSortField.SortDirection = _
CrystalDecisions.[Shared].SortDirection.DescendingOrder
End If
End If
Next
CrystalReportViewer1.ReportSource = myReport
End Sub
[C#]
private void btnModifySorting_Click(object sender, System.EventArgs e)
{
CrystalReport1 myReport = new CrystalReport1();
//Modify the order of the OrderDate field to Descending
//Reference the fields by traversing the sort fields collection
foreach(CrystalDecisions.CrystalReports.Engine.SortField mySortField in
myReport.DataDefinition.SortFields)
{
if (mySortField.Field.Name == "Last Name")
{
//There are two different sort objects with this name
//Make sure its a record sort.
if (mySortField.SortType ==
CrystalDecisions.Shared.SortFieldType.RecordSortField)
{
mySortField.SortDirection =
CrystalDecisions.Shared.SortDirection.DescendingOrder;
}
}
crystalReportViewer1.ReportSource = myReport;
}
}

This example uses a form with a button on it which changes the sorting order of the report used in the last example. When the user clicks on the button, it loads the report into the object variable myReport. The SortFields collection is traversed looking for the SortField with a name property of “Order Date”. In this example report, there are two fields with this name. This is because the group section is based upon the order date’s month, and within the group the individual records are sorted by the day of the order date.

Once it matches the name of the field, it has to check if this is the field for the group section or the individual record. When it is certain that it has the object for the individual record, it changes the sort order to descending. Once this is finished, the report object is assigned to the viewer. If you wanted to modify the sort order for the group section, you would do it here, but instead you would check if the field is of type GroupSortField. The report output is shown in Figure 15-11.



Figure 15-11. Report output after modifying the sort order.

Both the SortField class and Group class have a property that lets you modify the field they are based on. It is called Field in the Sort class and called ConditionField in the Group class. Both are of the type FieldDefinition. To modify this property, you have to set it to a reference of an existing field object. Thus, the field must already exist somewhere on the report. This field could be a field from one of the report tables or a formula field. Listing 15-14 demonstrates how to change the field by modifying the group object. This code works the same way for modifying a sort field.

Listing 15-14. Modifying a group’s field
[VB.NET]
Private Sub btnModifyGrouping_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnModifyGrouping.Click
Dim myReport As New CrystalReport1()
Dim crGroups As CrystalDecisions.CrystalReports.Engine.Groups
Dim crGroup As CrystalDecisions.CrystalReports.Engine.Group
Dim crField As CrystalDecisions.CrystalReports.Engine.DatabaseFieldDefinition
'Modify the group to use CustomerName rather than OrderDate
'Get the field to base the group on
crField = myReport.Database.Tables("Customer").Fields("Customer Name")
'Access the group by traversing the groups collection
crGroups = myReport.DataDefinition.Groups
For Each crGroup In crGroups
If crGroup.ConditionField.Name = "Order Date" Then
crGroup.ConditionField = crField
End If
Next
CrystalReportViewer1.ReportSource = myReport
End Sub
[C#]
private void btnModifyGrouping_Click(object sender, System.EventArgs e)
{
CrystalReport1 myReport = new CrystalReport1();
CrystalDecisions.CrystalReports.Engine.DatabaseFieldDefinition myField;
//Modify the group to use CustomerName rather than Orderdate
//Get the field to base the group on
myField = myReport.Database.Tables["Employee"].Fields["First Name"];
//Reference the group by traversing the Groups collection
foreach(CrystalDecisions.CrystalReports.Engine.Group myGroup in myReport.DataDefinition.Groups)
{
if (myGroup.ConditionField.Name == "Last Name")
{
myGroup.ConditionField = myField;
}
}
crystalReportViewer1.ReportSource = myReport;
}

This example uses another button on the same form as the last example and it also modifies the original report example. It changes the group from being based on Order Date to using the Customer Name field.

It first uses the Tables collection to get a reference to the Customer Name field from the Customers table. It loops through the Groups collection to find the correct Group object. The field is changed by setting the ConditionField to the field object variable. Once this is finished, the report object is assigned to the viewer and the viewer is refreshed. The output is shown in Figure 15-12.



Figure 15-12. Report output after modifying the group field.