Invoice

This example demonstrates how to generate an invoice from the database.

Pdf is mostly used when creating an invoice

Using a sample database we design this pdf

We set margins , colors , logo , fonts, tables

We choose a sample customer data bases on customer id in database

Clicking generate will generate pre designed invoice

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;

using OfficeComponent.Pdf;
using OfficeComponent.Pdf.Graphics;
using System.Data;
using OfficeComponent.Pdf.Tables;

namespace OfficeComponent.Samples
{
    class InvoiceExample : ExampleBase
    {
        public int OrderId { get; set; }

        public InvoiceExample(string commonDataPath, string outputDir)
            : base(commonDataPath, outputDir)
        {

        }

        public InvoiceExample(string commonDataPath, string outputDir, string xmlFile) : base(commonDataPath, outputDir, xmlFile)
        {

        }

        public override string Execute()
        {
#if WEB
            OrderId = 1000;
#endif

            string shipName, address, shipCity, shipCountry;
            DateTime shippedDate;
            Double total, ftotal;

            Order order = GetOrder(OrderId);
            shipName = order.ShipName;
            address = order.ShipAddress;
            shipCity = order.ShipCity;
            shipCountry = order.ShipCountry;
            shippedDate = order.ShippedDate;
            total = order.Total;
        

            int oid = OrderId;

            // Create a new instance of PdfDocument class.
            PdfDocument doc = new PdfDocument();

            doc.PageSettings.Margins.All = 5;

            //Add a page
            PdfPage page = doc.Pages.Add();
            PdfGraphics g = page.Graphics;
            RectangleF rect = new RectangleF(0, 0, page.Graphics.ClientSize.Width, 100);

            //Draw gradient rectangle at the the top and bottom of the page
            PdfLinearGradientBrush lgBrush = new PdfLinearGradientBrush(new PointF(page.Graphics.ClientSize.Width, 0), new PointF(page.Graphics.ClientSize.Width, 100), Color.FromArgb(218, 229, 245), Color.White);
            PdfBrush brush = new PdfSolidBrush(Color.Black);

            PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 25);
            g.DrawRectangle(lgBrush, rect);

            lgBrush = new PdfLinearGradientBrush(new PointF(0, page.Graphics.ClientSize.Height), new PointF(0, page.Graphics.ClientSize.Height - 120), Color.FromArgb(218, 229, 245), Color.White);
            rect = new RectangleF(0, page.Graphics.ClientSize.Height - 120, page.Graphics.ClientSize.Width, 120);
            g.DrawRectangle(lgBrush, rect);

            //Add image
            PdfImage image = new PdfBitmap(CommonDataPath + "\\logo.gif");
            g.DrawImage(image, new PointF(10, 20), new SizeF(354f * 0.7f, 35f * 0.7f));

            g.DrawString("INVOICE", font, brush, 425, 20);

            // Get the product table details
            DataTable shipTable = GetShipDetails(oid);

            Font f = new Font("Trebuchet MS", 10);
            font = new PdfTrueTypeFont(f);

            
            // Display the "bill to" and "ship to" address
            g.DrawString("Invoice ID:   " + oid.ToString(), font, brush, new PointF(325, 116));
            g.DrawString("Shipped Date: " + shippedDate, font, brush, new PointF(325, 130));

            g.DrawString("Northwind Traders\n67,rue des Cinquante Otages,\nElgin,\nUnites States.", font, brush, new RectangleF(10, 116, 200, 200));
            float xpos = 10, ypos = 200;
            f = new Font("Trebuchet MS", 12, FontStyle.Bold);
            font = new PdfTrueTypeFont(f);
            g.DrawString("Bill to:", font, brush, new PointF(xpos, ypos));
            xpos = xpos + 73;
            f = new Font("Trebuchet MS", 10, FontStyle.Regular);
            font = new PdfTrueTypeFont(f);
            g.DrawString(shipName, font, brush, new PointF(xpos, ypos));
            ypos = ypos + 10;
            g.DrawString(address, font, brush, new PointF(xpos, ypos));
            ypos = ypos + 10;
            g.DrawString(shipCity, font, brush, new PointF(xpos, ypos));
            ypos = ypos + 10;
            g.DrawString(shipCountry, font, brush, new PointF(xpos, ypos));
            xpos = 325; ypos = 200;
            f = new Font("Trebuchet MS", 12, FontStyle.Bold);
            font = new PdfTrueTypeFont(f);
            g.DrawString("Ship to:", font, brush, new PointF(xpos, ypos));
            xpos = xpos + 75;
            f = new Font("Trebuchet MS", 10, FontStyle.Regular);
            font = new PdfTrueTypeFont(f);
            g.DrawString(shipName, font, brush, new PointF(xpos, ypos));
            ypos = ypos + 10;
            g.DrawString(address, font, brush, new PointF(xpos, ypos));
            ypos = ypos + 10;
            g.DrawString(shipCity, font, brush, new PointF(xpos, ypos));
            ypos = ypos + 10;
            g.DrawString(shipCountry, font, brush, new PointF(xpos, ypos));


