/// <summary>
        /// Draw Grid column headers from partition
        /// </summary>
        /// <param name="g"></param>
        /// <param name="partition">Partition to print</param>
        /// <returns></returns>
        private float DrawColumnHeaders(Graphics g, Partition partition)
        {
            PartitionBounds bounds = partition.Bounds;

            float currentY = bounds.StartY;
            float currentX = bounds.StartX;

            // Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
            Pen linePen = new Pen(GridView.GridColor, 1);

            // Calculating and drawing the HeaderBounds
            RectangleF HeaderBounds = new RectangleF(currentX, currentY, bounds.Width, columnHeaderHeight);

            g.FillRectangle(
                new SolidBrush(GridHelper.ColumnsHeaderBackColor(GridView)),
                HeaderBounds);

            // Setting the format that will be used to print each cell of the header row
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoClip;

            // Printing each visible cell of the header row
            foreach (var column in partition.GetColumns())
            {
                DataGridViewHeaderCell cell = column.HeaderCell;

                CellFormat.Alignment = GridHelper.HorizontalAlignement(cell);

                RectangleF CellBounds = new RectangleF(currentX, currentY, columnWidths[column.Index], columnHeaderHeight);

                // Printing the cell text
                g.DrawString(column.HeaderText,
                    GridHelper.Font(cell,scale),
                    new SolidBrush(GridHelper.ForeColor(cell)),
                    CellBounds,
                    CellFormat);

                // Drawing the cell bounds
                if (GridView.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) // Draw the cell border only if the HeaderBorderStyle is not None
                    g.DrawRectangle(linePen, currentX, currentY, columnWidths[column.Index], columnHeaderHeight);

                currentX += columnWidths[column.Index];

            }

            return currentY + columnHeaderHeight;
        }
        /// <summary>
        /// Draw Grid rows from given partition
        /// </summary>
        /// <param name="g"></param>
        /// <param name="partition">Partition to print</param>
        /// <param name="currentY">Starting Y coordinate</param>
        private void DrawRows(Graphics g, Partition partition, float currentY)
        {
            PartitionBounds bounds = partition.Bounds;

            // Setting the LinePen that will be used to draw lines and rectangles
            Pen linePen = new Pen(GridView.GridColor, 1);

            // Setting the format that will be used to print each cell
            StringFormat CellFormat = new StringFormat();
            CellFormat.Trimming = StringTrimming.Word;
            CellFormat.FormatFlags = StringFormatFlags.LineLimit;

            foreach (var row in partition.GetRows())
            {
                float rowHeight = rowsHeights[row.Index];

                // Setting the RowFore style
                SolidBrush RowForeBrush = new SolidBrush(GridHelper.ForeColor(row));

                // Calculating the starting x coordinate that the printing process will start from
                float currentX = bounds.StartX;

                // Calculating the entire CurrentRow bounds
                RectangleF RowBounds = new RectangleF(currentX, currentY, bounds.Width, rowHeight);

                g.FillRectangle(new SolidBrush(GridHelper.BackColor(row)), RowBounds);

                foreach (var column in partition.GetColumns())
                {
                    var cell = row.Cells[column.Index];

                    CellFormat.Alignment = GridHelper.HorizontalAlignement(cell);

                    RectangleF CellBounds = new RectangleF(currentX, currentY, columnWidths[column.Index], rowHeight);

                    // Printing the cell text
                    g.DrawString(
                        cell.EditedFormattedValue.ToString(),
                        GridHelper.Font(cell, scale),
                        new SolidBrush(GridHelper.ForeColor(row)),
                        CellBounds,
                        CellFormat);

                    // Drawing the cell bounds
                    if (GridView.CellBorderStyle != DataGridViewCellBorderStyle.None) // Draw the cell border only if the CellBorderStyle is not None
                        g.DrawRectangle(linePen, currentX, currentY, columnWidths[column.Index], rowHeight);

                    currentX += columnWidths[column.Index];
                }

                currentY += rowHeight;
            }
        }
        /// <summary>
        /// Print a sheet containing the given partition
        /// </summary>
        /// <param name="g"></param>
        /// <param name="partition"></param>
        public void DrawSheet(Graphics g, Partition partition)
        {
            codes[CodeEnum.SheetNumber] = partition.SheetNumber.ToString();

            if (SheetHeader != null) // print header if it has been set
                SheetHeader.Draw(g, codes);

            // print report title on first page if a title block has been set
            if (partition.SheetNumber == 1 && TitlePrintBlock != null)
                TitlePrintBlock.Draw(g, codes);

            float currentY = DrawColumnHeaders(g, partition);
            DrawRows(g, partition, currentY);

            if (SheetFooter != null) // print footer if it has been set
                SheetFooter.Draw(g, codes);
        }