Use Case - Expense Report

This demo shows a master-detail report use case with a business object as the data source. The template contains master data (the purpose of the expense report, dates), employee information and the expenses in form of a table (detail information).

This example is part the Sample Explorer project which includes all samples in one. The sources for this sample project can be found here:

Language Project Location
C# %USERPROFILE%\Documents\TX Text Control 24.0.NET Server for ASP.NET\Samples\ASP.NET\CSharp\Sample Explorer\
VB.NET %USERPROFILE%\Documents\TX Text Control 24.0.NET Server for ASP.NET\Samples\ASP.NET\VB.NET\Sample Explorer\

You will find the source code and the ASPX page of this sample in the Solution structure tree under: Reporting\expenses.aspx

Example description

Simply Select a report from the GridView and click on Create report to start the merge process.

An expense report contains general data such as the purpose of the expense, the pay period and a statement number. Additionally, it should list the employee details and finally, the expenses itself. The class diagram of the business object is illustrated below:

The business object Expenses has some useful features. It contains XML Serialization attributes which allows us to use an XML data source that is deserialized into the business object automatically.

[C#]
[XmlType("expenses", IncludeInSchema = true)] 
public class Expenses : List<Expense> 
{ 
    [XmlElement("expense")] 
    public List<Expense> expenses { get; set; } 
} 

//...
[Visual Basic]
<XmlType("expenses", IncludeInSchema := True)> _
Public Class Expenses
	Inherits List(Of Expense)
	<XmlElement("expense")> _
	Public Property expenses() As List(Of Expense)
		Get
			Return m_expenses
		End Get
		Set
			m_expenses = Value
		End Set
	End Property
	Private m_expenses As List(Of Expense)
End Class
'...

The attributes define which XML element is mapped to which member of the object. An XmlSerializer is used to deserialize the XML in order to create a new instance of the business object.

[C#]
XmlSerializer serializer = new XmlSerializer(typeof(Expenses)); 
Expenses expenses = (Expenses)serializer.Deserialize( 
    new StreamReader("expense_report_data.xml"));
[Visual Basic]
Dim serializer As New XmlSerializer(GetType(Expenses))
Dim expenses As Expenses = DirectCast(serializer.Deserialize( _
	New StreamReader("expense_report_data.xml")), Expenses)

Additionally, we don't need to store all values in our XML file (or database in real life applications). The business object contains the logic and the code to calculate specific field values internally. All inverted members in the above illustration are not imported from the XML, but calculated on the fly in the business object itself.

The following code shows how the Total value is calculated based on existing values:

[C#]
public double Total 
{ 
    get 
    { 
        double dTotal = 0; 

        foreach (LineItem item in this.LineItems) 
        { 
            dTotal += item.line_total; 
        } 

        return dTotal - this.Advances; 
    } 
}
[Visual Basic]
Public ReadOnly Property Total() As Double
	Get
		Dim dTotal As Double = 0

		For Each item As LineItem In Me.LineItems
			dTotal += item.line_total
		Next

		Return dTotal - Me.Advances
	End Get
End Property

In order to start the merge process itself, only 1 line of code is required:

[C#]
mailMerge1.MergeObjects(expenses);
[Visual Basic]
mailMerge1.MergeObjects(expenses)

Text Control's Reporting engine MailMerge is mapping the merge fields to the business object members and related objects automatically.