            // Create table and format it. 
            PdfSimpleTable table = new PdfSimpleTable();
            table.DataSource = GetTestOrder(oid);

            PdfPen borderPen = new PdfPen(Color.FromArgb(192, 201, 219));
            borderPen.Width = 1.0f;

            PdfCellStyle defStyle = new PdfCellStyle();
            defStyle.Font = font;
            defStyle.BorderPen = borderPen;
            table.Style.DefaultStyle = defStyle;

            f = new Font("Trebuchet MS", 10, FontStyle.Bold);
            PdfFont headerFont = new PdfTrueTypeFont(f);

            PdfCellStyle headerStyle = new PdfCellStyle();
            headerStyle.Font = headerFont;

            PdfStringFormat format = new PdfStringFormat();
            format.Alignment = PdfTextAlignment.Center;
            headerStyle.StringFormat = format;

            PdfBrush headerBrush = new PdfSolidBrush(Color.FromArgb(218, 229, 245));
            headerStyle.BackgroundBrush = headerBrush;
            headerStyle.BorderPen = borderPen;

            table.Style.HeaderStyle = headerStyle;
            table.Style.HeaderSource = PdfHeaderSource.ColumnCaptions;
            table.Style.ShowHeader = true;
            table.Style.CellPadding = 6f;
            table.Style.BorderPen = borderPen;
            table.Style.BorderOverlapStyle = PdfBorderOverlapStyle.Overlap;
            PdfSimpleTableLayoutResult result = table.Draw(page, 0, ypos + 65, 565);

            table.DataSource = GetProductDetails(oid);
            f = new Font("Trebuchet MS", 10, FontStyle.Regular);
            font = new PdfTrueTypeFont(f);
            table.Style.DefaultStyle.Font = font;

            result = table.Draw(result.Page, 0, result.Bounds.Bottom + 30, 565);

            // Create DataTable for source
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("ID1");
            dataTable.Columns.Add("ID2");

            object[] values = new object[] {
				"SUBTOTAL","$"+ String.Format("{0:#.00}", total)};
            dataTable.Rows.Add(values);

            values = new object[] {
				"FREIGHT","$"+ String.Format("{0:#.00}",shipTable.Rows[0]["Freight"])};
            dataTable.Rows.Add(values);

            ftotal = total + Convert.ToDouble(shipTable.Rows[0]["Freight"]);
            values = new object[] {
				"TOTAL", "$"+ String.Format("{0:#.00}", ftotal) };
            dataTable.Rows.Add(values);

            table.DataSource = dataTable;
            table.Style.ShowHeader = false;
            table.Style.BorderOverlapStyle = PdfBorderOverlapStyle.Overlap;

            table.Draw(result.Page, 339, result.Bounds.Bottom, 226);

            g.DrawString("THANK YOU FOR THE BUSINESS", font, brush, 240, 760);

            // Save and close the document.
            var outputPath = Path.Combine(OutputDir, this.GetType().Name + "_" + Guid.NewGuid().ToString() + ".pdf");
            doc.Save(outputPath);
            doc.Close(true);

            return outputPath;
        }


