Saturday, February 6, 2010

Print Multiple-layered column header in datagridview

Recently someone had asked a question on a forum of “How to create multiple-layered column header in datagridview and also have a print preview of it in vb.net”. Creating multiple-layered column header is available on “Windows Forms Data Controls and Data Binding Forum FAQ” on MSDN Forum but the code is provided in VC#. So I have created a code in VB.NET through which multiple-layered column header can be created as well we can have print preview of it.

Multiple-layered Column Header DatagridView

Datagridview1

To create a datagridview with multiple column header we have to handle the DataGridView.Painting and DataGridView.CellPainting events, so that we can draw header as we want. We can use PrintPage event of PrintDocument to build the page for printing.

Print Preview of Multi-layered Column Datagridview

Datagridview2

Code for Datagridview

Imports System.Drawing.Printing
Public Class DemoForm
Dim names() As String = {"Microsoft", "Adobe", "SUN"}
Dim WithEvents MyPrintDocument As New PrintDocument
Private Sub DemoForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.DataGridView1.Columns.Add("clmProduct1", "Product")
Me.DataGridView1.Columns.Add("clmPrice1", "Price")
Me.DataGridView1.Columns.Add("clmProduct2", "Product")
Me.DataGridView1.Columns.Add("clmPrice2", "Price")
Me.DataGridView1.Columns.Add("clmProduct3", "Product")
Me.DataGridView1.Columns.Add("clmPrice3", "Price")
DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
DataGridView1.ColumnHeadersHeight = DataGridView1.ColumnHeadersHeight * 2
DataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter
End Sub
Private Sub
DataGridView1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles DataGridView1.Paint
For i As Integer = 0 To 5 Step 2
Dim rec As Rectangle = DataGridView1.GetCellDisplayRectangle(i, -1, True)
rec.X += 1
rec.Y += 1
rec.Width = rec.Width * 2 - 2
rec.Height = rec.Height / 2 - 2
e.Graphics.FillRectangle(New SolidBrush(Me.DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), rec)
Dim format As New StringFormat
format.Alignment = StringAlignment.Center
format.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(names(i / 2), DataGridView1.ColumnHeadersDefaultCellStyle.Font, New SolidBrush(DataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), rec, format)
Next
End Sub
Private Sub
DataGridView1_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
If e.RowIndex = -1 And e.ColumnIndex <> -1 Then
e.PaintBackground(e.CellBounds, False)
Dim rec As Rectangle = e.CellBounds
rec.Y += e.CellBounds.Height / 2
rec.Height = e.CellBounds.Height / 2
e.PaintContent(rec)
e.Handled = True
End If
End Sub

Private Sub
btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
Dim dg As New PrintPreviewDialog
dg.Document = MyPrintDocument
dg.ShowDialog()
End Sub

Private Sub
PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles MyPrintDocument.PrintPage
Dim leftMargin As Integer = 10
Dim position As Integer = leftMargin
Dim yPosition As Integer
Dim
height As Integer = DataGridView1.ColumnHeadersHeight / 2
yPosition = 0
For i As Integer = 0 To 5 Step 2
Dim totalWidth As Double = DataGridView1.Columns(i).Width + DataGridView1.Columns(i + 1).Width
e.Graphics.FillRectangle(New SolidBrush(Color.LightGray), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, totalWidth, height))
Dim format As New StringFormat
format.Alignment = StringAlignment.Center
format.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(names(i / 2), New Font("Arial", 12, FontStyle.Bold), Brushes.Black, position, yPosition)
position = position + totalWidth
Next

position = leftMargin
yPosition = DataGridView1.ColumnHeadersHeight / 2
For Each dr As DataGridViewColumn In DataGridView1.Columns
Dim totalWidth As Double = dr.Width
e.Graphics.FillRectangle(New SolidBrush(Color.LightGray), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawString(dr.HeaderText, New Font("Arial", 12, FontStyle.Bold), Brushes.Black, position, yPosition)
position = position + totalWidth
Next

For Each
dr As DataGridViewRow In DataGridView1.Rows
position = leftMargin
yPosition = yPosition + DataGridView1.ColumnHeadersHeight / 2
For Each dc As DataGridViewCell In dr.Cells
Dim totalWidth As Double = dc.OwningColumn.Width
e.Graphics.FillRectangle(New SolidBrush(Color.White), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, dc.OwningColumn.Width, height))
e.Graphics.DrawString(dc.Value, New Font("Arial", 12, FontStyle.Regular), Brushes.Black, position, yPosition)
position = position + totalWidth
Next
Next
End Sub

End Class