        /// 
        /// Gets fictitious order by id.
        /// 
        private DataSet GetTestOrder(int orderId)
        {
            Order order = GetOrder(orderId);

            DataTable dt = new DataTable();
            dt.Columns.Add("ShipName", typeof(string));
            dt.Columns.Add("ShipAddress", typeof(string));
            dt.Columns.Add("Freight", typeof(float));
            dt.Columns.Add("ShippedDate", typeof(DateTime));
            dt.Columns.Add("ShipCity", typeof(string));
            dt.Columns.Add("ShipCountry", typeof(string));

            dt.Rows.Add(order.ShipName, order.ShipAddress, order.Freight, order.ShippedDate, order.ShipCity, order.ShipCountry);

            // Create dataset
            DataSet dataSet = new DataSet();
            dataSet.Tables.Add(dt);

            return dataSet;
        }

        //Sub table
        private DataTable GetProductDetails(int orderId)
        {
            OrderDetails[] details = GetOrderDetails(orderId);

            DataTable dt = new DataTable();
            dt.Columns.Add("ProductID", typeof(string));
            dt.Columns.Add("Quantity", typeof(string));
            dt.Columns.Add("UnitPrice", typeof(float));
            dt.Columns.Add("Discount", typeof(float));
            dt.Columns.Add("Price", typeof(string));

            foreach (OrderDetails d in details)
                dt.Rows.Add(d.ProductID, d.Quantity, d.UnitPrice, d.Discount, "$" + (d.Quantity * d.UnitPrice).ToString());

            return dt;
        }

        private DataTable GetShipDetails(int orderId)
        {
            Order order = GetOrder(orderId);

            DataTable dt = new DataTable();
            dt.Columns.Add("ShipName", typeof(string));
            dt.Columns.Add("ShipAddress", typeof(string));
            dt.Columns.Add("Freight", typeof(float));
            dt.Columns.Add("ShipCity", typeof(string));
            dt.Columns.Add("ShipCountry", typeof(string));
            dt.Columns.Add("ShippedDate", typeof(DateTime));

            dt.Rows.Add(order.ShipName, order.ShipAddress, order.Freight, order.ShipCity, order.ShipCountry, order.ShippedDate);

            return dt;
        }

        class OrderDetails
        {
            int _productID;
            public int ProductID
            {
                get { return _productID; }
                set { _productID = value; }
            }

            int _quantity;
            public int Quantity
            {
                get { return _quantity; }
                set { _quantity = value; }
            }

            float _unitPrice;
            public float UnitPrice
            {
                get { return _unitPrice; }
                set { _unitPrice = value; }
            }

            float _discount;
            public float Discount
            {
                get { return _discount; }
                set { _discount = value; }
            }
        }

        class Order
        {
            int _orderID;
            public int OrderID
            {
                get { return _orderID; }
                set { _orderID = value; }
            }

            string _shipName;
            public string ShipName
            {
                get { return _shipName; }
                set { _shipName = value; }
            }
            
            string _shipAddress;
            public string ShipAddress
            {
                get { return _shipAddress; }
                set { _shipAddress = value; }
            }
            
            float _freight;
            public float Freight
            {
                get { return _freight; }
                set { _freight = value; }
            }

            string _shipCity;
            public string ShipCity
            {
                get { return _shipCity; }
                set { _shipCity = value; }
            }

            string _shipCountry;
            public string ShipCountry
            {
                get { return _shipCountry; }
                set { _shipCountry = value; }
            }

            DateTime _shippedDate;
            public DateTime ShippedDate
            {
                get { return _shippedDate; }
                set { _shippedDate = value; }
            }

            OrderDetails[] _details;
            public OrderDetails[] Details
            {
                get { return _details; }
                set { _details = value; }
            }

            public float Total
            {
                get
                {
                    float t = 0.0f;
                    foreach (OrderDetails d in Details)
                    {
                        t = t + (d.UnitPrice*d.Quantity - d.Discount);
                    }

                    return t;
                }
            }
        }

        Random random = new Random();

        Order[] _orders;
        Order[] EnsureOrders()
        {
            if (_orders == null)
            {
                const int max = 50;
                _orders = new Order[max];

                // Create fake orders.
                for (int i = 0; i < max; i++)
                {
                    Order order = new Order();

                    order.OrderID = 1000 + i;
                    order.ShipAddress = "Luisenstr. 48" + i;
                    order.ShipCity = "Manster";
                    order.ShipCountry = "Germany";
                    order.ShipName = "Toms Spezialitaten";
                    order.ShippedDate = DateTime.Now.AddYears(-1);
                    order.Freight = 11.6f;

                    order.Details = new OrderDetails[2];

                    OrderDetails details = new OrderDetails();
                    details.Discount = 0;
                    details.ProductID = 20 + i;
                    details.Quantity = random.Next(30) + 1;
                    details.UnitPrice = 5.6f * (i + 1);
                    order.Details[0] = details;

                    details = new OrderDetails();
                    details.Discount = 0;
                    details.ProductID = 20 + i + 1;
                    details.Quantity = random.Next(30) + 1;
                    details.UnitPrice = 7.6f * (i + 1);
                    order.Details[1] = details;

                    _orders[i] = order;
                }
            }

            return _orders;
        }

        OrderDetails[] GetOrderDetails(int orderId)
        {
            foreach (Order o in EnsureOrders())
            {
                if (o.OrderID == orderId)
                    return o.Details;
            }

            throw new Exception("Order not found");
        }

        Order GetOrder(int orderId)
        {
            foreach (Order ord in EnsureOrders())
            {
                if (ord.OrderID == orderId)
                    return ord;
            }

            throw new Exception("Order not found");
        }

        internal int[] GetOrderIds()
        {
            Order[] orders = EnsureOrders();

            List list = new List();
            foreach (Order ord in orders)
                list.Add(ord.OrderID);

            return list.ToArray();
        }
    }
}
Imports System.IO
Imports System.Text

Imports OfficeComponent.Pdf
Imports OfficeComponent.Pdf.Graphics
Imports OfficeComponent.Pdf.Tables

Namespace OfficeComponent.Samples
	Friend Class InvoiceExample
		Inherits ExampleBase
		Private privateOrderId As Integer
		Public Property OrderId() As Integer
			Get
				Return privateOrderId
			End Get
			Set(ByVal value As Integer)
				privateOrderId = value
			End Set
		End Property

		Public Sub New(ByVal commonDataPath As String, ByVal outputDir As String)
			MyBase.New(commonDataPath, outputDir)

		End Sub

		Public Sub New(ByVal commonDataPath As String, ByVal outputDir As String, ByVal xmlFile As String)
			MyBase.New(commonDataPath, outputDir, xmlFile)

		End Sub

		Public Overrides Function Execute() As String
#If WEB Then
			OrderId = 1000
#End If

			Dim shipName, address, shipCity, shipCountry As String
			Dim shippedDate As Date
			Dim total, ftotal As Double

			Dim order As Order = GetOrder(OrderId)
			shipName = order.ShipName
			address = order.ShipAddress
			shipCity = order.ShipCity
			shipCountry = order.ShipCountry
			shippedDate = order.ShippedDate
			total = order.Total


			Dim oid As Integer = OrderId

			' Create a new instance of PdfDocument class.
			Dim doc As New PdfDocument()

			doc.PageSettings.Margins.All = 5

			'Add a page
			Dim page As PdfPage = doc.Pages.Add()
			Dim g As PdfGraphics = page.Graphics
			Dim rect As New RectangleF(0, 0, page.Graphics.ClientSize.Width, 100)

			'Draw gradient rectangle at the the top and bottom of the page
			Dim lgBrush As New PdfLinearGradientBrush(New PointF(page.Graphics.ClientSize.Width, 0), New PointF(page.Graphics.ClientSize.Width, 100), Color.FromArgb(218, 229, 245), Color.White)
			Dim brush As PdfBrush = New PdfSolidBrush(Color.Black)

			Dim font As PdfFont = New PdfStandardFont(PdfFontFamily.Helvetica, 25)
			g.DrawRectangle(lgBrush, rect)

			lgBrush = New PdfLinearGradientBrush(New PointF(0, page.Graphics.ClientSize.Height), New PointF(0, page.Graphics.ClientSize.Height - 120), Color.FromArgb(218, 229, 245), Color.White)
			rect = New RectangleF(0, page.Graphics.ClientSize.Height - 120, page.Graphics.ClientSize.Width, 120)
			g.DrawRectangle(lgBrush, rect)

			'Add image
			Dim image As PdfImage = New PdfBitmap(CommonDataPath & "\logo.gif")
			g.DrawImage(image, New PointF(10, 20), New SizeF(354F * 0.7F, 35F * 0.7F))

			g.DrawString("INVOICE", font, brush, 425, 20)

			' Get the product table details
			Dim shipTable As DataTable = GetShipDetails(oid)

			Dim f As New Font("Trebuchet MS", 10)
			font = New PdfTrueTypeFont(f)


			' Display the "bill to" and "ship to" address
			g.DrawString("Invoice ID:   " & oid.ToString(), font, brush, New PointF(325, 116))
			g.DrawString("Shipped Date: " & shippedDate, font, brush, New PointF(325, 130))

			g.DrawString("Northwind Traders" & vbLf & "67,rue des Cinquante Otages," & vbLf & "Elgin," & vbLf & "Unites States.", font, brush, New RectangleF(10, 116, 200, 200))
			Dim xpos As Single = 10, ypos As Single = 200
			f = New Font("Trebuchet MS", 12, FontStyle.Bold)
			font = New PdfTrueTypeFont(f)
			g.DrawString("Bill to:", font, brush, New PointF(xpos, ypos))
			xpos = xpos + 73
			f = New Font("Trebuchet MS", 10, FontStyle.Regular)
			font = New PdfTrueTypeFont(f)
			g.DrawString(shipName, font, brush, New PointF(xpos, ypos))
			ypos = ypos + 10
			g.DrawString(address, font, brush, New PointF(xpos, ypos))
			ypos = ypos + 10
			g.DrawString(shipCity, font, brush, New PointF(xpos, ypos))
			ypos = ypos + 10
			g.DrawString(shipCountry, font, brush, New PointF(xpos, ypos))
			xpos = 325
			ypos = 200
			f = New Font("Trebuchet MS", 12, FontStyle.Bold)
			font = New PdfTrueTypeFont(f)
			g.DrawString("Ship to:", font, brush, New PointF(xpos, ypos))
			xpos = xpos + 75
			f = New Font("Trebuchet MS", 10, FontStyle.Regular)
			font = New PdfTrueTypeFont(f)
			g.DrawString(shipName, font, brush, New PointF(xpos, ypos))
			ypos = ypos + 10
			g.DrawString(address, font, brush, New PointF(xpos, ypos))
			ypos = ypos + 10
			g.DrawString(shipCity, font, brush, New PointF(xpos, ypos))
			ypos = ypos + 10
			g.DrawString(shipCountry, font, brush, New PointF(xpos, ypos))


			' Create table and format it. 
			Dim table As New PdfSimpleTable()
			table.DataSource = GetTestOrder(oid)

			Dim borderPen As New PdfPen(Color.FromArgb(192, 201, 219))
			borderPen.Width = 1.0F

			Dim defStyle As New PdfCellStyle()
			defStyle.Font = font
			defStyle.BorderPen = borderPen
			table.Style.DefaultStyle = defStyle

			f = New Font("Trebuchet MS", 10, FontStyle.Bold)
			Dim headerFont As PdfFont = New PdfTrueTypeFont(f)

			Dim headerStyle As New PdfCellStyle()
			headerStyle.Font = headerFont

			Dim format As New PdfStringFormat()
			format.Alignment = PdfTextAlignment.Center
			headerStyle.StringFormat = format

			Dim headerBrush As PdfBrush = New PdfSolidBrush(Color.FromArgb(218, 229, 245))
			headerStyle.BackgroundBrush = headerBrush
			headerStyle.BorderPen = borderPen

			table.Style.HeaderStyle = headerStyle
			table.Style.HeaderSource = PdfHeaderSource.ColumnCaptions
			table.Style.ShowHeader = True
			table.Style.CellPadding = 6F
			table.Style.BorderPen = borderPen
			table.Style.BorderOverlapStyle = PdfBorderOverlapStyle.Overlap
			Dim result As PdfSimpleTableLayoutResult = table.Draw(page, 0, ypos + 65, 565)

			table.DataSource = GetProductDetails(oid)
			f = New Font("Trebuchet MS", 10, FontStyle.Regular)
			font = New PdfTrueTypeFont(f)
			table.Style.DefaultStyle.Font = font

			result = table.Draw(result.Page, 0, result.Bounds.Bottom + 30, 565)

			' Create DataTable for source
			Dim dataTable As New DataTable()
			dataTable.Columns.Add("ID1")
			dataTable.Columns.Add("ID2")

			Dim values() As Object = { "SUBTOTAL","$" & String.Format("{0:#.00}", total)}
			dataTable.Rows.Add(values)

			values = New Object() { "FREIGHT","$" & String.Format("{0:#.00}",shipTable.Rows(0)("Freight"))}
			dataTable.Rows.Add(values)

			ftotal = total + Convert.ToDouble(shipTable.Rows(0)("Freight"))
			values = New Object() { "TOTAL", "$" & String.Format("{0:#.00}", ftotal) }
			dataTable.Rows.Add(values)

			table.DataSource = dataTable
			table.Style.ShowHeader = False
			table.Style.BorderOverlapStyle = PdfBorderOverlapStyle.Overlap

			table.Draw(result.Page, 339, result.Bounds.Bottom, 226)

			g.DrawString("THANK YOU FOR THE BUSINESS", font, brush, 240, 760)

			' Save and close the document.
			Dim outputPath = Path.Combine(OutputDir, Me.GetType().Name & "_" & Guid.NewGuid().ToString() & ".pdf")
			doc.Save(outputPath)
			doc.Close(True)

			Return outputPath
		End Function


		''' 
		''' Gets fictitious order by id.
		''' 
		Private Function GetTestOrder(ByVal orderId As Integer) As DataSet
			Dim order As Order = GetOrder(orderId)

			Dim dt As New DataTable()
			dt.Columns.Add("ShipName", GetType(String))
			dt.Columns.Add("ShipAddress", GetType(String))
			dt.Columns.Add("Freight", GetType(Single))
			dt.Columns.Add("ShippedDate", GetType(Date))
			dt.Columns.Add("ShipCity", GetType(String))
			dt.Columns.Add("ShipCountry", GetType(String))

			dt.Rows.Add(order.ShipName, order.ShipAddress, order.Freight, order.ShippedDate, order.ShipCity, order.ShipCountry)

			' Create dataset
			Dim dataSet As New DataSet()
			dataSet.Tables.Add(dt)

			Return dataSet
		End Function

		'Sub table
		Private Function GetProductDetails(ByVal orderId As Integer) As DataTable
			Dim details() As OrderDetails = GetOrderDetails(orderId)

			Dim dt As New DataTable()
			dt.Columns.Add("ProductID", GetType(String))
			dt.Columns.Add("Quantity", GetType(String))
			dt.Columns.Add("UnitPrice", GetType(Single))
			dt.Columns.Add("Discount", GetType(Single))
			dt.Columns.Add("Price", GetType(String))

			For Each d As OrderDetails In details
				dt.Rows.Add(d.ProductID, d.Quantity, d.UnitPrice, d.Discount, "$" & (d.Quantity * d.UnitPrice).ToString())
			Next d

			Return dt
		End Function

		Private Function GetShipDetails(ByVal orderId As Integer) As DataTable
			Dim order As Order = GetOrder(orderId)

			Dim dt As New DataTable()
			dt.Columns.Add("ShipName", GetType(String))
			dt.Columns.Add("ShipAddress", GetType(String))
			dt.Columns.Add("Freight", GetType(Single))
			dt.Columns.Add("ShipCity", GetType(String))
			dt.Columns.Add("ShipCountry", GetType(String))
			dt.Columns.Add("ShippedDate", GetType(Date))

			dt.Rows.Add(order.ShipName, order.ShipAddress, order.Freight, order.ShipCity, order.ShipCountry, order.ShippedDate)

			Return dt
		End Function

		Private Class OrderDetails
			Private _productID As Integer
			Public Property ProductID() As Integer
				Get
					Return _productID
				End Get
				Set(ByVal value As Integer)
					_productID = value
				End Set
			End Property

			Private _quantity As Integer
			Public Property Quantity() As Integer
				Get
					Return _quantity
				End Get
				Set(ByVal value As Integer)
					_quantity = value
				End Set
			End Property

			Private _unitPrice As Single
			Public Property UnitPrice() As Single
				Get
					Return _unitPrice
				End Get
				Set(ByVal value As Single)
					_unitPrice = value
				End Set
			End Property

			Private _discount As Single
			Public Property Discount() As Single
				Get
					Return _discount
				End Get
				Set(ByVal value As Single)
					_discount = value
				End Set
			End Property
		End Class

		Private Class Order
			Private _orderID As Integer
			Public Property OrderID() As Integer
				Get
					Return _orderID
				End Get
				Set(ByVal value As Integer)
					_orderID = value
				End Set
			End Property

			Private _shipName As String
			Public Property ShipName() As String
				Get
					Return _shipName
				End Get
				Set(ByVal value As String)
					_shipName = value
				End Set
			End Property

			Private _shipAddress As String
			Public Property ShipAddress() As String
				Get
					Return _shipAddress
				End Get
				Set(ByVal value As String)
					_shipAddress = value
				End Set
			End Property

			Private _freight As Single
			Public Property Freight() As Single
				Get
					Return _freight
				End Get
				Set(ByVal value As Single)
					_freight = value
				End Set
			End Property

			Private _shipCity As String
			Public Property ShipCity() As String
				Get
					Return _shipCity
				End Get
				Set(ByVal value As String)
					_shipCity = value
				End Set
			End Property

			Private _shipCountry As String
			Public Property ShipCountry() As String
				Get
					Return _shipCountry
				End Get
				Set(ByVal value As String)
					_shipCountry = value
				End Set
			End Property

			Private _shippedDate As Date
			Public Property ShippedDate() As Date
				Get
					Return _shippedDate
				End Get
				Set(ByVal value As Date)
					_shippedDate = value
				End Set
			End Property

			Private _details() As OrderDetails
			Public Property Details() As OrderDetails()
				Get
					Return _details
				End Get
				Set(ByVal value As OrderDetails())
					_details = value
				End Set
			End Property

			Public ReadOnly Property Total() As Single
				Get
					Dim t As Single = 0.0F
					For Each d As OrderDetails In Details
						t = t + (d.UnitPrice*d.Quantity - d.Discount)
					Next d

					Return t
				End Get
			End Property
		End Class

		Private random As New Random()

		Private _orders() As Order
		Private Function EnsureOrders() As Order()
			If _orders Is Nothing Then
				Const max As Integer = 50
				_orders = New Order(max - 1){}

				' Create fake orders.
				For i As Integer = 0 To max - 1
					Dim order As New Order()

					order.OrderID = 1000 + i
					order.ShipAddress = "Luisenstr. 48" & i
					order.ShipCity = "Manster"
					order.ShipCountry = "Germany"
					order.ShipName = "Toms Spezialitaten"
					order.ShippedDate = Date.Now.AddYears(-1)
					order.Freight = 11.6F

					order.Details = New OrderDetails(1){}

					Dim details As New OrderDetails()
					details.Discount = 0
					details.ProductID = 20 + i
					details.Quantity = random.Next(30) + 1
					details.UnitPrice = 5.6F * (i + 1)
					order.Details(0) = details

					details = New OrderDetails()
					details.Discount = 0
					details.ProductID = 20 + i + 1
					details.Quantity = random.Next(30) + 1
					details.UnitPrice = 7.6F * (i + 1)
					order.Details(1) = details

					_orders(i) = order
				Next i
			End If

			Return _orders
		End Function

		Private Function GetOrderDetails(ByVal orderId As Integer) As OrderDetails()
			For Each o As Order In EnsureOrders()
				If o.OrderID = orderId Then
					Return o.Details
				End If
			Next o

			Throw New Exception("Order not found")
		End Function

		Private Function GetOrder(ByVal orderId As Integer) As Order
			For Each ord As Order In EnsureOrders()
				If ord.OrderID = orderId Then
					Return ord
				End If
			Next ord

			Throw New Exception("Order not found")
		End Function

		Friend Function GetOrderIds() As Integer()
			Dim orders() As Order = EnsureOrders()

			Dim list As New List(Of Integer)()
			For Each ord As Order In orders
				list.Add(ord.OrderID)
			Next ord

			Return list.ToArray()
		End Function
	End Class
End Namespace