none
Printing DatagridView

    Question

  • Hi,

    I'd like to print only certain columns of a DataGridView. How would something like this be done? I couldn't find any code examples.

    Thanks
    Friday, July 08, 2005 4:01 PM

Answers

  • There isn't any built in printing support, so there are two options:
    1) Use the standard printing system provided by Windows Forms and manually print out the information that you want. Check out the documentation for PrintPage and PrintDocument

    2) Use the DataGridView's clipboard copy support to copy the content to an Excel file and then print that.

    Hope this helps,
    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"
    Friday, July 08, 2005 5:51 PM
  • Wow, I haven't see that, unless you are using TextRenderer.DrawText for your printing. Unfortunitely TextRenderer.DrawText uses GDI while Graphics.DrawString uses GDI+. GDI drawing with our current print engine doesn't work correctly, so you'll need to use Graphics.DrawString.

    Let me know if that works. If that isn't the case then can you file a bug and we'll investigate it? Thanks

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"
    Monday, July 11, 2005 7:26 PM

All replies

  • There isn't any built in printing support, so there are two options:
    1) Use the standard printing system provided by Windows Forms and manually print out the information that you want. Check out the documentation for PrintPage and PrintDocument

    2) Use the DataGridView's clipboard copy support to copy the content to an Excel file and then print that.

    Hope this helps,
    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"
    Friday, July 08, 2005 5:51 PM
  • ok, I just wrote a class that works with PrintPage and PrintDocument and everything looks good in the print preview dialog. However, as soon as I'm printing, only the grid headers and some extra text I added (page numbers, etc.) are printed. None of the DataGridView content that I painted and is visible in the print preview is printed to the output document.

    Any idea why this could be the case?
    Monday, July 11, 2005 1:54 PM
  • Wow, I haven't see that, unless you are using TextRenderer.DrawText for your printing. Unfortunitely TextRenderer.DrawText uses GDI while Graphics.DrawString uses GDI+. GDI drawing with our current print engine doesn't work correctly, so you'll need to use Graphics.DrawString.

    Let me know if that works. If that isn't the case then can you file a bug and we'll investigate it? Thanks

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"
    Monday, July 11, 2005 7:26 PM
  • I'm using DrawString...

    here's my code ... it's a bit messy right now but should do the job ;)


    private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
            {
                int x = 0;
                int y = 100;
                int rowGap = 20;
                int colGap = 5;
                int leftMargin = 50;
     
                int linesPerPage = e.MarginBounds.Height / _dataGridView.DefaultCellStyle.Font.Height;
                Font font = new Font(_dataGridView.DefaultCellStyle.Font.FontFamily, _dataGridView.DefaultCellStyle.Font.Size);
                Font headingFont = new Font("Arial", 10, FontStyle.Bold);
                Font captionFont = new Font("Arial", 10, FontStyle.Bold);
                Brush brush = new SolidBrush(Color.Black);
                string cellValue = "";

                e.Graphics.DrawString("Erstellt von " + ObjectStore.Account.UserName + " am " + DateTime.Now.ToLongDateString(), captionFont, brush, new PointF(50, 50));
                e.Graphics.DrawString("Seite " + _pageNumber, captionFont, brush, new PointF(e.PageBounds.Width - 100, e.PageBounds.Height - 50));

                int rowCount = _dataGridView.Rows.Count;
                int colCount = _dataGridView.Columns.Count;

                y += rowGap;
                x = leftMargin;
                foreach (DataGridViewColumn column in _dataGridView.Columns)
                {
                    if(column.GetType() != typeof(DataGridViewButtonColumn) && column.GetType() != typeof(DataGridViewCheckBoxColumn))
                    {
                        cellValue = column.HeaderText;
                        e.Graphics.DrawString(cellValue, headingFont, brush, x, y);
                        x += column.Width + colGap;
                    }
                }

                int count = 0;
                for (int i = _rowPosition; i < _dataGridView.Rows.Count; i++)
                {
                    y += rowGap;
                    x = leftMargin;

                    foreach (DataGridViewColumn column in _dataGridView.Columns)
                    {
                        if (column.GetType() != typeof(DataGridViewButtonColumn) && column.GetType() != typeof(DataGridViewCheckBoxColumn))
                        {
                            cellValue = _dataGridView.Rows//emoticons/emotion-55.gif" alt="Idea" />.Cells[column.Index].Value.ToString();
                            e.Graphics.DrawString(cellValue, captionFont, brush, x, y);
                            x += column.Width + colGap;
                            y = y + rowGap * (cellValue.Split(new char[] { '\r', '\n' }).Length - 1);
                        }
                    }

                    _rowPosition++;
                    count++;

                    if (count > linesPerPage)
                    {
                        break;
                    }
                }

                if (_rowPosition > linesPerPage && _rowPosition < _dataGridView.Rows.Count)
                {
                    _pageNumber++;
                    e.HasMorePages = true;
                }
            }

     

    Monday, July 11, 2005 10:07 PM
  • any takers? ;)
    Wednesday, July 13, 2005 12:16 PM
  • The MSDN library provides the following guidance for printing a DataGrid...

    This example demonstrates printing a DataGrid control.

    Example

    private void printGrid_Click(System.Object sender, System.EventArgs e) { printDocument1.Print(); } private void printDocument1_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e) { PaintEventArgs myPaintArgs = new PaintEventArgs(e.Graphics, new Rectangle(new Point(0, 0), this.Size)); this.InvokePaint(dataGrid1, myPaintArgs); 







    Is it planned to have this work for the DataGridView?
    I have tried to use it but it printed only the Grid, omitting the contents of the cells.
    Does the code in the above example work in VS 2005? That is, maybe I should copy
    the contents of my DataGridView to a DataGrid and print from there!
    Wednesday, August 17, 2005 1:59 AM
  • For anyone needing to know how to start printing a grid, here is some code I whipped up after not finding any samples I could heist from someone else.  I'm sure there are better ways to do this, but like I said, this is a start.  Probably why MS doesn't offer a print function or component is because there is truly an unlimited number of configurations for a print setup.  To achieve most of them isn't even rocket science, the beauty of VB.NET.  Cheers.


        Private oStringFormat As StringFormat
        Private oStringFormatComboBox As StringFormat
        Private oButton As Button
        Private oCheckbox As CheckBox
        Private oComboBox As ComboBox

        Private nTotalWidth As Int16
        Private nRowPos As Int16
        Private NewPage As Boolean
        Private nPageNo As Int16
        Private Header As String = "Header Test"
        Private sUserName As String = "Will"

        Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter

            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox

            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                nTotalWidth += oColumn.Width

            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0

        End Sub

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

                Static oColumnLefts As New ArrayList
                Static oColumnWidths As New ArrayList
                Static oColumnTypes As New ArrayList
                Static nHeight As Int16

                Dim nWidth, i, nRowsPerPage As Int16
                Dim nTop As Int16 = e.MarginBounds.Top
                Dim nLeft As Int16 = e.MarginBounds.Left

                If nPageNo = 1 Then

                    For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                        nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                        nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                        oColumnLefts.Add(nLeft)
                        oColumnWidths.Add(nWidth)
                        oColumnTypes.add(oColumn.GetType)
                        nLeft += nWidth

                    Next

                End If

                Do While nRowPos < DataGridView1.Rows.Count - 1

                    Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

                    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                        DrawFooter(e, nRowsPerPage)

                        NewPage = True
                        nPageNo += 1
                        e.HasMorePages = True
                        Exit Sub

                    Else

                        If NewPage Then

                            ' Draw Header
                            e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                            ' Draw Columns
                            nTop = e.MarginBounds.Top
                            i = 0
                            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                                e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                                e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                                e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                                i += 1

                            Next
                            NewPage = False

                        End If

                        nTop += nHeight
                        i = 0
                        For Each oCell As DataGridViewCell In oRow.Cells

                            If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                                oButton.Text = oCell.Value.ToString
                                oButton.Size = New Size(oColumnWidths(i), nHeight)
                                Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                                oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                                oCheckbox.Size = New Size(14, 14)
                                oCheckbox.Checked = CType(oCell.Value, Boolean)
                                Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                                Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                                oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                                oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                                Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                                oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                                Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
                                Dim oImageSize As Size = CType(oCell.Value, Image).Size
                                e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                            End If

                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                            i += 1

                        Next

                    End If

                    nRowPos += 1
                    nRowsPerPage += 1

                Loop

                DrawFooter(e, nRowsPerPage)

                e.HasMorePages = False

        End Sub

        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

            Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

            ' Right Align - User Name
            e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

        End Sub

    • Proposed as answer by Alex01987 Tuesday, February 15, 2011 1:39 PM
    Saturday, January 07, 2006 6:54 PM
  • Will,

    This is great code. Thank you!!! This works great for a straight print. I've played around with the code but can't seem to get it to work with print preview or a printdialog control. Do you have any code or have any idea on how to modofy your code so that it works with either control???

     

    Thanks,

    VB-Bandit

    Monday, January 30, 2006 1:03 PM
  • VB-Bandit,

    The code above creates the PrintDocument now all you need to do is use it, the following code with give you a print preview!

    Dim dlg As New PrintPreviewDialog()

    dlg.Document = PrintDocument1

    dlg.ShowDialog()

     

    This code gives you the page setup form...

    Dim psDlg As New PageSetupDialog

    Dim storedPageSettings As PageSettings = New PageSettings()

    psDlg.PageSettings = storedPageSettings

    psDlg.ShowDialog()

     

    I hope this is what you were looking for!

     

    CoNNect

    Saturday, March 18, 2006 6:36 AM
  • Thanks Heaps for your code Will!!!

    BTW, your code drops off the last line, it's fixed now as below:

     

    Saturday, March 18, 2006 6:54 AM
  • Private oStringFormat As StringFormat
        Private oStringFormatComboBox As StringFormat
        Private oButton As Button
        Private oCheckbox As CheckBox
        Private oComboBox As ComboBox

        Private nTotalWidth As Int16
        Private nRowPos As Int16
        Private NewPage As Boolean
        Private nPageNo As Int16
        Private Header As String = "Header Test"
        Private sUserName As String = "Will"

        Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter

            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox

            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                nTotalWidth += oColumn.Width

            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0

        End Sub

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

                Static oColumnLefts As New ArrayList
                Static oColumnWidths As New ArrayList
                Static oColumnTypes As New ArrayList
                Static nHeight As Int16

                Dim nWidth, i, nRowsPerPage As Int16
                Dim nTop As Int16 = e.MarginBounds.Top
                Dim nLeft As Int16 = e.MarginBounds.Left

                If nPageNo = 1 Then

                    For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                        nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                        nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                        oColumnLefts.Add(nLeft)
                        oColumnWidths.Add(nWidth)
                        oColumnTypes.add(oColumn.GetType)
                        nLeft += nWidth

                    Next

                End If

                Do While nRowPos < DataGridView1.Rows.Count - 1

                    Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

                    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                        DrawFooter(e, nRowsPerPage)

                        NewPage = True
                        nPageNo += 1
                        e.HasMorePages = True
                        Exit Sub

                    Else

                        If NewPage Then

                            ' Draw Header
                            e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                            ' Draw Columns
                            nTop = e.MarginBounds.Top
                            i = 0
                            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                                e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                                e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                                e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                                i += 1

                            Next
                            NewPage = False

                        End If

                        nTop += nHeight
                        i = 0
                        For Each oCell As DataGridViewCell In oRow.Cells

                            If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                                oButton.Text = oCell.Value.ToString
                                oButton.Size = New Size(oColumnWidths(i), nHeight)
                                Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                                oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                                oCheckbox.Size = New Size(14, 14)
                                oCheckbox.Checked = CType(oCell.Value, Boolean)
                                Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                                Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                                oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                                oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                                Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                                oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                                Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
                                Dim oImageSize As Size = CType(oCell.Value, Image).Size
                                e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                            End If

                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                            i += 1

                        Next

                    End If

                    nRowPos += 1
                    nRowsPerPage += 1

                Loop

                DrawFooter(e, nRowsPerPage)

                e.HasMorePages = False

        End Sub

        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

            Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

            ' Right Align - User Name
            e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

        End Sub

    • Proposed as answer by Melvindev Wednesday, December 16, 2009 3:07 AM
    Saturday, March 18, 2006 7:23 AM
  • Hy guys.

    I must say that this is a great code. But i get following error
    Error 1 Handles clause requires a WithEvents variable defined in the containing type or one of its base types.

    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

    Problem is with Handles PrintDocument1.PrintPage

    Can you please tell me what i'm doing wrong?

    Regards...
    Wednesday, March 22, 2006 5:46 PM
  • Ok i managed to solve that. But now i got one serious problem! This code print all rows from my DataGridView except last one. It always show one page more that actually exist.

    I have try your code too CoNNect but there is same problem with last row...


    Some help will be very wellcome!
    Wednesday, March 22, 2006 8:56 PM
  • Ok i have managed that too. If anyone will run into similar problem here is a way to set it right.

    In while loop in posted code you must set Do While nRowPos < DataGridView1.Rows.Count - 1 you must delet -1. It should look like this Do While nRowPos < DataGridView1.Rows.Count. Then it will work just fine.

    Great code indeed. Thank you...

    Wednesday, March 22, 2006 9:11 PM
  • This code was a HUGE help.  Thank you...

    I did add/change the following because I had a few empty cells and I was getting errors

    For Each oCell As DataGridViewCell In oRow.Cells

    If oCell.Value <> Nothing Then

    sValue = oCell.Value.ToString

    else

    sValue = ""

    End If

    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

    e.Graphics.DrawString(sValue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

    Friday, March 31, 2006 5:11 PM
  • Hey, That's great.  I had the same problem and would like to know how you did.  I tried but not as lucky as you.  Help please!
    Thursday, April 06, 2006 3:13 PM
  • is your problem about two pages on the same page?
    Thursday, April 06, 2006 3:50 PM
  • If anyone is interested, I converted the code to C# and added a fix for correctly computing number of pages on the last page.

    private StringFormat m_stringFormat;

    private double m_totalWidth;

    private int m_rowPos;

    private bool m_newPage;

    private int m_pageNo;

    private string m_pageHeader = "Header";

    private string m_userName = "Printed by <username>";

    private ArrayList m_columnLefts = new ArrayList();

    private ArrayList m_columnWidths = new ArrayList();

    private int m_pageHeight = 0;

    private int m_pageCount = 0;

    private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)

    {

    m_stringFormat = new StringFormat();

    m_stringFormat.Alignment = StringAlignment.Near;

    m_stringFormat.LineAlignment = StringAlignment.Center;

    m_stringFormat.Trimming = StringTrimming.EllipsisCharacter;

    m_totalWidth = 0;

    foreach (DataGridViewColumn oColumn in dataGridView1.Columns)

    {

    m_totalWidth += oColumn.Width;

    }

    m_pageNo = 1;

    m_newPage = true;

    m_rowPos = 0;

    }

    private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

    {

    int nWidth, i;

    double nRowsPerPage = 0;

    int nTop = e.MarginBounds.Top;

    int nLeft = e.MarginBounds.Left;

    if (m_pageNo == 1)

    {

    m_columnLefts.Clear();

    m_columnWidths.Clear();

    m_pageHeight = 0;

    m_pageCount = 0;

    foreach (DataGridViewColumn oColumn in dataGridView1.Columns)

    {

    double floorVal = Convert.ToDouble( oColumn.Width ) / m_totalWidth * m_totalWidth * (Convert.ToDouble( e.MarginBounds.Width) / m_totalWidth);

    nWidth = Convert.ToInt32(Math.Floor(floorVal));

    m_pageHeight = Convert.ToInt32(e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height) + 11;

    m_columnLefts.Add(nLeft);

    m_columnWidths.Add(nWidth);

    nLeft += nWidth;

    }

    }

    while (m_rowPos < dataGridView1.Rows.Count )

    {

    DataGridViewRow oRow = dataGridView1.Rows[m_rowPos];

    if (nTop + m_pageHeight >= e.MarginBounds.Height + e.MarginBounds.Top)

    {

    DrawFooter(e, nRowsPerPage);

    m_newPage = true;

    m_pageNo++;

    e.HasMorePages = true;

    return;

    }

    else

    {

    if (m_newPage)

    {

    // Draw Header

    e.Graphics.DrawString(m_pageHeader, new Font(dataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(m_pageHeader, new Font(dataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13);

    // Draw Columns

    nTop = e.MarginBounds.Top;

    i = 0;

    foreach (DataGridViewColumn oColumn in dataGridView1.Columns)

    {

    e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), new Rectangle((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight));

    e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight));

    e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, new SolidBrush(oColumn.InheritedStyle.ForeColor), new RectangleF((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight), m_stringFormat);

    i++;

    }

    m_newPage = false;

    }

    nTop += m_pageHeight;

    i = 0;

    foreach (DataGridViewCell oCell in oRow.Cells)

    {

    string sValue = String.Empty;

    if (oCell.Value != null)

    {

    sValue = oCell.Value.ToString();

    }

    e.Graphics.DrawString(sValue, oCell.InheritedStyle.Font, new SolidBrush(oCell.InheritedStyle.ForeColor), new RectangleF((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight), m_stringFormat);

    e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight));

    i++;

    }

    }

    m_rowPos++;

    nRowsPerPage++;

    }

     

    DrawFooter(e, nRowsPerPage);

    e.HasMorePages = false;

    }

    private void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, double nRowsPerPage)

    {

    if (m_pageCount == 0)

    {

    m_pageCount = Convert.ToInt32( Math.Ceiling(Convert.ToDouble(dataGridView1.Rows.Count) / nRowsPerPage) );

    }

    string sPageNo = String.Format("Page {0} of {1}", m_pageNo.ToString(), m_pageCount.ToString()).ToString();

    // Right Align - User Name

    e.Graphics.DrawString(m_userName, dataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7);

    // Left Align - Date/Time

    e.Graphics.DrawString(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString(), dataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7);

    // Center - Page No. Info

    e.Graphics.DrawString(sPageNo, dataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31);

    }

    Monday, April 10, 2006 10:00 AM
  •  JeremyZK wrote:

    If oCell.Value <> Nothing Then

    Love the code!

    One small change to handle dbnull:

    If oCell.Value IsNot Nothing Then

    or

    If Not oCell.Value Is Nothing Then

     

     

     

    Friday, May 12, 2006 2:31 AM
  • Hi,

    Have a look to this article 'DataGridViewPrinter Class':

    http://www.codeproject.com/csharp/datagridviewprinter.asp

     


    Salan

    Thursday, May 18, 2006 9:02 PM
  • Hi,

    Great Code! I Try to modify it because I need that it don't print a column if the property visible is set to false ... but I can't resolve the problem!

    Anyone can help me?! Thanks so much :)

    P.S. I Apologise for my bad english!

    Monday, June 12, 2006 11:06 AM
  • Hi Frankie,

    Next time if you have question regarding the DataGridViewPrinter class, try to post it in the article page of that class:

    http://www.codeproject.com/csharp/datagridviewprinter.asp

    However, to solve your problem, just insert the below code in the beginning of the Calculate function of the class:

    foreach (DataGridViewColumn col in TheDataGridView.Columns)

        col.Visible = true;

     

    Salan..

    Tuesday, June 13, 2006 8:54 AM
  • Excellent piece of code, does exactly what it is supposed to do, did have problem with not displaying last row but the deleteing of the -1 off count fixed problem. Thank you
    Friday, June 16, 2006 12:17 PM
  • After reading this post, I decided to give it the Print Grid solution a try (by will_affinity).  I was able to get it to work.  The Print Preview, Print Dialog, and Page Setup all worked as advertised, but I did rub into a slight problem that I am hoping someone in this discussion board can help me with.

    If I select Print Preview, then close that window and select Page Setup and Perform another Print Preview, the grid maintains the same width as in Portrait.  Whereas, if I start the program over, select Page Setup, change to Landscape, select Print Preview (document looks ok), select Page Setup, select Portrait, select Print Preview (document looks good), select Page Setup, change to Landscape, select Print Preview (document has bad margins again).

    I'm sure this is not the best way to discribe what is happening, but since I am not to sure what I need to look for ...Oh well.  I guess I sound confused and lost because I am.  I have only been using Visual Basic (VS 2005) for about 6 months now, and I know I've only scratched the surface on what this stuff is capable of.  Anyway, any help, comments, or directions would be greatly appreciated.  Thank you in advance for your time and effort.

    Friday, June 30, 2006 7:40 PM
  • There's a problem with printing out the footer. It messes up the page number if the page has fewer than the max number of rows. For example, I had 38 rows spread over two pages, the first page said "Page 1 of 2" but the last one would say "Page 2 of 13" since there were only 3 rows on the final page. Either way, I've 'Option Stricted' and turned it into a class unto itself. Enjoy!

    To Implement:
        Private Sub btnPrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintPreview.Click
            If IsNothing(Printer) Then
                Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
            End If
            Printer.ShowPrintPreviewDialog()
        End Sub

        Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
            If IsNothing(Printer) Then
                Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
            End If
            Printer.Print()
        End Sub

    Public Class Printer
        Private oStringFormat As StringFormat
        Private oStringFormatComboBox As StringFormat
        Private oButton As Button
        Private oCheckbox As CheckBox
        Private oComboBox As ComboBox

        Private nTotalWidth As Int16
        Private nRowPos As Int16
        Private NewPage As Boolean
        Private nPageNo As Int16
        Private Header As String
        Private sUserName As String
        Private nPageCount As Integer = 0
        Private dgv As DataGridView
        Private WithEvents PrintDoc As New Printing.PrintDocument
        Private storedPageSettings As Printing.PageSettings = New Printing.PageSettings()

        Property DataGridViewToPrint() As DataGridView
            Get
                Return dgv
            End Get
            Set(ByVal value As DataGridView)
                dgv = value
            End Set
        End Property
        Property UserName() As String
            Get
                Return sUserName
            End Get
            Set(ByVal value As String)
                sUserName = value
            End Set
        End Property
        Property HeaderText() As String
            Get
                Return Header
            End Get
            Set(ByVal value As String)
                Header = value
            End Set
        End Property

        Public Sub New(ByVal aDGV As DataGridView, ByVal aHeader As String, ByVal aUserName As String)
            DataGridViewToPrint = aDGV
            UserName = aUserName
            HeaderText = aHeader
        End Sub
        Public Sub Print()
            Dim psDlg As New PageSetupDialog
            psDlg.PageSettings = storedPageSettings
            psDlg.ShowDialog()
        End Sub
        Public Sub ShowPrintPreviewDialog()
            Dim dlg As New PrintPreviewDialog()
            dlg.Document = PrintDoc
            dlg.ShowDialog()
        End Sub
        Private Sub PrintDoc_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDoc.BeginPrint

            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter

            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox

            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                nTotalWidth = CShort(nTotalWidth + oColumn.Width)

            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0

        End Sub

        Private Sub Printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage

            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16

            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = CShort(e.MarginBounds.Top)
            Dim nLeft As Int16 = CShort(e.MarginBounds.Left)

            If nPageNo = 1 Then

                For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                    nHeight = CShort(e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11)

                    oColumnLefts.Add(nLeft)
                    oColumnWidths.Add(nWidth)
                    oColumnTypes.Add(oColumn.GetType)
                    nLeft += nWidth

                Next

            End If

            Do While nRowPos < DataGridViewToPrint.Rows.Count

                Dim oRow As DataGridViewRow = DataGridViewToPrint.Rows(nRowPos)

                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                    DrawFooter(e, nRowsPerPage)

                    NewPage = True
                    nPageNo = CShort(nPageNo + 1)
                    e.HasMorePages = True
                    Exit Sub

                Else

                    If NewPage Then

                        ' Draw Header
                        e.Graphics.DrawString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        ' Draw Columns
                        nTop = CShort(e.MarginBounds.Top)
                        i = 0
                        For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
                            i = CShort(i + 1)

                        Next
                        NewPage = False

                    End If

                    nTop += nHeight
                    i = 0
                    For Each oCell As DataGridViewCell In oRow.Cells

                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                            oButton.Text = oCell.Value.ToString
                            oButton.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                            oCheckbox.Size = New Size(14, 14)
                            oCheckbox.Checked = CType(oCell.Value, Boolean)
                            Dim oBitmap As New Bitmap(CInt(oColumnWidths(i)), nHeight)
                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                            oComboBox.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CInt(oColumnLefts(i)) + 1, nTop, CInt(oColumnWidths(i)) - 16, nHeight), oStringFormatComboBox)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                            Dim oCellSize As Rectangle = New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight)
                            Dim oImageSize As Size = CType(oCell.Value, Image).Size
                            e.Graphics.DrawImage(CType(oCell.Value, Image), New Rectangle(CType(oColumnLefts(i), Int32) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                        End If

                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))

                        i = CShort(i + 1)

                    Next

                End If

                nRowPos = CShort(nRowPos + 1)
                nRowsPerPage = CShort(nRowsPerPage + 1)
            Loop

            DrawFooter(e, nRowsPerPage)

            e.HasMorePages = False

        End Sub

        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

            'Changed from Page XXX of XXX to just Page XXX because
            'Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString() would generate
            'inaccurate page numbers on pages with less than the max number of rows (ie: the last page)
            'Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString
            Dim sPageNo As String = "Page " + nPageNo.ToString

            ' Right Align - User Name
            e.Graphics.DrawString("Printed by: " + sUserName, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

        End Sub
    End Class

    Tuesday, July 04, 2006 7:39 PM
  • hey,

    i tried your code but it is giving me compiling errors

    Error 1 Handles clause requires a WithEvents variable defined in the containing type or one of its base {ERROR OCCURED IN BTN[PREVIEW CLICK EVENT}

    Error 2 'Printer' is a type and cannot be used as an expression. {IN THE SAME EVENT :

    If IsNothing(Printer) Then

    Printer = New Printer(DataGridView1, Me.Text, "shrey") 'DataGridView, Wiindow Title (as the Page Header), Username

    End If

    Printer.ShowPrintPreviewDialog()

    }

    Error 8 Reference to a non-shared member requires an object reference. 

    Printer.Print()

    Could you help me i am new at vb.

    thnks in advance

    Shrey Sharma

    Tuesday, July 11, 2006 3:03 PM
  • DrawFooter(e, nPageNo);

    after the main row loop rather than

    DrawFooter(e, nRowsPerPage);

    eliminates the problem when the page has fewer than the max rows too.

     

     

     

    Monday, July 31, 2006 6:36 AM
  • How do I call this from a button?

    Regards

    Sabe75

    Wednesday, August 09, 2006 11:55 AM
  • Thanks Guys,

    Its a really a great code. My heartful Thanks to those guys who did the program. please update for new codings and projects.

    vimalbtechit2005@gmail.com

    Vimal.

     

    Monday, August 21, 2006 11:30 AM
  • Hey I am relativly new to VB.Net, love the code, just one question. I have a DGV with 24 columns, I do not want to print all the columns how could I set it up just to print the first 9 columns? Please help thanks in advance!
    Monday, October 16, 2006 3:00 AM
  • Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString


    I changed the above code in Sub DrawFooter  to:

    ________________________________________________________________________

    Dim sPageNo As String

    If blnGotNumPages = False Then

    blnGotNumPages = True

    strNumOfPages = Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

    sPageNo = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

    Else

    sPageNo = nPageNo.ToString + " of " + strNumOfPages

    End If

    ______________________________________________________________________________________________

    Ofcourse I declared blnGotNumPages and strNumOfPages outside of the Sub, and made blnGotNumPages = False when the print Preview btn was clicked.

    This solution will give you Page x of y correctly. Even for the last page. I hope this was helpful to some of you all.

    Thomas

     

    Thursday, November 16, 2006 3:39 PM
  • Getting the same errors, did anyone figure it out?
    Printer is a class. Cant imagine why it would bring the error:

    'Printer' is a type and cannot be used as an expression.

    Thanks.
    Thursday, December 07, 2006 4:09 PM
  • Hi,

    Hi, I like the Code and I also saw the code project Printing class. Here is a version that uses static methods and auto generates the print document internally. This way you can just call: PrintFactory.Print() or PrintFactory.Preview() from anywhere and not worry about instances. Obviously, you can expand on this code in a million ways, but it is start for clean library for datagridview printing.

    Imports System.Windows.Forms

    Public Class PrintFactory

    #Region "Instance"

    #Region "Declerations"

    Private WithEvents _printDocument As Printing.PrintDocument = _

    New Printing.PrintDocument()

    Private _dgv As DataGridView

    Private _stringFormat As StringFormat

    Private _stringFormatComboBox As StringFormat

    Private _button As Button

    Private _checkBox As CheckBox

    Private _comboBox As ComboBox

    Private _totalWidth As Int16

    Private _rowPos As Int16

    Private _newPage As Boolean

    Private _pageNumber As Int16

    Private _userName As String

    Private _headerText As String

    #End Region

    #Region "Properties"

    Private ReadOnly Property DGV() As DataGridView

    Get

    Return _dgv

    End Get

    End Property

    Private Property HeaderText() As String

    Get

    Return _headerText

    End Get

    Set(ByVal value As String)

    _headerText = value

    End Set

    End Property

    Private Property UserName() As String

    Get

    Return _userName

    End Get

    Set(ByVal value As String)

    _userName = value

    End Set

    End Property

    Private Property StringFormat() As StringFormat

    Get

    Return _stringFormat

    End Get

    Set(ByVal value As StringFormat)

    _stringFormat = value

    End Set

    End Property

    Private Property StringFormatComboBox() As StringFormat

    Get

    Return _stringFormatComboBox

    End Get

    Set(ByVal value As StringFormat)

    _stringFormatComboBox = value

    End Set

    End Property

    Private Property Button() As Button

    Get

    Return _button

    End Get

    Set(ByVal value As Button)

    _button = value

    End Set

    End Property

    Private Property CheckBox() As CheckBox

    Get

    Return _checkBox

    End Get

    Set(ByVal value As CheckBox)

    _checkBox = value

    End Set

    End Property

    Private Property ComboBox() As ComboBox

    Get

    Return _comboBox

    End Get

    Set(ByVal value As ComboBox)

    _comboBox = value

    End Set

    End Property

    Private Property TotalWidth() As Int16

    Get

    Return _totalWidth

    End Get

    Set(ByVal value As Int16)

    _totalWidth = value

    End Set

    End Property

    Private Property RowPos() As Int16

    Get

    Return _rowPos

    End Get

    Set(ByVal value As Int16)

    _rowPos = value

    End Set

    End Property

    Private Property NewPage() As Boolean

    Get

    Return _newPage

    End Get

    Set(ByVal value As Boolean)

    _newPage = value

    End Set

    End Property

    Private Property PageNumber() As Int16

    Get

    Return _pageNumber

    End Get

    Set(ByVal value As Int16)

    _pageNumber = value

    End Set

    End Property

    #End Region

    Private Sub New(ByVal userName As String, _

    ByVal headerText As String)

    Me._userName = userName

    Me._headerText = headerText

    End Sub

    Private Sub _printDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles _printDocument.PrintPage

    EndPrint(Me, e)

    End Sub

    #End Region

    #Region "Statics"

    Public Shared Function Print(ByVal dgv As DataGridView, _

    ByVal userName As String, _

    ByVal headerText As String) As Boolean

    Validate(dgv, userName, headerText)

    Dim tempPrintFactory As PrintFactory = BeginPrint(dgv, userName, headerText)

    tempPrintFactory._printDocument.Print()

    End Function

    Public Shared Function Preview(ByVal dgv As DataGridView, _

    ByVal userName As String, _

    ByVal headerText As String) As Boolean

    Validate(dgv, userName, headerText)

    Dim tempPrintFactory As PrintFactory = BeginPrint(dgv, userName, headerText)

    Dim tempPrintDiag As New PrintPreviewDialog()

    tempPrintDiag.Document = tempPrintFactory._printDocument

    tempPrintDiag.ShowDialog()

    End Function

    Private Shared Function BeginPrint(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String) As PrintFactory

    Dim printEntity As PrintFactory = New PrintFactory(userName, headerText)

    printEntity._dgv = dgv

    printEntity.StringFormat = New StringFormat

    printEntity.StringFormat.Alignment = StringAlignment.Near

    printEntity.StringFormat.LineAlignment = StringAlignment.Center

    printEntity.StringFormat.Trimming = StringTrimming.EllipsisCharacter

    printEntity.StringFormatComboBox = New StringFormat

    printEntity.StringFormatComboBox.LineAlignment = StringAlignment.Center

    printEntity.StringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap

    printEntity.StringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

    printEntity.Button = New Button

    printEntity.CheckBox = New CheckBox

    printEntity.ComboBox = New ComboBox

    printEntity.TotalWidth = 0

    For Each oColumn As DataGridViewColumn In dgv.Columns

    printEntity.TotalWidth += oColumn.Width

    Next

    printEntity.PageNumber = 1

    printEntity.NewPage = True

    printEntity.RowPos = 0

    Return printEntity

    End Function

    Private Shared Function EndPrint(ByVal printEntity As PrintFactory, _

    ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean

    Dim oColumnLefts As New ArrayList

    Dim oColumnWidths As New ArrayList

    Dim oColumnTypes As New ArrayList

    Dim nHeight As Int16

    Dim nWidth, i, nRowsPerPage As Int16

    Dim nTop As Int16 = e.MarginBounds.Top

    Dim nLeft As Int16 = e.MarginBounds.Left

    If printEntity.PageNumber = 1 Then

    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

    nWidth = CType(Math.Floor(oColumn.Width / printEntity.TotalWidth * printEntity.TotalWidth * (e.MarginBounds.Width / printEntity.TotalWidth)), Int16)

    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

    oColumnLefts.Add(nLeft)

    oColumnWidths.Add(nWidth)

    oColumnTypes.Add(oColumn.GetType)

    nLeft += nWidth

    Next

    End If

    Do While printEntity.RowPos < printEntity.DGV.Rows.Count - 1

    Dim oRow As DataGridViewRow = printEntity.DGV.Rows(printEntity.RowPos)

    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

    DrawFooter(printEntity.DGV, printEntity, nRowsPerPage, e)

    printEntity.NewPage = True

    printEntity.PageNumber += 1

    e.HasMorePages = True

    Exit Function

    Else

    If printEntity.NewPage Then

    ' Draw Header

    e.Graphics.DrawString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

    ' Draw Columns

    nTop = e.MarginBounds.Top

    i = 0

    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

    e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

    e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

    i += 1

    Next

    printEntity.NewPage = False

    End If

    nTop += nHeight

    i = 0

    For Each oCell As DataGridViewCell In oRow.Cells

    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

    printEntity.Button.Text = oCell.Value.ToString

    printEntity.Button.Size = New Size(oColumnWidths(i), nHeight)

    Dim oBitmap As New Bitmap(printEntity.Button.Width, printEntity.Button.Height)

    printEntity.Button.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))

    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

    printEntity.CheckBox.Size = New Size(14, 14)

    printEntity.CheckBox.Checked = CType(oCell.Value, Boolean)

    Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)

    Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)

    oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))

    printEntity.CheckBox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - printEntity.CheckBox.Width) / 2, Int32), CType((oBitmap.Height - printEntity.CheckBox.Height) / 2, Int32), printEntity.CheckBox.Width, printEntity.CheckBox.Height))

    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

    printEntity.ComboBox.Size = New Size(oColumnWidths(i), nHeight)

    Dim oBitmap As New Bitmap(printEntity.ComboBox.Width, printEntity.ComboBox.Height)

    printEntity.ComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))

    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), printEntity.StringFormatComboBox)

    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

    Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)

    Dim oImageSize As Size = CType(oCell.Value, Image).Size

    e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

    End If

    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

    i += 1

    Next

    End If

    printEntity.RowPos += 1

    nRowsPerPage += 1

    Loop

    DrawFooter(printEntity.DGV, printEntity, nRowsPerPage, e)

    e.HasMorePages = False

    End Function

    Private Shared Function DrawFooter(ByVal dgv As DataGridView, _

    ByVal printEntity As PrintFactory, _

    ByVal RowsPerPage As Int32, _

    ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean

    Dim sPageNo As String = printEntity.PageNumber.ToString + " of " + Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString

    ' Right Align - User Name

    e.Graphics.DrawString(printEntity.UserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

    ' Left Align - Date/Time

    e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

    ' Center - Page No. Info

    e.Graphics.DrawString(sPageNo, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

    End Function

    Private Shared Sub Validate(ByVal dgv As DataGridView, _

    ByVal userName As String, _

    ByVal headerText As String)

    If dgv Is Nothing Then

    Throw New ArgumentNullException("dgv")

    End If

    If String.IsNullOrEmpty(userName) = True Then

    Throw New ArgumentNullException("userName")

    End If

    If String.IsNullOrEmpty(headerText) = True Then

    Throw New ArgumentNullException("headerText")

    End If

    End Sub

    #End Region

    End Class

    Wednesday, January 31, 2007 4:37 PM
  • I like this code but I seem to be having issues with an error.  Have you experienced this one.

    Index was out of range. Must be non-negative and less than the size of the collection.
    The error is in the EndPrint function.

    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

    Error in this line >>>> e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

    e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

    i += 1

    Next

     

    Friday, March 02, 2007 9:32 PM
  •  

     Hi,

     I have tried your code. It is working very well. I wanted one enhancement in that.

     I tried even but that code after modification seems to be meshy. If you please look into what is my requirement and yes how it would be adjusted in the similar code.

    The requirement is : It should print the grid element like excel which means it should split the column after it reaches to page bounds.

     

     

    Wednesday, March 14, 2007 10:21 AM
  • sorry, it doesn't solve the problem.

    what I do it just change a little code in "Sub Printdoc_PrintPage"

    from

    Do While nRowPos < DataGridViewToPrint.Rows.Count

    to

    Do While nRowPos < DataGridViewToPrint.Rows.Count - 1

    Monday, March 26, 2007 12:12 PM
  •  

    Thanks to all that have contributed to this code.

     

    I had an issue with Forkbeard's code and the hardcopy document not actually printing.

     

    So I changed the "Print" subrouting in the above code to:-

     

    Code Snippet

    Public Sub Print()

     

    ' Remmed srowan 20070403. Forkbeard's original code posted to MSDN forum is below and commented.

    'Dim psDlg As New PageSetupDialog

    'psDlg.PageSettings = storedPageSettings

    'psDlg.ShowDialog()

     

    ' Modified srowan 20070403. Above code was not printing the document. Modified to perform action after showing the dialog. Also changed from Page Setup Dialog to Printer Dialog.

    Dim dlg As New PrintDialog()

    dlg.Document = PrintDoc

    Dim result As DialogResult = dlg.ShowDialog()

     

    If (result = System.Windows.Forms.DialogResult.OK) Then

    PrintDoc.Print()

    End If

     

    End Sub

     

    Regards,


    Scott

    Tuesday, April 03, 2007 1:02 AM
  • hellow!! I am new in VB2005 and i really have no idea about it..My on the job training superior ask me to make a program..I already finish some of the parts except the printing...I only used rich textbox, the copy/paste command the problem is the alignment.

    please reply... thanks alot..godbless

    Tuesday, April 10, 2007 7:35 AM
  • Just replace

    Do While nRowPos < DataGridView1.Rows.Count - 1

    with

    Do While nRowPos < DataGridView1.Rows.Count

     

    Tuesday, May 29, 2007 11:52 AM
  •  

    I've got a problem where one of the columns in the datagridview displays ONLY the date, but the print is printing the date plus '00:00:00'

     

    Can anyone help me please with the code to displaying only the date in a format of 'dd/mm/yy' to the print document?

     

    Thanks

    Monday, June 18, 2007 12:59 PM
  • Just starting with VB Express

    This helped a lot.

    Have found that you need to destroy the static variables when finished or the next time you print preview it uses the same value even if you change the column width s etc.

    Also found that you need to check for actual cell contents before printing text from a cell.

    Easy done.

    Great bit of code.
    Wednesday, July 25, 2007 11:54 AM
  • The static approach is interesting. Buster has another approach using vb, that prints the grid as seen on the screen.

    I've modified it for c# too.

    Tuesday, August 07, 2007 11:29 AM
  • hey all. after long time and nearly null results on vb2005 and datagridview printing. i found this thread.. all works ok with some minor modifications.. but one or two problems still persists.

     

    if too many columns then it squizes everything in one page.. cant get it on a second.. (not for rows.. but for columns)

    and after that. if i preview lets say 5 columns and then 2.. the width of the table gets the whole page.. although its good in the beginning..

     

     

    any help would be greatly appreciated..

     

    as for the part that wouldnt print on landscape.. had the same problem as well nd i just got

    e.PageSettings.Landscape = True

     

    on the query page settings. or u can even get ur own radiobuttons for the user to have a choice..

     

    thank u in advance

    Friday, August 31, 2007 11:55 AM
  •  

    FTAO Will_Affinity

    Your brain must be the size of a moon. I've copied your code into my program and it works perfect.

    I can't thank you enough, you've saved me hours of headaches. If i could afford it i'd send you a cheque.

     

    NoZparker

    Thursday, September 06, 2007 10:04 AM
  • I'm still having trouble here.

    The cell contents is only displaying the date format, which is what I want.

    But when I do a print preview, it displays the date as well as '00:00:00'. 

    I'd like to remove the time.

    Everything else works perfectly.

     

    • Proposed as answer by vancryce Tuesday, April 27, 2010 11:34 PM
    Thursday, September 06, 2007 6:37 PM
  • Hi folks, there is a free component that gives the printing functionality. This is something like pluggin for the DataGridView control itself - it just wraps it - also it gives you the functionalities of searching for an item in the DataGridView control, exporting data to HTML, Excel and Pdf and many more ...

    Check it out on http://www.completit.com/Products/DGVE/Overview.aspx

     

    It thing that a lot ot hard work is done there.

    Wednesday, December 12, 2007 8:04 AM
  • Was a great post! I just paste it and works! Thank You Very Much
    Still I have some question for you. How should I do if I want the Header to be multiline. like:
    Title of the page
    Subtitle of the page
    Another thing where do I put the code so I can print it on landscape?
    And the last how can I manage the cell borders.
    Thats it, than you again for a great code.

    Wednesday, January 23, 2008 9:38 PM
  • How did you solve this problem?

    Tuesday, February 19, 2008 2:05 PM
  • I started with a need to print a DataGridView a couple of years ago and went down several pathways. However, I recently discovered a very sweet solution for printing a DataGridView and many other .Net objects. It is the Reporting Services control available for Visual Studio 2005 (Its also in 2008 but has a nasty bug!). It is an almost trivial task to construct a class to organises the DataGrid contents as a datasource to an RDL (Report Definition Language) based report. The RDL report has good capabilities for formatting, sorting, totalling, etc. Once the report is rendered to the user's screen, the user is able to print it, output to PDF or Excel. A really neat bit is the ability to created a drilldown report which puts more control back into the user's hands.

    Do not get confused with server side reporting using Reporting Services. The VS control does not require any SQL Server components or licences. It is described with SQL Server Reporting Services because the RDL syntax and capabilities are almost identical.

     

    Tuesday, February 19, 2008 9:42 PM
  • Does anyone know how to solve the Handles PrintDocument1.PrintPage problem?

     

    Thanks

    Wednesday, April 02, 2008 9:38 PM
  • Here you are a tool which can help you: GridDrawer.Net

     

    Sunday, April 27, 2008 8:28 PM
  •  My datagridveiw works perfect wth the above original code. except with the blank cell whicth returns an error. the above is still great

    Thank you.

     

    Tuesday, July 01, 2008 5:59 AM
  •  

    Hi,

    Great work and really good one. But One suggetion, is it possible to convert to .NET 2.0.

    Why because, Your control will be more usefull, If it is available for .NET 2.0 Applications. Please make it available, then it will be great.

    Wednesday, July 02, 2008 3:42 PM
  • How did you fix the previous Handles PrintDocument1.PrintPage problem? I've got the same message.

    Saturday, July 05, 2008 10:27 AM
  • This is great.  One question.  How would i change the page settings so that i could change the paper type.  I would like to be able to use this to print without a preview.  how would i do that?  thanks!
    Sunday, July 06, 2008 6:21 PM
  • How can i change columns width (for printing)? some of columns has wraper strings...
    Wednesday, August 06, 2008 2:37 PM
  • If my understanding of this is correct You have to change the datagridview so that you can view the whole collum contents. The code just looks at the width of the collum that is viewed not the total of the contents. So adjust your collum width of data grid view so that when you see the data on screen you see all of it. Then the print routine will see the correct width. Hope this helps.

     

    Wednesday, August 13, 2008 7:50 PM
  •  

    I am busy for a few month with a library which could help you to print DataGridView contents.

     

    see http://www.codeplex.com/PrintDataGridView and enjoy (I hope) Wink

    Wednesday, August 13, 2008 8:05 PM
  • Another small fix:

    ' Right Align - User Name

    e.Graphics.DrawString(sUserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sUserName, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

     

    Tuesday, August 19, 2008 12:08 PM
  • My friend connect . . .

     

    i have a problem. . .

     

    im using vb2008, and your code works great

     

    but i have one problem with your code :

     

    Dim psDlg As New PageSetupDialog

    Dim storedPageSettings As PageSettings = New PageSettings()

    psDlg.PageSettings = storedPageSettings

    psDlg.ShowDialog()

     

     

    that do not compile, i think there is a typo but i cannot find where . . .

    the vb2008 do not even know pagesettings . . .

     

    so this is my question

     

    1. a) do you have an updated solution on how to print a grid from a form?
    2. b) can you fix this code
    3. c) how do i relate the page setupdialog with the print document?

     

    my preview looks good, but the margings are too big, making some columns display too small

     

    d) id there anyway to hide some columns . . .

     

    Mr. White. . .

    Monday, September 15, 2008 9:28 PM
  •  

    May be you could try the solution I implemented...

    http://www.codeplex.com/PrintYourGridsDotNet

     

     

    Have a nice evening

    Monday, September 15, 2008 9:35 PM
  • Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint


    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage



    I too am getting the Handles clause requires a WithEvents variable defined in the containing type or one of its base types. error.  Can someone please explain what those of us (there seem to be several) who are getting this message are missing? 
    Tuesday, September 16, 2008 5:13 AM
  • I have taken snippits from all over this forum and have been successful in printing out my datagrid exactly how i want it.

    i can print :-

    All

    Odds

    Evens

    Ranges

    and Single Pages (all done by the coding)

     

    However, the amount of pages i need to print out are in excess of 300 pages

     

    When I print, the printer only seems to have enough memory for about 100 pages. I then have to start the printing again using the range of pages from say 100 on.

     

    Alternatively in the printer set up I can set the print to print direct, This of coarse sends each page to the printer 1 at a time, which is holding up resources.

     

    Can anyone suggest a solution so that i can print all 300 pages at the same time.

     

    Friday, September 19, 2008 11:56 AM
  • Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

     

    &

     

    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

     

    To solve them simply add (double click or drag and drop) a PrintDocument to your project found in the toolbox

     

    For making a Page Setup, followed by a Print Preview Dialog Box that uses your input in the Page Setup you can use this...

     

    'Place these lines after the Public Class (Name of Form)

    Public DefaultPageSettings As PageSettings = New PageSettings()

    Public StringPageNo As String

    Public StringNumberOfPages As String

    Public BooleanNumOfPages As Boolean

     

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

    Dim PageSetupDialog1 As New PageSetupDialog

    PageSetupDialog1.PageSettings = DefaultPageSettings

    PageSetupDialog1.ShowDialog()

    Dim PrintPreviewDialog1 As New PrintPreviewDialog()

    BooleanNumberOfPages = False

    PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings

    PrintPreviewDialog1.Document = PrintDocument1

    PrintPreviewDialog1.ShowDialog()

    End Sub

     

    'Place these if you a Footer (Page x of y)

    If GotNumberOfPages = False Then

    StringNumberOfPages = Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

    GotNumberOfPages = True

    End If

    StringPageNo = NumberPageNumber.ToString + " of " + StringNumOfPages

     

    Just remember that the Variables can provide an error if they won't match your project
    Monday, October 13, 2008 4:37 PM
  •  

    I want to know how I can call this code.

     

    Call PrintDocument1_BeginPrint(sender, e)???

    Monday, October 20, 2008 4:03 AM
  •  

    in any button

    document1.print

    in fact if you have the correct imports at the top just ouside the class declaration you should see a list

    of items when you type document1 followed by a dot (document1.)

    Friday, October 24, 2008 5:22 PM
  • ok the following :
    1-have CoNNect fix "no print last row"
    2- print only VISIBLE columns


    Private oStringFormat As StringFormat
    Private oStringFormatComboBox As StringFormat
    Private oButton As Button
    Private oCheckbox As CheckBox
    Private oComboBox As ComboBox

    Private nTotalWidth As Int16
    Private nRowPos As Int16
    Private NewPage As Boolean
    Private nPageNo As Int16
    Private Header As String = "Header Test"
    Private sUserName As String = "Will"

    Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

    oStringFormat = New StringFormat
    oStringFormat.Alignment = StringAlignment.Near
    oStringFormat.LineAlignment = StringAlignment.Center
    oStringFormat.Trimming = StringTrimming.EllipsisCharacter

    oStringFormatComboBox = New StringFormat
    oStringFormatComboBox.LineAlignment = StringAlignment.Center
    oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
    oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

    oButton = New Button
    oCheckbox = New CheckBox
    oComboBox = New ComboBox

    nTotalWidth = 0
    For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    If oColumn.Visible = True Then
    nTotalWidth += oColumn.Width
    End If

    Next
    nPageNo = 1
    NewPage = True
    nRowPos = 0

    End Sub

    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

    Static oColumnLefts As New ArrayList
    Static oColumnWidths As New ArrayList
    Static oColumnTypes As New ArrayList
    Static nHeight As Int16

    Dim nWidth, i, nRowsPerPage As Int16
    Dim nTop As Int16 = e.MarginBounds.Top
    Dim nLeft As Int16 = e.MarginBounds.Left

    If nPageNo = 1 Then

    For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    If oColumn.Visible = True Then
    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

    oColumnLefts.Add(nLeft)
    oColumnWidths.Add(nWidth)
    oColumnTypes.Add(oColumn.GetType)
    nLeft += nWidth
    End If
    Next

    End If

    Do While nRowPos < DataGridView1.Rows.Count - 1

    Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

    DrawFooter(e, nRowsPerPage)

    NewPage = True
    nPageNo += 1
    e.HasMorePages = True
    Exit Sub

    Else

    If NewPage Then

    ' Draw Header
    e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

    ' Draw Columns
    nTop = e.MarginBounds.Top
    i = 0
    For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    If oColumn.Visible = True Then
    e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
    i += 1
    End If

    Next
    NewPage = False

    End If

    nTop += nHeight
    i = 0
    For Each oCell As DataGridViewCell In oRow.Cells
    If oCell.Visible = True Then
    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

    oButton.Text = oCell.Value.ToString
    oButton.Size = New Size(oColumnWidths(i), nHeight)
    Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
    oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

    oCheckbox.Size = New Size(14, 14)
    oCheckbox.Checked = CType(oCell.Value, Boolean)
    Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
    Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
    oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

    oComboBox.Size = New Size(oColumnWidths(i), nHeight)
    Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
    oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

    Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
    Dim oImageSize As Size = CType(oCell.Value, Image).Size
    e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

    End If

    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

    i += 1
    End If
    Next

    End If

    nRowPos += 1
    nRowsPerPage += 1

    Loop

    DrawFooter(e, nRowsPerPage)

    e.HasMorePages = False

    End Sub

    Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

    Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

    ' Right Align - User Name
    e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

    ' Left Align - Date/Time
    e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

    ' Center - Page No. Info
    e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

    End Sub
    Monday, November 03, 2008 1:21 PM
  • yababer, thank you for your post, I like being able to call PrintFactory.Print() to print the dataGridView. I was having some problems with your code and have fixed them. The things that I improved were

    1. Don't print columns that are not set to visible
    2. Fixed the page numbers
    3. Added the ability to print in Landscape

    I can view the document in print preview but when I press the print button in print preview it does not print the datagridview. If anyone can fix this please let me know.

    To implement create a class called PrintFactory and copy the code below into the class. To print use  
    PrintFactory.Print(Me.DataGridView1, "Username", "Header", "L") the "L" will print in landscape, any other text string will print in portrait.
    Print Preview
    PrintFactory.Preview(Me.DataGridView1, "Username", "Header", "L")

    Imports System.Windows.Forms
    Public Class PrintFactory
    #Region "Instance"

    #Region "Declerations"

    Private WithEvents _printDocument As Printing.PrintDocument = New Printing.PrintDocument()
    Private _dgv As DataGridView
    Private _stringFormat As StringFormat
    Private _stringFormatComboBox As StringFormat
    Private _button As Button
    Private _checkBox As CheckBox
    Private _comboBox As ComboBox
    Private _totalWidth As Int16
    Private _rowPos As Int16
    Private _newPage As Boolean
    Private _pageNumber As Int16
    Private _userName As String
    Private _headerText As String
    Private _blnGotNumPages As Boolean
    Private _strNumOfPages As String
    Private _orientation As String

    #End Region

    #Region "Properties"

    Private ReadOnly Property DGV() As DataGridView
    Get
    Return _dgv
    End Get
    End Property

    Private Property HeaderText() As String
    Get
    Return _headerText
    End Get

    Set(ByVal value As String)
    _headerText = value
    End Set

    End Property

    Private Property UserName() As String

    Get
    Return _userName
    End Get

    Set(ByVal value As String)
    _userName = value
    End Set
    End Property

    Private Property StringFormat() As StringFormat
    Get
    Return _stringFormat
    End Get

    Set(ByVal value As StringFormat)
    _stringFormat = value
    End Set
    End Property

    Private Property StringFormatComboBox() As StringFormat
    Get
    Return _stringFormatComboBox
    End Get

    Set(ByVal value As StringFormat)
    _stringFormatComboBox = value
    End Set
    End Property

    Private Property Button() As Button

    Get
    Return _button
    End Get

    Set(ByVal value As Button)
    _button = value
    End Set
    End Property

    Private Property CheckBox() As CheckBox
    Get
    Return _checkBox
    End Get

    Set(ByVal value As CheckBox)
    _checkBox = value
    End Set
    End Property

    Private Property ComboBox() As ComboBox
    Get
    Return _comboBox
    End Get

    Set(ByVal value As ComboBox)
    _comboBox = value
    End Set
    End Property

    Private Property TotalWidth() As Int16
    Get
    Return _totalWidth
    End Get

    Set(ByVal value As Int16)
    _totalWidth = value
    End Set
    End Property

    Private Property RowPos() As Int16
    Get
    Return _rowPos
    End Get

    Set(ByVal value As Int16)
    _rowPos = value
    End Set
    End Property

    Private Property NewPage() As Boolean
    Get
    Return _newPage
    End Get

    Set(ByVal value As Boolean)
    _newPage = value
    End Set
    End Property

    Private Property PageNumber() As Int16
    Get
    Return _pageNumber
    End Get

    Set(ByVal value As Int16)
    _pageNumber = value
    End Set
    End Property
    Private Property strNumOfPages() As String
    Get
    Return _strNumOfPages
    End Get

    Set(ByVal value As String)
    _strNumOfPages = value
    End Set
    End Property
    Private Property blnGotNumPages() As Boolean
    Get
    Return _blnGotNumPages
    End Get

    Set(ByVal value As Boolean)
    _blnGotNumPages = value
    End Set
    End Property
    Private Property orientation() As String

    Get
    Return _orientation
    End Get

    Set(ByVal value As String)
    _orientation = value
    End Set
    End Property
    #End Region

    Private Sub New(ByVal userName As String, ByVal headerText As String)
    Me._userName = userName
    Me._headerText = headerText
    End Sub

    Private Sub _printDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles _printDocument.PrintPage
    EndPrint(Me, e)
    End Sub

    #End Region

    #Region "Statics"

    Public Shared Function Print(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
    Validate(dgv, userName, headerText)
    Dim tempPrintFactory As PrintFactory
    tempPrintFactory = BeginPrint(dgv, userName, headerText)
    If orientation = "L" Then
    tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
    End If
    tempPrintFactory._printDocument.Print()
    End Function

    Public Shared Function Preview(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
    Validate(dgv, userName, headerText)
    Dim tempPrintFactory As PrintFactory
    tempPrintFactory = BeginPrint(dgv, userName, headerText)
    If Orientation = "L" Then
    tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
    End If
    Dim tempPrintDiag As New PrintPreviewDialog()
    tempPrintDiag.Document = tempPrintFactory._printDocument
    tempPrintDiag.ShowDialog()
    End Function

    Private Shared Function BeginPrint(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String) As PrintFactory
    Dim printEntity As PrintFactory = New PrintFactory(userName, headerText)
    printEntity._dgv = dgv
    printEntity.StringFormat = New StringFormat
    printEntity.StringFormat.Alignment = StringAlignment.Near
    printEntity.StringFormat.LineAlignment = StringAlignment.Center
    printEntity.StringFormat.Trimming = StringTrimming.EllipsisCharacter
    printEntity.StringFormatComboBox = New StringFormat
    printEntity.StringFormatComboBox.LineAlignment = StringAlignment.Center
    printEntity.StringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
    printEntity.StringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
    printEntity.Button = New Button
    printEntity.CheckBox = New CheckBox
    printEntity.ComboBox = New ComboBox
    printEntity.TotalWidth = 0

    For Each oColumn As DataGridViewColumn In dgv.Columns
    printEntity.TotalWidth += oColumn.Width
    Next
    printEntity.PageNumber = 1
    printEntity.NewPage = True
    printEntity.RowPos = 0
    Return printEntity
    End Function

    Private Shared Function EndPrint(ByVal printEntity As PrintFactory, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
    Static oColumnLefts As New ArrayList
    Static oColumnWidths As New ArrayList
    Static oColumnTypes As New ArrayList
    Static nHeight As Int16

    Dim nWidth, i, nRowsPerPage As Int16
    Dim blnGotNumPages As Boolean
    Dim strNumOfPages As String

    Dim nTop As Int16 = e.MarginBounds.Top
    Dim nLeft As Int16 = e.MarginBounds.Left

    If printEntity.PageNumber = 1 Then

    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns
    If oColumn.Visible = True Then
    nWidth = CType(Math.Floor(oColumn.Width / printEntity.TotalWidth * printEntity.TotalWidth * (e.MarginBounds.Width / printEntity.TotalWidth)), Int16)
    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
    oColumnLefts.Add(nLeft)
    oColumnWidths.Add(nWidth)
    oColumnTypes.Add(oColumn.GetType)
    nLeft += nWidth
    End If
    Next
    End If

    Do While printEntity.RowPos < printEntity.DGV.Rows.Count
    Dim oRow As DataGridViewRow = printEntity.DGV.Rows(printEntity.RowPos)

    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
    DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
    printEntity.NewPage = True
    printEntity.PageNumber += 1
    e.HasMorePages = True
    Exit Function
    Else

    If printEntity.NewPage Then

    ' Draw Header
    e.Graphics.DrawString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
    ' Draw Columns
    nTop = e.MarginBounds.Top
    i = 0
    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

    If oColumn.Visible = True Then
    e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
    i += 1
    End If

    Next

    printEntity.NewPage = False
    End If

    nTop += nHeight
    i = 0

    For Each oCell As DataGridViewCell In oRow.Cells
    If oCell.Visible = True Then
    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
    printEntity.Button.Text = oCell.Value.ToString
    printEntity.Button.Size = New Size(oColumnWidths(i), nHeight)
    Dim oBitmap As New Bitmap(printEntity.Button.Width, printEntity.Button.Height)
    printEntity.Button.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
    printEntity.CheckBox.Size = New Size(14, 14)
    printEntity.CheckBox.Checked = CType(oCell.Value, Boolean)
    Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
    Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
    oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    printEntity.CheckBox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - printEntity.CheckBox.Width) / 2, Int32), CType((oBitmap.Height - printEntity.CheckBox.Height) / 2, Int32), printEntity.CheckBox.Width, printEntity.CheckBox.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
    printEntity.ComboBox.Size = New Size(oColumnWidths(i), nHeight)
    Dim oBitmap As New Bitmap(printEntity.ComboBox.Width, printEntity.ComboBox.Height)
    printEntity.ComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), printEntity.StringFormatComboBox)
    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
    Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
    Dim oImageSize As Size = CType(oCell.Value, Image).Size

    e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))
    End If
    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    i += 1
    End If
    Next
    End If

    printEntity.RowPos += 1
    nRowsPerPage += 1

    Loop

    DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
    e.HasMorePages = False
    End Function
    Private Shared Function DrawFooter(ByVal blnGotNumPages As Boolean, ByVal strNumOfPages As String, ByVal dgv As DataGridView, ByVal printEntity As PrintFactory, ByVal RowsPerPage As Int32, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
    Dim sPageNo As String

    If printEntity.blnGotNumPages = False Then
    printEntity.blnGotNumPages = True
    printEntity.strNumOfPages = Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
    sPageNo = printEntity.PageNumber.ToString + " of " + Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
    Else
    sPageNo = printEntity.PageNumber.ToString + " of " + printEntity.strNumOfPages
    End If

    ' Right Align - User Name
    e.Graphics.DrawString(printEntity.UserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(printEntity.UserName, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)
    ' Left Align - Date/Time
    e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)
    ' Center - Page No. Info
    e.Graphics.DrawString(sPageNo, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)
    End Function

    Private Shared Sub Validate(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String)
    If dgv Is Nothing Then
    Throw New ArgumentNullException("dgv")
    End If
    If String.IsNullOrEmpty(userName) = True Then
    Throw New ArgumentNullException("userName")
    End If
    If String.IsNullOrEmpty(headerText) = True Then
    Throw New ArgumentNullException("headerText")
    End If
    End Sub
    #End Region
    End Class
    • Edited by AlexWA Friday, March 20, 2009 6:04 PM Fixed last row not printing
    • Proposed as answer by AlexWA Friday, March 20, 2009 6:06 PM
    Friday, March 20, 2009 6:00 PM
  • As I have had the same problem printing the contents of a DataGridView, I appreciate all the fine suggestions of all those who have responded to this post. However, I have the further problem of having to print not only the cell contents but the ALL the cell settings (most especially the cell background color) in my DataGridView.

    Also, I need to print out the text in the RowHeader cells.

    Would appreciate any help in this area.

    Thanks Profusely,
    EdYberg
    Friday, April 24, 2009 4:34 PM
  • I figured out how to print out my Row Headers and all the DGV Cell Formatting Contents using  AlexWA's fine PrintFactory Class code.

    Along the way I discovered that by checking the Visible property of the column, you are also checking to see whether or not your column is visible in the underlying DataGridView control which means that if you have horizontal scrollbars showing (meaning that some columns are NOT visible due to the fact that they are not showing rather than because a user has SET then to Visible = False) those columns that are hidden by the size of the grid control will not print either. BTW, AlexWA asked why his code would not print out the first page of his grid and that is because he set the page to 1 in his BeginPrint Sub, so that by the time he gets to printing out the grid contents he is already on Page 2 and since there is no data yet for Page 2, he just prints out a blank Page 2 and he's done. Not quite sure why that happens but setting the Page to 0 in the BeginPrint Sub fixes the problem.

    Thanks again to AlexWA!

    (I'm sorry I can't show the code for this because I am not at my development machine right now, but if you reply to this post, I will reply with the code that I came up with.)

    The problem I am now grappling with is how to print out more than 40 columns (in Landscape) by somehow capturing the total number of columns and dividing the TotalWidth by that to set the column widths...  not having much success... seems that the columns just start out again at the beginning of the grid and overwrite the previous contents.
    • Proposed as answer by EdYberg Saturday, May 02, 2009 11:58 AM
    Saturday, May 02, 2009 11:58 AM
  • Thanks a lot guys the code is amazing..
    Wednesday, June 10, 2009 1:06 PM
  • Hello.
    Can you tell me why I'm getting in my printed paper date format like : 8.8.2009 0:00:00 ?
    In my datagridview there is no time at the end, but on printed paper there is. I would like to remove that time from the end, so what exactly in this code should i change to do that ?
    Thank you in advance.
    Thursday, June 11, 2009 6:21 PM
  • Find the place in your code where it says... ' Left Align - Date/Time e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7) ...this is the code that's printing your footer. You could try commenting it out. Good luck!
    Friday, June 12, 2009 2:19 PM
  • EdYberg thank you for your reply and i apologize for not being clear about my problem, but i will try to explain a little better this time.
    I'm not having problem with time at the end (bottom) of the printed paper, but i'm having problems with time in columns that have date value .
    In datagridview there's correct date and there's no time after the date, but when i print it (on paper) there is time and it says "0:00:00". something like :

    | _____date_____  |
    |                           |
    | 8.8.2009 0:00:00 |
    | 4.4.2009 0:00:00 |
    | 2.6.2009 0:00:00 |

    Also in access table that column i set to short date and there's just date (no time).
    My English is not very good but i hope i explained myself a little better this time.
    Any kind of help will be very appreciated.

    Saturday, June 13, 2009 1:47 PM
  • Hi Will-affinity

    your code works great but the document is being printed on the right of the page  and no footer,  this hapends on a DGV that is bindet by code, if i use a DGV and Bind it by smart tag it works fine. is there a fix for this>
    If i can make the default layout to Landscape that will do


    thanks

    • Edited by deti Friday, July 03, 2009 9:01 PM
    Friday, July 03, 2009 3:55 PM
  • Thanks so much for this routine.  I was printing pages on top of each other and about to pull my hair out.  This routine you posted works great, even better than I expected with very little work needed to insert into my project.  I realize it is three years old but it still works great in VBE2008
    Sunday, July 26, 2009 11:15 PM
  • hi there, i'm new here.. i've tried your codes and it's great but i want to print something on the last page like "NOTHING FOLLOWS", i really dont know where to put the DrawString thing here.. all i want to to do is to print something on the last page.. could you help me??
    Monday, August 03, 2009 1:40 PM
  • hi there Nectuss.. that's great i have tried it, and my printing now is working properly, the last record on the DataGridView is now recognized.. and the records don't overlap with the footer.. btw, can you help with the printing of text or string on the last page of the reports.. i just dont know where to put the draw string thing, i want to some text like "NOTHING FOLLOWS".. on the last part of the page.. plz help me.. im hoping for your response..
    Monday, August 03, 2009 1:43 PM
  • [i][i][i][i]
    Sunday, August 09, 2009 11:27 AM
  • hi there, im new here, i want to know how to print some string after the datagridview contents, like i want to print the "NOTHING FOLLOWS", or even "Total Nos. of Records", something like that, i want to know how to, pls help me guyz..
    Monday, August 17, 2009 2:45 PM
  • hi there, i wanted to know how to print some label or string after printing the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
    Monday, August 17, 2009 2:49 PM
  • hi there, i wanted to know how to print some label or string after printing the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
    Monday, August 17, 2009 2:50 PM
  • Private oStringFormat As StringFormat
        Private oStringFormatComboBox As StringFormat
        Private oButton As Button
        Private oCheckbox As CheckBox
        Private oComboBox As ComboBox

        Private nTotalWidth As Int16
        Private nRowPos As Int16
        Private NewPage As Boolean
        Private nPageNo As Int16
        Private Header As String = "Header Test"
        Private sUserName As String = "Will"

        Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter

            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox

            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                nTotalWidth += oColumn.Width

            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0

        End Sub

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

                Static oColumnLefts As New ArrayList
                Static oColumnWidths As New ArrayList
                Static oColumnTypes As New ArrayList
                Static nHeight As Int16

                Dim nWidth, i, nRowsPerPage As Int16
                Dim nTop As Int16 = e.MarginBounds.Top
                Dim nLeft As Int16 = e.MarginBounds.Left

                If nPageNo = 1 Then

                    For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                        nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                        nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                        oColumnLefts.Add(nLeft)
                        oColumnWidths.Add(nWidth)
                        oColumnTypes.add(oColumn.GetType)
                        nLeft += nWidth

                    Next

                End If

                Do While nRowPos < DataGridView1.Rows.Count - 1

                    Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

                    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                        DrawFooter(e, nRowsPerPage)

                        NewPage = True
                        nPageNo += 1
                        e.HasMorePages = True
                        Exit Sub

                    Else

                        If NewPage Then

                            ' Draw Header
                            e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                            ' Draw Columns
                            nTop = e.MarginBounds.Top
                            i = 0
                            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                                e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                                e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                                e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                                i += 1

                            Next
                            NewPage = False

                        End If

                        nTop += nHeight
                        i = 0
                        For Each oCell As DataGridViewCell In oRow.Cells

                            If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                                oButton.Text = oCell.Value.ToString
                                oButton.Size = New Size(oColumnWidths(i), nHeight)
                                Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                                oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                                oCheckbox.Size = New Size(14, 14)
                                oCheckbox.Checked = CType(oCell.Value, Boolean)
                                Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                                Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                                oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                                oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                                Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                                oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

                            ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                                Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
                                Dim oImageSize As Size = CType(oCell.Value, Image).Size
                                e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                            End If

                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                            i += 1

                        Next

                    End If

                    nRowPos += 1
                    nRowsPerPage += 1

                Loop

                DrawFooter(e, nRowsPerPage)

                e.HasMorePages = False

        End Sub

        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

            Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

            ' Right Align - User Name
            e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

        End Sub


    hi there, i wanted to know how to print some label or string after printing the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
    Monday, August 17, 2009 2:50 PM
  • There's a problem with printing out the footer. It messes up the page number if the page has fewer than the max number of rows. For example, I had 38 rows spread over two pages, the first page said "Page 1 of 2" but the last one would say "Page 2 of 13" since there were only 3 rows on the final page. Either way, I've 'Option Stricted' and turned it into a class unto itself. Enjoy!

    To Implement:
        Private Sub btnPrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintPreview.Click
            If IsNothing(Printer) Then
                Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
            End If
            Printer.ShowPrintPreviewDialog()
        End Sub

        Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
            If IsNothing(Printer) Then
                Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
            End If
            Printer.Print()
        End Sub

    Public Class Printer
        Private oStringFormat As StringFormat
        Private oStringFormatComboBox As StringFormat
        Private oButton As Button
        Private oCheckbox As CheckBox
        Private oComboBox As ComboBox

        Private nTotalWidth As Int16
        Private nRowPos As Int16
        Private NewPage As Boolean
        Private nPageNo As Int16
        Private Header As String
        Private sUserName As String
        Private nPageCount As Integer = 0
        Private dgv As DataGridView
        Private WithEvents PrintDoc As New Printing.PrintDocument
        Private storedPageSettings As Printing.PageSettings = New Printing.PageSettings()

        Property DataGridViewToPrint() As DataGridView
            Get
                Return dgv
            End Get
            Set(ByVal value As DataGridView)
                dgv = value
            End Set
        End Property
        Property UserName() As String
            Get
                Return sUserName
            End Get
            Set(ByVal value As String)
                sUserName = value
            End Set
        End Property
        Property HeaderText() As String
            Get
                Return Header
            End Get
            Set(ByVal value As String)
                Header = value
            End Set
        End Property

        Public Sub New(ByVal aDGV As DataGridView, ByVal aHeader As String, ByVal aUserName As String)
            DataGridViewToPrint = aDGV
            UserName = aUserName
            HeaderText = aHeader
        End Sub
        Public Sub Print()
            Dim psDlg As New PageSetupDialog
            psDlg.PageSettings = storedPageSettings
            psDlg.ShowDialog()
        End Sub
        Public Sub ShowPrintPreviewDialog()
            Dim dlg As New PrintPreviewDialog()
            dlg.Document = PrintDoc
            dlg.ShowDialog()
        End Sub
        Private Sub PrintDoc_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDoc.BeginPrint

            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter

            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox

            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                nTotalWidth = CShort(nTotalWidth + oColumn.Width)

            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0

        End Sub

        Private Sub Printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage

            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16

            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = CShort(e.MarginBounds.Top)
            Dim nLeft As Int16 = CShort(e.MarginBounds.Left)

            If nPageNo = 1 Then

                For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                    nHeight = CShort(e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11)

                    oColumnLefts.Add(nLeft)
                    oColumnWidths.Add(nWidth)
                    oColumnTypes.Add(oColumn.GetType)
                    nLeft += nWidth

                Next

            End If

            Do While nRowPos < DataGridViewToPrint.Rows.Count

                Dim oRow As DataGridViewRow = DataGridViewToPrint.Rows(nRowPos)

                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                    DrawFooter(e, nRowsPerPage)

                    NewPage = True
                    nPageNo = CShort(nPageNo + 1)
                    e.HasMorePages = True
                    Exit Sub

                Else

                    If NewPage Then

                        ' Draw Header
                        e.Graphics.DrawString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        ' Draw Columns
                        nTop = CShort(e.MarginBounds.Top)
                        i = 0
                        For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
                            i = CShort(i + 1)

                        Next
                        NewPage = False

                    End If

                    nTop += nHeight
                    i = 0
                    For Each oCell As DataGridViewCell In oRow.Cells

                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                            oButton.Text = oCell.Value.ToString
                            oButton.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                            oCheckbox.Size = New Size(14, 14)
                            oCheckbox.Checked = CType(oCell.Value, Boolean)
                            Dim oBitmap As New Bitmap(CInt(oColumnWidths(i)), nHeight)
                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                            oComboBox.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CInt(oColumnLefts(i)) + 1, nTop, CInt(oColumnWidths(i)) - 16, nHeight), oStringFormatComboBox)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                            Dim oCellSize As Rectangle = New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight)
                            Dim oImageSize As Size = CType(oCell.Value, Image).Size
                            e.Graphics.DrawImage(CType(oCell.Value, Image), New Rectangle(CType(oColumnLefts(i), Int32) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                        End If

                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))

                        i = CShort(i + 1)

                    Next

                End If

                nRowPos = CShort(nRowPos + 1)
                nRowsPerPage = CShort(nRowsPerPage + 1)
            Loop

            DrawFooter(e, nRowsPerPage)

            e.HasMorePages = False

        End Sub

        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

            'Changed from Page XXX of XXX to just Page XXX because
            'Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString() would generate
            'inaccurate page numbers on pages with less than the max number of rows (ie: the last page)
            'Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString
            Dim sPageNo As String = "Page " + nPageNo.ToString

            ' Right Align - User Name
            e.Graphics.DrawString("Printed by: " + sUserName, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

        End Sub
    End Class



    hi there, i wanted to know how to print some label or string after printing the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
    Monday, August 17, 2009 2:51 PM
  • Hi,

    This code is absolutely amazing. works exactly the way I want...
    However, I have a question:

    Can a particular cell be aligned Right ? I looked in the code but could not find any way to alter the default alignment.
    Any help in this regard would be appreciated.

    Thanks

    Kazmi
    Tuesday, August 25, 2009 10:54 PM
  • yababer, thank you for your post, I like being able to call PrintFactory.Print() to print the dataGridView. I was having some problems with your code and have fixed them. The things that I improved were

    1. Don't print columns that are not set to visible
    2. Fixed the page numbers
    3. Added the ability to print in Landscape

    I can view the document in print preview but when I press the print button in print preview it does not print the datagridview. If anyone can fix this please let me know.

    To implement create a class called PrintFactory and copy the code below into the class. To print use  
    PrintFactory.Print( Me .DataGridView1, "Username" , "Header" , "L" ) the "L" will print in landscape, any other text string will print in portrait.
    Print Preview
    PrintFactory.Preview( Me .DataGridView1, "Username" , "Header" , "L" )

    Imports System.Windows.Forms
    Public Class PrintFactory
    #Region "Instance"

    #Region "Declerations"

    Private WithEvents _printDocument As Printing.PrintDocument = New Printing.PrintDocument()
    Private _dgv As DataGridView
    Private _stringFormat As StringFormat
    Private _stringFormatComboBox As StringFormat
    Private _button As Button
    Private _checkBox As CheckBox
    Private _comboBox As ComboBox
    Private _totalWidth As Int16
    Private _rowPos As Int16
    Private _newPage As Boolean
    Private _pageNumber As Int16
    Private _userName As String
    Private _headerText As String
    Private _blnGotNumPages As Boolean
    Private _strNumOfPages As String
    Private _orientation As String

    #End Region

    #Region "Properties"

    Private ReadOnly Property DGV() As DataGridView
    Get
    Return _dgv
    End Get
    End Property

    Private Property HeaderText() As String
    Get
    Return _headerText
    End Get

    Set(ByVal value As String)
    _headerText = value
    End Set

    End Property

    Private Property UserName() As String

    Get
    Return _userName
    End Get

    Set(ByVal value As String)
    _userName = value
    End Set
    End Property

    Private Property StringFormat() As StringFormat
    Get
    Return _stringFormat
    End Get

    Set(ByVal value As StringFormat)
    _stringFormat = value
    End Set
    End Property

    Private Property StringFormatComboBox() As StringFormat
    Get
    Return _stringFormatComboBox
    End Get

    Set(ByVal value As StringFormat)
    _stringFormatComboBox = value
    End Set
    End Property

    Private Property Button() As Button

    Get
    Return _button
    End Get

    Set(ByVal value As Button)
    _button = value
    End Set
    End Property

    Private Property CheckBox() As CheckBox
    Get
    Return _checkBox
    End Get

    Set(ByVal value As CheckBox)
    _checkBox = value
    End Set
    End Property

    Private Property ComboBox() As ComboBox
    Get
    Return _comboBox
    End Get

    Set(ByVal value As ComboBox)
    _comboBox = value
    End Set
    End Property

    Private Property TotalWidth() As Int16
    Get
    Return _totalWidth
    End Get

    Set(ByVal value As Int16)
    _totalWidth = value
    End Set
    End Property

    Private Property RowPos() As Int16
    Get
    Return _rowPos
    End Get

    Set(ByVal value As Int16)
    _rowPos = value
    End Set
    End Property

    Private Property NewPage() As Boolean
    Get
    Return _newPage
    End Get

    Set(ByVal value As Boolean)
    _newPage = value
    End Set
    End Property

    Private Property PageNumber() As Int16
    Get
    Return _pageNumber
    End Get

    Set(ByVal value As Int16)
    _pageNumber = value
    End Set
    End Property
    Private Property strNumOfPages() As String
    Get
    Return _strNumOfPages
    End Get

    Set(ByVal value As String)
    _strNumOfPages = value
    End Set
    End Property
    Private Property blnGotNumPages() As Boolean
    Get
    Return _blnGotNumPages
    End Get

    Set(ByVal value As Boolean)
    _blnGotNumPages = value
    End Set
    End Property
    Private Property orientation() As String

    Get
    Return _orientation
    End Get

    Set(ByVal value As String)
    _orientation = value
    End Set
    End Property
    #End Region

    Private Sub New(ByVal userName As String, ByVal headerText As String)
    Me._userName = userName
    Me._headerText = headerText
    End Sub

    Private Sub _printDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles _printDocument.PrintPage
    EndPrint(Me, e)
    End Sub

    #End Region

    #Region "Statics"

    Public Shared Function Print(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
    Validate(dgv, userName, headerText)
    Dim tempPrintFactory As PrintFactory
    tempPrintFactory = BeginPrint(dgv, userName, headerText)
    If orientation = "L" Then
    tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
    End If
    tempPrintFactory._printDocument.Print()
    End Function

    Public Shared Function Preview(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
    Validate(dgv, userName, headerText)
    Dim tempPrintFactory As PrintFactory
    tempPrintFactory = BeginPrint(dgv, userName, headerText)
    If Orientation = "L" Then
    tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
    End If
    Dim tempPrintDiag As New PrintPreviewDialog()
    tempPrintDiag.Document = tempPrintFactory._printDocument
    tempPrintDiag.ShowDialog()
    End Function

    Private Shared Function BeginPrint(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String) As PrintFactory
    Dim printEntity As PrintFactory = New PrintFactory(userName, headerText)
    printEntity._dgv = dgv
    printEntity.StringFormat = New StringFormat
    printEntity.StringFormat.Alignment = StringAlignment.Near
    printEntity.StringFormat.LineAlignment = StringAlignment.Center
    printEntity.StringFormat.Trimming = StringTrimming.EllipsisCharacter
    printEntity.StringFormatComboBox = New StringFormat
    printEntity.StringFormatComboBox.LineAlignment = StringAlignment.Center
    printEntity.StringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
    printEntity.StringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
    printEntity.Button = New Button
    printEntity.CheckBox = New CheckBox
    printEntity.ComboBox = New ComboBox
    printEntity.TotalWidth = 0

    For Each oColumn As DataGridViewColumn In dgv.Columns
    printEntity.TotalWidth += oColumn.Width
    Next
    printEntity.PageNumber = 1
    printEntity.NewPage = True
    printEntity.RowPos = 0
    Return printEntity
    End Function

    Private Shared Function EndPrint(ByVal printEntity As PrintFactory, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
    Static oColumnLefts As New ArrayList
    Static oColumnWidths As New ArrayList
    Static oColumnTypes As New ArrayList
    Static nHeight As Int16

    Dim nWidth, i, nRowsPerPage As Int16
    Dim blnGotNumPages As Boolean
    Dim strNumOfPages As String

    Dim nTop As Int16 = e.MarginBounds.Top
    Dim nLeft As Int16 = e.MarginBounds.Left

    If printEntity.PageNumber = 1 Then

    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns
    If oColumn.Visible = True Then
    nWidth = CType(Math.Floor(oColumn.Width / printEntity.TotalWidth * printEntity.TotalWidth * (e.MarginBounds.Width / printEntity.TotalWidth)), Int16)
    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
    oColumnLefts.Add(nLeft)
    oColumnWidths.Add(nWidth)
    oColumnTypes.Add(oColumn.GetType)
    nLeft += nWidth
    End If
    Next
    End If

    Do While printEntity.RowPos < printEntity.DGV.Rows.Count
    Dim oRow As DataGridViewRow = printEntity.DGV.Rows(printEntity.RowPos)

    If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
    DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
    printEntity.NewPage = True
    printEntity.PageNumber += 1
    e.HasMorePages = True
    Exit Function
    Else

    If printEntity.NewPage Then

    ' Draw Header
    e.Graphics.DrawString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
    ' Draw Columns
    nTop = e.MarginBounds.Top
    i = 0
    For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

    If oColumn.Visible = True Then
    e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
    i += 1
    End If

    Next

    printEntity.NewPage = False
    End If

    nTop += nHeight
    i = 0

    For Each oCell As DataGridViewCell In oRow.Cells
    If oCell.Visible = True Then
    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
    printEntity.Button.Text = oCell.Value.ToString
    printEntity.Button.Size = New Size(oColumnWidths(i), nHeight)
    Dim oBitmap As New Bitmap(printEntity.Button.Width, printEntity.Button.Height)
    printEntity.Button.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
    printEntity.CheckBox.Size = New Size(14, 14)
    printEntity.CheckBox.Checked = CType(oCell.Value, Boolean)
    Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
    Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
    oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    printEntity.CheckBox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - printEntity.CheckBox.Width) / 2, Int32), CType((oBitmap.Height - printEntity.CheckBox.Height) / 2, Int32), printEntity.CheckBox.Width, printEntity.CheckBox.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
    printEntity.ComboBox.Size = New Size(oColumnWidths(i), nHeight)
    Dim oBitmap As New Bitmap(printEntity.ComboBox.Width, printEntity.ComboBox.Height)
    printEntity.ComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
    e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), printEntity.StringFormatComboBox)
    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
    Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
    Dim oImageSize As Size = CType(oCell.Value, Image).Size

    e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))
    End If
    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    i += 1
    End If
    Next
    End If

    printEntity.RowPos += 1
    nRowsPerPage += 1

    Loop

    DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
    e.HasMorePages = False
    End Function
    Private Shared Function DrawFooter(ByVal blnGotNumPages As Boolean, ByVal strNumOfPages As String, ByVal dgv As DataGridView, ByVal printEntity As PrintFactory, ByVal RowsPerPage As Int32, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
    Dim sPageNo As String

    If printEntity.blnGotNumPages = False Then
    printEntity.blnGotNumPages = True
    printEntity.strNumOfPages = Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
    sPageNo = printEntity.PageNumber.ToString + " of " + Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
    Else
    sPageNo = printEntity.PageNumber.ToString + " of " + printEntity.strNumOfPages
    End If

    ' Right Align - User Name
    e.Graphics.DrawString(printEntity.UserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(printEntity.UserName, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)
    ' Left Align - Date/Time
    e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)
    ' Center - Page No. Info
    e.Graphics.DrawString(sPageNo, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)
    End Function

    Private Shared Sub Validate(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String)
    If dgv Is Nothing Then
    Throw New ArgumentNullException("dgv")
    End If
    If String.IsNullOrEmpty(userName) = True Then
    Throw New ArgumentNullException("userName")
    End If
    If String.IsNullOrEmpty(headerText) = True Then
    Throw New ArgumentNullException("headerText")
    End If
    End Sub
    #End Region
    End Class

    this is a wonderful code and it just works simply by copy & paste.

    however, just a question. its seems that in this solution, there is the Print() & Preview() function. however, if let say i were to do a preview of the page BUT doesn't wan to print it out. is that possible?

    sphericalx
     
    Friday, October 16, 2009 3:35 AM
  • When I use

    PrintFactory.Print

    everything works fine as described, however if you use the

    PrintFactory.Preview

    with the same arguments the preview dialog is perfect but if you hit the print button you get an empty page with the date pag number and user printed but no gird.

    Monday, October 19, 2009 10:07 PM
  • I haven't looked at this code for several months but I'm betting that it has something to do with a previous user's problem to which I replied... "BTW, AlexWA asked why his code would not print out the first page of his grid and that is because he set the page to 1 in his BeginPrint Sub, so that by the time he gets to printing out the grid contents he is already on Page 2 and since there is no data yet for Page 2, he just prints out a blank Page 2 and he's done. Not quite sure why that happens but setting the Page to 0 in the BeginPrint Sub fixes the problem. " The best thing to do is step through the code with a watch on the page setting and see what happens Good Luck!
    Friday, October 23, 2009 4:31 PM
  • This code works fine and I have used it but I've found two problems: when you try to print two dgv, printFactory creates 3 arrays (oColumnTypes, oColumnLefts, oColumnWidths) and in the method EndPrint() appends the new dgv at the oldest. I have fix this error simply writing 3 lines of code in the EndPrint method:

    oColumnTypes.Clear()
    oColumnLefts.Clear()
    oColumnWidths.Clear()

    behind the first for each construct.

    The second problem is the same of previous posts: When I call printFactory.Preview() the print preview dialog starts fine but if you hit the print button, you get an empty page!!!

    We have to capture the print button event??? Can sameone help us???
    Saturday, December 05, 2009 9:32 AM
  • ONE SOLUTION...

    Disable the print button in the PreviewDialog. ;)

    The code: 
    DirectCast(DirectCast(tempPrintDiag.Controls(1), ToolStrip).Items(0), ToolStripButton).Enabled = False

     

     

     

    Monday, December 14, 2009 12:48 PM
  • EDIT: And one more question how do I call printer setup cause print is automated for all pages and i just want to print selected text or just first page???


    Based on XANDELONGHI solution I removed button to invisible and set printer to print when you click exit on print preview

    Public Shared Function Preview(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
            Validate(dgv, userName, headerText)
            Dim tempPrintFactory As PrintFactory
            tempPrintFactory = BeginPrint(dgv, userName, headerText)
            If Orientation = "L" Then
                tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
            End If
            Dim tempPrintDiag As New PrintPreviewDialog()
            DirectCast(DirectCast(tempPrintDiag.Controls(1), ToolStrip).Items(0), ToolStripButton).Visible = False
            tempPrintDiag.Document = tempPrintFactory._printDocument
            tempPrintDiag.ShowDialog()
            tempPrintFactory._printDocument.Print()
      
        End Function
    If anybody knows how call print on click it would be nice

    i thought something like this to declare in class don't know is it good and then call print...

            Dim tempPrintDiag As New PrintPreviewDialog()
            DirectCast(DirectCast(tempPrintDiag.Controls(1), ToolStrip).Items(0), ToolStripButton).PerformClick()
    • Proposed as answer by turkidc Monday, December 14, 2009 5:07 PM
    Monday, December 14, 2009 5:06 PM
  • First off, I just want to say SUPER DUPER THANK YOU to the contributers!!!

    I'm new to VB AND programming....  I would have been lost for days (possible weeks) working on a solution.

    Now... here comes the newbee question.

    Everything works fine as far as printing goes.  But, when my Print Screen form shows up, it's very tiny... like 300 x 300.

    Is it possible and where do I go to make this display with the same attributes as my other forms (i.e. - same size, background color, title bar, etc.)?

    Thank you!
    Wednesday, December 16, 2009 1:19 AM
  • The first thing is the printpreview is displayed according to the actual size of your printout. If you change the size of your print settings then you should change the preview size. the following link should give you some info on this.

    http://msdn.microsoft.com/en-us/library/b1x2ca5h(VS.80).aspx


    The code on the above link shows the e.graphics method of setting up printpreview. Also the page setup determines the size.

    Hope this helps

    Curtis
    Always Lost in Code
    Sunday, January 03, 2010 5:25 AM
  • Hello Mark, You seem like a guy who know's what you're doing.. i've got a slight problem... if you could help me that would be awesome thank you....

    I'm using 3 tables, Primary, Secondary and Tertiary,
    how do i get all three datagridview's to show for print preview and print on one form?? Any idea what the code may be as i have no idea because I have never done a print procedure for datagridview's on a form before.. but i want to show all three datagrids of the stock items that values have been changed from each datagrid on the one form...

    Sorry if this doesn't make sense. if it doesn't, please get back to me and i will try and make it a bit more clearer..

    Thanks in advanced

    Harvey
    Friday, January 08, 2010 3:15 PM
  • Hey Harvey,
     Just thought I would inform you there is a working data gridview print routine that I think will print what you want at the following post
    http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/2c930600-b2ed-47d3-8fa8-4648ef43685e
     
     Will Infinity wrote the code, I just cahnge a few things to make it a little better, But it printed out with print preview and  a hard copy for me, There were some of the people had wrap around issues but in general it is a good code.

    Hope this helps
    curtis
    Always Lost in Code
    Saturday, January 16, 2010 2:41 AM
  • Wicked! Thanks mate.. very helpful! (:
    Saturday, January 16, 2010 5:16 PM
  • hai
    i am getting an error for this code that arraylist cannot be converted to int.so please help me to correct it
    thanks in advance...
    dreamflowerslove@yahoo.com
    Thursday, January 28, 2010 11:46 AM
  • Hi kiranprabha,

     To start with you will need to provide a little more info. Your code in the area where the error occurs and the actual error code that is displayed would be helpfull and if possible the code line the error happens on.

    Curtis


    Always Lost in Code,
    Thursday, January 28, 2010 2:42 PM
  • Hi,

    I am using your modified version of the Will_Affinity code which works perfectly when printing a DataGridView when I call it with either a Landscape PageSetting or a Portrait PageSetting.
    What I am trying to do is to use two buttons on the DataGridView menu strip. One to call a Print in Landscape and the other to call a Print in Portrait.
    If I run the program in Debug and launch the Landcape Print it previews perfectly, if I then (in the same Debug session) launch the Portrait Print the page orientation previews as Portrait but the actual Grid image is too wide and therefore tuncated at the righthand side.
    If I do the opposite, start a new Debug session and launch the Portrait Print it previews perfectly, if I then (in the same Debug session) launch the Landscape Print the page orientation previews as Landscape  but the actual Grid image  is not full width. It start at the left side and seems to be about the same width as the previous Portrait image.
    As you can see from the above everything works perfectly if you only do one type of print in one Debug session (ie. the first one you run is fine). It seems as if the image width for whichever print is run second somehow remains the same as the first print, even thought the PageSettings are different and must be OK or else the prints would not run OK when launched by themselves.
    I've tried lots of things including defining the Landscape and Portrait versions as different PrintDocuments, but no success.
    I'm not sure if this the right place to post the question, but if you have any ideas I would be most grateful or if not, could you suggest an alternative place to post the query
    Thanks NewDax
    Saturday, March 13, 2010 3:35 PM
  •  Hi NewDax,

      There may be someone else out there that is better qualified to answer this. I am not sure if I can answer you questions. But Ill try to help.

     First off I had two applications that used the print routine one used a page setup dialog for the default printer. Set the page up for with the settings for portrait or landscape. You may have to refresh the datagridview after changing the page setup dialog. The second used code to change the settings.

    Are you using code or a page dialog to setup the views. Though I can't see where it would make much difference. At the bottom of the link

    http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/2c930600-b2ed-47d3-8fa8-4648ef43685e

    the last reply has a code printer set up Did you see this?

     Have you tried to print a paper copy from the print preview screen. When priint preview comes up it has an option to print.

    I willl look in to this it may take me a little while to set all of it back up and test it.

    Curtis



    Always Lost in Code,
    Saturday, March 13, 2010 4:05 PM
  • Hi Curtis,

    Thanks for your offer of help and your extemely fast response.

    The PageSettings are done in code.

    I tried to do the Landscape/Portrait selection in the page setup dialog but had to give up as when I changed the orientation the default margin settings flippped ie, what was my default bottom margin changed to a right hand margin. Anyway thats another problem and as I couldn't solve it I opted to use settings in code.

    Thanks NewDax
    Saturday, March 13, 2010 4:24 PM
  •   Try this code in your code where your calling printprview.
    Private Sub PrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreview.Click
            Dim dlg As New PrintPreviewDialog()
            If PageSetupDialog1.Document.DefaultPageSettings.Landscape = False Then
                PrintDocument1.DefaultPageSettings.Landscape = False
            End If
            If PageSetupDialog1.Document.DefaultPageSettings.Landscape = True Then
                PrintDocument1.DefaultPageSettings.Landscape = True
            End If
            dlg.Document = PrintDocument1
            dlg.ShowDialog()
        End Sub
    I was using a sub called from a menu. I believe the pagesetup dialog just changes the print driver and not the document at least this caused my portrait view to print correctly when change. I use two if statements to check to see what the pagesetup is set to. You should be able to use this before call the print or printprview.

    curtis


    Always Lost in Code,
    Saturday, March 13, 2010 5:28 PM
  •  NewDax,
     The above code did not stop the problem for me it just change it a little. I had tried it three time and it seamed to work but I went and exited debug and restarted the app and it started having the same problem. But I still believe that the new view for some reason is not updating the datagridview graphics.
    Always Lost in Code,
    Saturday, March 13, 2010 6:03 PM
  •  Have discovered some thing new that sheds light on problem. When I start debug with the pagesetup in portrait mode and I change to landscape mode the graphics image stays in portrait mode. I don't know yet how to change this. But I will keep trying.
    Curtis

    Always Lost in Code,
    Saturday, March 13, 2010 6:23 PM
  • Hey NewDax,

     Since no one has jumped in to help I suggest starting a new question. So that others will see it. Also post your code for the datagridview print.
    So the other people will have it to test with. I will still be looking for solution for the problem. I don't claim to know a lot about datagridview and it has a lot to it.

    Curtis

    Always Lost in Code,
    Saturday, March 13, 2010 6:52 PM
  • Hi Curtis,

    Thanks for your efforts, I'm still trying also.

    I need to tidy up my code a little before I post it, its been hacked around a lot with my different attempts.
    I'm new to this game, but I will look into starting a new question.

    Thanks again, NewDax
    Saturday, March 13, 2010 8:52 PM
  • Hi Curtis,

    I did try printing from the preview and it printed with exactly the same layout as the preview ie when the preview was wrong so was the print.

    I will try to raise a new question, meanwhile below is my code module for the DataGridView Printing

    Imports System.Drawing.Printing
    Module PrintGrid
    
        ' This module Prints a DataGridView1 of multiple pages
        ' It allows user Page orientation
        ' It Previews the Print before printing
        ' It can be tailored to hide certain Columns by setting their Visible property to False
        ' in the StartPrint Sub
        ' This version has been modied so that Landscape and Portrait prints us separate PrintDocuments
        ' in an attempt to solve a problem, it if fact is no improvement over using a single PrintDocument
    
        Public oPortrait As Boolean
    
        Public WithEvents PrintDocument1 As New PrintDocument 'Added by me to overcome WithEvents required error
        Public WithEvents PrintDocument2 As New PrintDocument ' tt
        Public DataGridView1 As New DataGridView 'Added by me to overcome DataGridView1 not declared error
        ' Public DataGridView2 As New DataGridView ' tt2
        Public DefaultPageSettings As PageSettings = New PageSettings()
        Private WithEvents PrintPreviewDialog1 As New PrintPreviewDialog
        Private WithEvents PrintPreviewDialog2 As New PrintPreviewDialog 'tt
        Public WithEvents DocToPrint As New PrintDocument 'tt6
        Dim oLandscape As Boolean
        Dim GridToPrint As DataGridView
        Dim PageSetUpDialog1 As New PageSetupDialog 'trial 1
        Dim PageSetUpDialog2 As New PageSetupDialog ' tt
    
        Private lPageNo As String = ""
    
        Private sPageNo As String = ""
    
        Private oStringFormat As StringFormat
    
        Private oStringFormatComboBox As StringFormat
    
        Private oButton As Button
    
        Private oCheckbox As CheckBox
    
        Private oComboBox As ComboBox
    
        Private nTotalWidth As Int16
    
        Private nRowPos As Int16
    
        Private NewPage As Boolean
    
        Private nPageNo As Int16
    
        Private Header As String
    
        Private sUserName As String = ""
       
        Public Sub StartPrintL(ByVal GridToPrint) 'ByVal GridToPrint As DataGridView)
    
            DataGridView1 = GridToPrint
            DocToPrint = PrintDocument1
    
            'oLandscape = True 'used in previous attempt
    
            ' Set up Default Page Settings
            PrintDocument1.DefaultPageSettings.Landscape = True
            PrintDocument1.DefaultPageSettings.Margins.Left = 10
            PrintDocument1.DefaultPageSettings.Margins.Right = 10
            PrintDocument1.DefaultPageSettings.Margins.Top = 25
            PrintDocument1.DefaultPageSettings.Margins.Bottom = 50
    
            ' DataGridView1.Columns(2).Visible = False ' Use to hide a col. (index no.)at runtime
    
            PrintDocument1.OriginAtMargins = True ' takes margins into account 
    
            'PageSetUpDialog1.PageSettings = DefaultPageSettings ' Displays page setting dialog-removed due to problems
            ' PageSetUpDialog1.ShowDialog()                        ' with margins when paper orientation changed
    
            Dim PrintPreviewDialog1 As New PrintPreviewDialog()
    
            ' PrintDocument1.DefaultPageSettings = PageSetUpDialog1.PageSettings ' Sets page settings to those from PageSetupDialog
            PrintPreviewDialog1.ClientSize = New System.Drawing.Size(600, 600) ' Set Dialog box initial size
            PrintPreviewDialog1.Document = PrintDocument1 ' Previews print
            PrintPreviewDialog1.ShowDialog()
    
    
            'PrintDocument1.Print() ' Alternative for direct print
        End Sub
        Public Sub StartPrintP(ByVal GridToPrint)
    
            DocToPrint = PrintDocument2
            DataGridView1 = GridToPrint
    
            ' DataGridView1.Columns(2).Visible = False ' Use to hide a col. (index no.)
    
            PrintDocument2.OriginAtMargins = True ' takes margins into account 
            ' Set up Default Page Settings
            PrintDocument2.DefaultPageSettings.Landscape = False
            PrintDocument2.DefaultPageSettings.Margins.Left = 10
            PrintDocument2.DefaultPageSettings.Margins.Right = 10
            PrintDocument2.DefaultPageSettings.Margins.Top = 25
            PrintDocument2.DefaultPageSettings.Margins.Bottom = 50
    
            Dim PrintPreviewDialog2 As New PrintPreviewDialog()
    
            'PrintDocument1.DefaultPageSettings = PageSetUpDialog2.PageSettings ' Sets page settings to those from PageSetupDialog
            PrintPreviewDialog2.ClientSize = New System.Drawing.Size(600, 600) 'tt Set Dialog box initial size
            PrintPreviewDialog2.Document = PrintDocument2 ' Previews print
            PrintPreviewDialog2.ShowDialog()
    
    
            'PrintDocument1.Print()' Alternative for direct print
        End Sub
    
        ' 'Public Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
        ' Test using DocToPrint to carry in a different PrintDocument for Landscape and Portrait
        ' Same problem as using single PrintDocument
    
        Public Sub DocToPrint_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles DocToPrint.BeginPrint
    
            oStringFormat = New StringFormat
    
            oStringFormat.Alignment = StringAlignment.Near
    
            oStringFormat.LineAlignment = StringAlignment.Center
    
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter
    
            oStringFormatComboBox = New StringFormat
    
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
    
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
    
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
    
            oButton = New Button
    
            oCheckbox = New CheckBox
    
            oComboBox = New ComboBox
    
            nTotalWidth = 0
    
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                If oColumn.Visible = True Then ' Prints only Visible columns
                    nTotalWidth += oColumn.Width
                End If
            Next
    
            nPageNo = 1
    
            NewPage = True
    
            nRowPos = 0
    
        End Sub
        Public Sub DocToPrint_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.EndPrint
            'Not currently used
        End Sub
    
        '' Public Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        ' Test using DocToPrint to carry in a different PrintDocument for Landscape and Portrait
        ' Same problem as using single PrintDocument
        Public Sub DocToPrint_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles DocToPrint.PrintPage
            Using the_pen As New Pen(Color.Black, 5) ' For debugging only
                e.Graphics.DrawRectangle(the_pen, e.MarginBounds)
            End Using
    
            Header = "Books DataGridView"
    
            Static oColumnLefts As New ArrayList
    
            Static oColumnWidths As New ArrayList
    
            Static oColumnTypes As New ArrayList
    
            Static nHeight As Int16
    
            Dim nWidth, i, nRowsPerPage As Int16
    
            Dim nTop As Int16 = e.MarginBounds.Top
    
            Dim nLeft As Int16 = e.MarginBounds.Left
    
            If nPageNo = 1 Then
    
                For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                    If oColumn.Visible = True Then ' Prints cols with Visible property
                        nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
    
                        nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
    
                        oColumnLefts.Add(nLeft)
    
                        oColumnWidths.Add(nWidth)
    
                        oColumnTypes.Add(oColumn.GetType)
    
                        nLeft += nWidth
                    End If
    
                Next
    
            End If
    
            Do While nRowPos < DataGridView1.Rows.Count - 1 ' Reports of failing to Print last 
                'row. If so remove -1 from above line
                Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)
    
                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
    
                    DrawFooter(e, nRowsPerPage)
    
                    NewPage = True
    
                    nPageNo += 1
    
                    e.HasMorePages = True
    
                    Exit Sub
    
                Else
    
                    If NewPage Then
    
                        ' Draw Header
    
                        e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
    
                        ' Draw Columns
    
                        nTop = e.MarginBounds.Top
    
                        i = 0
    
                        For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                            If oColumn.Visible = True Then ' Prints cols with Visible property
                                e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    
                                e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    
                                e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
    
                                i += 1
                            End If
                        Next
    
                        NewPage = False
    
                    End If
    
                    nTop += nHeight
    
                    i = 0
    
                    Dim svalue As String
    
                    For Each oCell As DataGridViewCell In oRow.Cells
                        If oCell.Visible = True Then ' Prints cols with Visible property
                            If oCell.Value IsNot Nothing Then
    
                                svalue = oCell.Value.ToString
    
                            Else
    
                                svalue = ""
    
                            End If
    
                            If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    
                                e.Graphics.DrawString(svalue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
    
                            ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
    
                                oButton.Text = oCell.Value.ToString
    
                                oButton.Size = New Size(oColumnWidths(i), nHeight)
    
                                Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
    
                                oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                oBitmap.Height))
    
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    
                            ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
    
                                oCheckbox.Size = New Size(14, 14)
    
                                oCheckbox.Checked = CType(oCell.Value, Boolean)
    
                                Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
    
                                Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
    
                                oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, _
                                0, oBitmap.Width, oBitmap.Height))
    
                                oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, _
                                oCheckbox.Height))
    
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    
                            ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
    
                                oComboBox.Size = New Size(oColumnWidths(i), nHeight)
    
                                Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
    
                                oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                oBitmap.Height))
    
                                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    
                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, _
                                New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) _
                                - 16, nHeight), oStringFormatComboBox)
    
                            ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
    
                                Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, _
                                oColumnWidths(i), nHeight)
    
                                Dim oImageSize As Size = CType(oCell.Value, Image).Size
    
                                e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), _
                                CType(oCell.Value, Image).Width, CType(oCell.Value,  _
                                Image).Height))
    
                            End If
    
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), _
                            nTop, oColumnWidths(i), nHeight))
    
                            i += 1
                        End If
                    Next
    
                End If
    
                nRowPos += 1
    
                nRowsPerPage += 1
    
            Loop
    
            DrawFooter(e, nRowsPerPage)
    
            e.HasMorePages = False
    
        End Sub
    
        Public Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, _
        ByVal RowsPerPage As Int32)
    
            Dim sPageNo As String = nPageNo.ToString + " of "
    
            If nPageNo = "1" Then
    
                lPageNo = Math.Ceiling((DataGridView1.Rows.Count - 1) / RowsPerPage).ToString()
                sPageNo = nPageNo.ToString + " of " + lPageNo
    
            Else
    
                sPageNo = nPageNo.ToString + " of " + lPageNo
    
            End If
    
            ' Right Align - User Name
    
            e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, _
            e.MarginBounds.Left + (e.MarginBounds.Width - _
            e.Graphics.MeasureString(sPageNo, DataGridView1.Font, _
            e.MarginBounds.Width).Width), e.MarginBounds.Top + _
            e.MarginBounds.Height + 7)
    
            ' Left Align - Date/Time
    
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, _
            DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, _
            e.MarginBounds.Top + e.MarginBounds.Height + 7) '7 is a mod (was 31)to raise page no. up one line
    
            ' Center - Page No. Info
    
            e.Graphics.DrawString(sPageNo, DataGridView1.Font, _
            Brushes.Black, e.MarginBounds.Left + _
            (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, _
            DataGridView1.Font, e.MarginBounds.Width).Width) / 2, _
            e.MarginBounds.Top + e.MarginBounds.Height + 7)
    
        End Sub
    End Module
    The calling code calls a specific version of the Sub StartPrint depending upon the click event of either the Landscape or Portrait print buttons . Code below :

     Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
            ' OPortrait = False ' not used in this version
            PrintGrid.StartPrintL(DataGridView1) 'CallPrint module Sub
        End Sub
    
        Private Sub ToolStripButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPortrait.Click
            ' OPortrait = True 'not used in this version
            PrintGrid.StartPrintP(DataGridView1) 'CallPrint module Sub for portrait
        End Sub
    Sunday, March 14, 2010 4:04 PM
  • For those who are reading this post there has been found a fix for this problem. it is as follows.
     Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
           
            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16
    
            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = e.MarginBounds.Top
            Dim nLeft As Int16 = e.MarginBounds.Left
    
    
    ' add the 3 .clear statements below
    
            oColumnLefts.Clear()
            oColumnWidths.Clear()
            oColumnTypes.Clear()
    
    
            If nPageNo = 1 Then
                For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                    nWidth = CType(
    The problem was the Ocolumns are static and were being added to causing the grid to to be off the screen.

    Curtis

    Always Lost in Code,
    Tuesday, March 16, 2010 4:44 PM
  • Discover a Mistake I made in the logic of the above code.

     It should be
     Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
           
            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16
    
            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = e.MarginBounds.Top
            Dim nLeft As Int16 = e.MarginBounds.Left
    If nPageNo = 1 Then
    
    ' add the 3 .clear statements below
    
            oColumnLefts.Clear()
            oColumnWidths.Clear()
            oColumnTypes.Clear()
    
    
            
                For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                    nWidth = CType(
    

    Always Lost in Code,
    Tuesday, March 16, 2010 5:12 PM
  • Hello Curtis or anyone who can help me. This code does seem elegant, but I do get an error when I run it. At the following location:

    For Each oCell As DataGridViewCell In oRow.Cells
                        If oCell.Visible = True Then
                            If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

    I get this error.

    System.NullReferenceException was unhandled
      Message="Object reference not set to an instance of an object."
      Source="AssemblyTreeManual3"
      StackTrace:


    Am I lacking a reference or setting change? Thanks for the help.

    Hollertrek     

    Friday, April 09, 2010 4:54 PM
  • Hollertrek51,

     I edited this post to imform you the code you posted is by Yaboro and not the code I used, below is the code I used. Also the modifications I made is for the code that I am using and may not work for Yaboro's code.

     A null reference means one of the values in the object has nothing in it. Witch Line exactly has the error? You have 4 lines and each one has from 1 to 8 objects that could return the null reference error. When It errors you shoud be able to put the cursor over the different objects and see the value they hold it should show witch one is null. Sometimes it doesn,t work if the reference is from a different function or class.

     Then after you have found the object or variable that is null you have to backtrack to where it is getting its value and find out why it is null.

    The code works for me and without seeing the error and finding out witch object has the null in it, I could not tell you. If it was a setting or reference missing it would be a different error and would have errored out sooner.

    The above code iterates through each cell in a row and if the cell is visible then it checks to see ocolumn type which is a stored variable is the same as the type DataGridview TextBox column type or link column type. If this s true then it draws the cell to the graphics page in memory.
     

     Also did you make the change in code that is shown in my last post? This modfication I made has not been fully tested for all different size of collums or cells and this does effect the For Each Ocell.

     You might post the number of columns and approximately their widiths. so I can try to duplicate this error.

    Curtis


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    • Edited by Curtis UN Friday, April 09, 2010 10:45 PM
    Friday, April 09, 2010 9:51 PM
  • Here is the modified version with a printprview and print dialogs setup. I removed the variables that I used for my application but here is the imports and variables. Aslo shown is the print routine with the page and print dialogs. Of course they are being called from a menustrip.

       Imports System
    Imports System.IO
    Imports System.IO.Ports
    Imports System.Text
    Imports Microsoft.VisualBasic
    Imports System.Drawing
    Imports System.Drawing.Printing
    Imports System.Windows.Forms
    Public Class Spreadsheet
        
        
        Public columCount As Int64
        Public HeaderS As String
        Public rows(1000, 8) As String
        Public row As String
        Private lPageNo As String = ""
        Private sPageNo As String = ""
        Private oStringFormat As StringFormat
        Private oStringFormatComboBox As StringFormat
        Private oButton As Button
        Private oCheckbox As CheckBox
        Private oComboBox As ComboBox
        Private nTotalWidth As Int16
        Private nRowPos As Int16
        Private NewPage As Boolean
        Private nPageNo As Int16
        Private Header As String
     
     Private Sub PrintDocument_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintDocument.Click
    
    
            PrintDialog1.AllowSomePages = True
            ' Show the help button.
            PrintDialog1.ShowHelp = True
            PrintDialog1.Document = PrintDocument1
    
            Dim result As DialogResult = PrintDialog1.ShowDialog()
            ' If the result is OK then print the document.
            If (result = DialogResult.OK) Then
                PrintDocument1.Print()
            End If
        End Sub
        Private Sub PrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreview.Click
           
    
            Dim dlg As New PrintPreviewDialog()
            Dim d
    
            dlg.Document = printdocument1
            d = printdocument1.DefaultPageSettings.Bounds
    
    
            dlg.ShowDialog()
        End Sub
        Private Sub PageSetup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PageSetup.Click
    
            ' Sets the print document's color setting to false,
            ' so that the page will not be printed in color.
            'PageSetupDialog1.Document.DefaultPageSettings.Color = False
            'PageSetupDialog1.ShowDialog()
    
            PageSetupDialog1.Document = PrintDocument1
            PageSetupDialog1.AllowOrientation = True
            PageSetupDialog1.AllowPrinter = True
            'Show the dialog storing the result.
            Dim result As DialogResult = PageSetupDialog1.ShowDialog
    
    
    
    
        End Sub
    
    
          Private Sub InitializeDataGridView()
            ' Create an unbound DataGridView by declaring a column count.
            DataGridView1.ColumnCount = columCount
            DataGridView1.ColumnHeadersVisible = True
            DataGridView1.RowHeadersVisible = True
            ' Set the column header style.
            Dim columnHeaderStyle As New DataGridViewCellStyle()
            columnHeaderStyle.BackColor = Color.White
            columnHeaderStyle.Font = New Font("Verdana", 10, FontStyle.Bold)
            DataGridView1.ColumnHeadersDefaultCellStyle = columnHeaderStyle
        End Sub
    
         Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
    
            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter
    
            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
    
            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox
    
            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    
                nTotalWidth += oColumn.Width
    
            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0
    
    
    
        End Sub
        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
           
            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16
    
            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = e.MarginBounds.Top
            Dim nLeft As Int16 = e.MarginBounds.Left
    
            If nPageNo = 1 Then
                oColumnLefts.Clear()
                oColumnWidths.Clear()
                oColumnTypes.Clear()
                For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
                    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
                    oColumnLefts.Add(nLeft)
                    oColumnWidths.Add(nWidth)
                    oColumnTypes.Add(oColumn.GetType)
                    nLeft += nWidth
                Next
            End If
            Do While nRowPos < DataGridView1.Rows.Count - 1
                Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)
                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
                    DrawFooter(e, nRowsPerPage)
                    NewPage = True
                    nPageNo += 1
                    e.HasMorePages = True
                    Exit Sub
                Else
                    If NewPage Then
                        ' Draw Header
                        e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
                        ' Draw Columns
                        nTop = e.MarginBounds.Top
                        i = 0
                        For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                            i += 1
                        Next
                        NewPage = False
                    End If
                    nTop += nHeight
                    i = 0
                    Dim svalue As String
                    For Each oCell As DataGridViewCell In oRow.Cells
                        If oCell.Value <> Nothing Then
                            svalue = oCell.Value.ToString
                        Else
                            svalue = ""
                        End If
                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                            e.Graphics.DrawString(svalue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
                            oButton.Text = oCell.Value.ToString
                            oButton.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                                                        oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
                            oCheckbox.Size = New Size(14, 14)
                            oCheckbox.Checked = CType(oCell.Value, Boolean)
                            Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, _
                                                        0, oBitmap.Width, oBitmap.Height))
                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width _
                                      - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height _
                                      - oCheckbox.Height) / 2, Int32), oCheckbox.Width, _
                                      oCheckbox.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
                            oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                                                          oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, _
                                       New SolidBrush(oCell.InheritedStyle.ForeColor), New  _
                                       RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) _
                                       - 16, nHeight), oStringFormatComboBox)
                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
                            Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, _
                                                                       oColumnWidths(i), nHeight)
                            Dim oImageSize As Size = CType(oCell.Value, Image).Size
                            e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) _
                                       + CType(((oCellSize.Width _
                                       - oImageSize.Width) / 2), Int32), nTop + CType _
                                       (((oCellSize.Height - oImageSize.Height) / 2), Int32), _
                                       CType(oCell.Value, Image).Width, CType(oCell.Value,  _
                                       Image).Height))
                        End If
                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), _
                                                             nTop, oColumnWidths(i), nHeight))
                        i += 1
                    Next
                End If
                nRowPos += 1
                nRowsPerPage += 1
            Loop
            DrawFooter(e, nRowsPerPage)
            e.HasMorePages = False
        End Sub
    
        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, _
                               ByVal RowsPerPage As Int32)
    
            Dim sPageNo As String = nPageNo.ToString + " of "
            If nPageNo = "1" Then
                ' rowsC = Math.Ceiling(DataGridView1.Rows.Count - 1)
                lPageNo = Math.Ceiling((DataGridView1.Rows.Count - 1) / RowsPerPage).ToString()
                sPageNo = nPageNo.ToString + " of " + lPageNo
            Else
                sPageNo = nPageNo.ToString + " of " + lPageNo
            End If
    
            ' Right Align - User Name
            e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, _
                                  e.MarginBounds.Left + (e.MarginBounds.Width - _
                                  e.Graphics.MeasureString(sPageNo, DataGridView1.Font, _
                                  e.MarginBounds.Width).Width), e.MarginBounds.Top + _
                                  e.MarginBounds.Height + 7)
            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, _
                                  DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, _
                                  e.MarginBounds.Top + e.MarginBounds.Height + 7)
            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridView1.Font, _
                                  Brushes.Black, e.MarginBounds.Left + _
                                  (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, _
                                   DataGridView1.Font, e.MarginBounds.Width).Width) / 2, _
                                   e.MarginBounds.Top + e.MarginBounds.Height + 31)
        End Sub
    
    End Class
    

    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Friday, April 09, 2010 10:12 PM
  • Hello Curtis or anyone who can help me. This code does seem elegant, but I do get an error when I run it. At the following location:

    For Each oCell As DataGridViewCell In oRow.Cells
                        If oCell.Visible = True Then
                            If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

    I get this error.

    System.NullReferenceException was unhandled
      Message="Object reference not set to an instance of an object."
      Source="AssemblyTreeManual3"
      StackTrace:


    Am I lacking a reference or setting change? Thanks for the help.

    Hollertrek     


    I just figured out that the code you posted is Yarboro's posted code. I don't have his code in a working Application. I posted the code I have in A working application above. It was originally written by Will Infinity. If you are using PrintDocument to call the print routine this will work but if your calling in a different way I don't Know if this code woud work or not.

    There is two or three different codes posted above.

    Curtis

     


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    • Edited by Curtis UN Friday, April 09, 2010 10:38 PM spelling
    Friday, April 09, 2010 10:36 PM
  • Hi Curtis,

    Thanks for the response. I'm trying a couple things here. First, my example code was to give a context, the last line producing the error. It appears the oCell.Value.ToString is the null value. If that line is taken out I'm able to print the grid with no values. For some reason the values are not getting to the grid. I'll have to look at that more carefully.

     

    Secondly, I've placed your code and as a class it doesn't recognize the controls on the form. If I remove the class heading the controls are then recognized but I now get the error at each sub heading, statement not valid in a namespace . I must be missing something simple.

     

    Jon

    Monday, April 12, 2010 2:12 PM
  • Gilberto74 Users Medals Users Medals Users Medals Users Medals Users Medals
     
    I have a workaround to your problem.
    There's a better solution i guess, but anyway...

    01. FIRST: Identify the position of your datagridview column with datetime format, starting at ZERO for the first column;
    02. SECOND: Change this portion of code:

    (...)
    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
    (...)

    TO THIS:
    (...)
    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    if i=<>2 (supose that's the position number of your datetime format column) then
    e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
    else
    e.Graphics.DrawString(iif(oCell.Value.ToString="",oCell.Value.ToString,oCell.Value), oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
    end if
    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
    (...)

    It works for me!
    Tuesday, April 27, 2010 11:43 PM
  • You can download a Visual Studio 2010 solution at:

    http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=7777&lngWId=10

    It contains the solutions that have been posted in this forum, as well as a few other features.
    Monday, May 03, 2010 1:43 PM
  • Friday, June 11, 2010 11:43 AM
  • I used this code and works perfect as i need for direct print.

    Thanks a lot.

    Wednesday, July 21, 2010 4:40 AM
    • Edited by leon geve Wednesday, September 29, 2010 6:50 AM
    Wednesday, September 29, 2010 6:49 AM
  • The code works great...Thank You all so much....

    How do you change the font size in the printing grid?

    I can print and it works fine but sometimes the info is to large for the column and thats when the sheet thats printed out gets sloppy looking.

    What would be ideal is to change the font size inside the grid only for printing purposes. Anyone know how?

    Wednesday, September 29, 2010 8:31 PM
  • hi 

    the code gives uniform column width for all columns.....

    For Each oColumn As DataGridViewColumn In DataGridView1.Columns
            nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

    how to set different column width for different columns??


    Rismiya Nasrudeen
    Wednesday, December 15, 2010 1:26 PM
  • Hi Rismiya,

     If I remeber correctly the oColumn.Width is data from the gridveiw and this is used to calculate the individual column widths. So If in the gridview mode before calling the print you set the width of the colums to display all the data in the column on the screen it should print the data correctly.

     But I am not 100% sure of this because I lost most of my applications due to a system failure and have not had time to reinstall all the VB source codes.

     

    Curtis


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Thursday, December 16, 2010 7:01 PM
  • Oh how i wish i'd found this code before now!

    I have one issue however, in print preview it shows the message below;

    'Document does not contain any pages'

    I can't seem to find where PrintDocument1 is populated in the code above? Am i missing something obvious here?

    Thursday, December 16, 2010 8:20 PM
  • Hi AnqeTB,

     The printdocument1 gets the data from the datgridview1 in the following routine. Do you have a datagridview setup with data in it? Also the name of the datgridview is datagridview1 and it uses this name to retrieve data. If you will post your code I will look at it and see where it is failing to gett he data.

     

      Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        
        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16
    
        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = e.MarginBounds.Top
        Dim nLeft As Int16 = e.MarginBounds.Left
    
        If nPageNo = 1 Then
          oColumnLefts.Clear()
          oColumnWidths.Clear()
          oColumnTypes.Clear()
          For Each oColumn As DataGridViewColumn In DataGridView1.Columns
            nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
            nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
            oColumnLefts.Add(nLeft)
            oColumnWidths.Add(nWidth)
            oColumnTypes.Add(oColumn.GetType)
            nLeft += nWidth
          Next
        End If
        Do While nRowPos < DataGridView1.Rows.Count - 1
          Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)
          If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
            DrawFooter(e, nRowsPerPage)
            NewPage = True
            nPageNo += 1
            e.HasMorePages = True
            Exit Sub
          Else
            If NewPage Then
              ' Draw Header
              e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
              ' Draw Columns
              nTop = e.MarginBounds.Top
              i = 0
              For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                i += 1
              Next
              NewPage = False
            End If
            nTop += nHeight
            i = 0
            Dim svalue As String
            For Each oCell As DataGridViewCell In oRow.Cells
              If oCell.Value <> Nothing Then
                svalue = oCell.Value.ToString
              Else
                svalue = ""
              End If
              If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                e.Graphics.DrawString(svalue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
              ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
                oButton.Text = oCell.Value.ToString
                oButton.Size = New Size(oColumnWidths(i), nHeight)
                Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                      oBitmap.Height))
                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
              ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
                oCheckbox.Size = New Size(14, 14)
                oCheckbox.Checked = CType(oCell.Value, Boolean)
                Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, _
                              0, oBitmap.Width, oBitmap.Height))
                oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width _
                     - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height _
                     - oCheckbox.Height) / 2, Int32), oCheckbox.Width, _
                     oCheckbox.Height))
                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
              ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
                oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                       oBitmap.Height))
                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, _
                      New SolidBrush(oCell.InheritedStyle.ForeColor), New _
                      RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) _
                      - 16, nHeight), oStringFormatComboBox)
              ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
                Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, _
                                      oColumnWidths(i), nHeight)
                Dim oImageSize As Size = CType(oCell.Value, Image).Size
                e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) _
                      + CType(((oCellSize.Width _
                      - oImageSize.Width) / 2), Int32), nTop + CType _
                      (((oCellSize.Height - oImageSize.Height) / 2), Int32), _
                      CType(oCell.Value, Image).Width, CType(oCell.Value, _
                      Image).Height))
              End If
              e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), _
                                 nTop, oColumnWidths(i), nHeight))
              i += 1
            Next
          End If
          nRowPos += 1
          nRowsPerPage += 1
        Loop
        DrawFooter(e, nRowsPerPage)
        e.HasMorePages = False
      End Sub
    
    
    
    

     Curtis


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Friday, December 17, 2010 1:08 AM
  • Hi Curtis,

    I have a date column in my datagridview. The column is showing the date as well as time. So i have formatted it using the following code to show only date

    datagridview.columns("DueDate").DefaultCellStyle.Format = "dd/mm/yy"

    This code shows only the date in the DataGridView. But in the Print Preview, it is showing both time and date. I want to print only date.

    My data is connected to the Access Database. In the Acess File, This column is formatted as Short Date. Please Help

     


    Rismiya Nasrudeen
    Monday, December 20, 2010 11:47 AM
  • Rismiya1989,

     Please don't ask a question of a certain person. The reason is there are a lot of people on the forums that might be able to answer the question better and by asking a certain person the others most likely will not reply. Give ereryone a chance to answer.

     This routine takes all the columns and prints them as they are in the gridview. The date time cell in datagridview is similar to a database in that the date field always has the time included and there is now way to exclude the time from the cell.

     That said the only way would be to modify the print routine where it is getting the data for each column and test it to see if it is a date time field then format the date time field without the time and put this in the variable instead of what is now being put in.

     At the moment I don't have time to write and test a code for this. So if there is someone else out there that has time please give him a little help.

     I will look into it in a day or so and see what can be done if someone else doesn't reply.

    Curtis


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Monday, December 20, 2010 8:26 PM
  • Rismiya1989,

    You would have to do something like this to remove the time from the date time being displayed in print preview or printed. Because there is no actual date time field in datagrid view and it is just a text field, you have to test the string for certain charectors. The Database Date time always has both the date and time in the field and can not be altered. So either the date has to be formated before it is put into datagridview or the printdocument1_PrintPage sub has to be altered as I have done in this example.

      Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        
        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16
    
        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = e.MarginBounds.Top
        Dim nLeft As Int16 = e.MarginBounds.Left
    
        If nPageNo = 1 Then
          oColumnLefts.Clear()
          oColumnWidths.Clear()
          oColumnTypes.Clear()
          For Each oColumn As DataGridViewColumn In DataGridView1.Columns
            nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
            nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
            oColumnLefts.Add(nLeft)
            oColumnWidths.Add(nWidth)
            oColumnTypes.Add(oColumn.GetType)
            nLeft += nWidth
          Next
        End If
        Do While nRowPos < DataGridView1.Rows.Count - 1
          Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)
          If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
            DrawFooter(e, nRowsPerPage)
            NewPage = True
            nPageNo += 1
            e.HasMorePages = True
            Exit Sub
          Else
            If NewPage Then
              ' Draw Header
              e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
              ' Draw Columns
              nTop = e.MarginBounds.Top
              i = 0
              For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                i += 1
              Next
              NewPage = False
            End If
            nTop += nHeight
            i = 0
            Dim svalue As String
            For Each oCell As DataGridViewCell In oRow.Cells
              If oCell.Value <> Nothing Then
                svalue = oCell.Value.ToString
              Else
                svalue = ""
              End If
    
    
    ' Test for Date in cells and remove time---------------------------------------
              If svalue.Contains("/") Then
                svalue = svalue.Substring(0,10)
              End If
    ' End test for date ---------------------------------------------------------------
    
    
              If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                e.Graphics.DrawString(svalue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
              ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
                oButton.Text = oCell.Value.ToString
                oButton.Size = New Size(oColumnWidths(i), nHeight)
                Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                      oBitmap.Height))
                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
              ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
                oCheckbox.Size = New Size(14, 14)
                oCheckbox.Checked = CType(oCell.Value, Boolean)
                Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, _
                              0, oBitmap.Width, oBitmap.Height))
                oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width _
                     - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height _
                     - oCheckbox.Height) / 2, Int32), oCheckbox.Width, _
                     oCheckbox.Height))
                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
              ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
                oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                       oBitmap.Height))
                e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, _
                      New SolidBrush(oCell.InheritedStyle.ForeColor), New _
                      RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) _
                      - 16, nHeight), oStringFormatComboBox)
              ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
                Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, _
                                      oColumnWidths(i), nHeight)
                Dim oImageSize As Size = CType(oCell.Value, Image).Size
                e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) _
                      + CType(((oCellSize.Width _
                      - oImageSize.Width) / 2), Int32), nTop + CType _
                      (((oCellSize.Height - oImageSize.Height) / 2), Int32), _
                      CType(oCell.Value, Image).Width, CType(oCell.Value, _
                      Image).Height))
              End If
          e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), _
                             nTop, oColumnWidths(i), nHeight))
          i += 1
            Next
          End If
          nRowPos += 1
          nRowsPerPage += 1
        Loop
        DrawFooter(e, nRowsPerPage)
        e.HasMorePages = False
      End Sub
    
    
    

     

     In the above the code the string has the date in it like this "12/21/2010 12:34" I am checking to see if there is a / in the string and if there is then I am then I am getting a sub string of the svalue equal to the length of the date which is 10 charectors. this removes the time from the string and returns "12/21/2010"

    Curtis


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    • Proposed as answer by Rismiya1989 Tuesday, December 21, 2010 3:31 PM
    Tuesday, December 21, 2010 2:47 PM
  • Thank You.

    I just tried it. It works. 


    Rismiya Nasrudeen
    Tuesday, December 21, 2010 3:32 PM
  • Hi

    I have an application connected to Access Database. In the Access Database, I have a column called "Due_Date". 

    In the application, I have a search option. The results of search are displayed in a datagridview. I use sql query such as the following....

    dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"

    dbSource = "Data Source = F:\App.mdb"

    con.ConnectionString = dbProvider & dbSource

    con.Open()

    sql = "SELECT * FROM Register WHERE [Due_Date] = #" & DateTimePicker1.Value.Date & "#"

    da = New OleDb.OleDbDataAdapter(sql, con)

    da.Fill(ds, "Register")

    con.Close()

    DataGridView1.DataSource = ds.Tables(0)

     

    The problem is for some of the records, due date is NULL. When i search, it shows the error "Data type mismatch in criteria expression"

    But when all the records have a date in the due_date column, there is no error.

    The thing is the records can have NULL value in due_date column....is there any way to fix this??


    Rismiya Nasrudeen
    Saturday, January 01, 2011 12:25 PM
  • Rismiya1989,

    This question needs to be asked on one of the Data base forum's. I am not very good with database stuff.

    But there is, you can change the data base due date field to where it cannot contain a null value. This will force a date to be entered into this field or you can give it a default value when the database data is entered in to the database with no due date. Such as 00/00/00 00:00 entered when there is no due date.

     But this has to be handled using the database or as the data is entered into the data base. So you need to ask on a database forum to get the best answer.

     

    Curtis 


    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Saturday, January 01, 2011 3:20 PM
  • Hi,

    if you want to print not only the cell contents but the ALL the cell settings (most especially the cell background color

    in the code of  Forkbeard you just add the follwing:

     

    Private Sub Printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage
    ...............................

    ...............................

     

     For Each oCell As DataGridViewCell In oRow.Cells

      If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    ................................

     

                       e.Graphics.FillRectangle(New SolidBrush(oCell.InheritedStyle.BackColor), CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight)

    paste the above in each if

    Friday, January 07, 2011 1:14 PM
  • Hi guys, I have a problem in this lines

    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

    this is the error

    {"El índice estaba fuera del intervalo. Debe ser un valor no negativo e inferior al tamaño de la colección. Nombre del parámetro: index"}

     

    if somebody help me, I appreciate.

    Thanks

    Friday, January 07, 2011 4:16 PM
  • el Billy change this  Do While nRowPos < DataGridViewToPrint.Rows.Count with this Do While nRowPos < DataGridViewToPrint.Rows.Count - 1
    Friday, January 07, 2011 5:25 PM
  • Hi Friend...I have use the code...I was error free...But I don't know how to print my records from my datagridview....Because there was no code been use for the print button...I have a print button...your code you didn't put any code for the print button...Please how can this work without a code in the print button?..thkx hope to hear from u soon.
    Friday, March 11, 2011 6:35 PM
  • Hi AronHall,

     In the full code I posted earlier about 20 posts pervious you will notice the following code. This code handles the print button, Preview button and page setup.

     
     Private Sub PrintDocument_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintDocument.Click
    
    
        PrintDialog1.AllowSomePages = True
        ' Show the help button.
        PrintDialog1.ShowHelp = True
        PrintDialog1.Document = PrintDocument1
    
        Dim result As DialogResult = PrintDialog1.ShowDialog()
        ' If the result is OK then print the document.
        If (result = DialogResult.OK) Then
          PrintDocument1.Print()
        End If
      End Sub
      Private Sub PrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreview.Click
        
    
        Dim dlg As New PrintPreviewDialog()
        Dim d
    
        dlg.Document = printdocument1
        d = printdocument1.DefaultPageSettings.Bounds
    
    
        dlg.ShowDialog()
      End Sub
      Private Sub PageSetup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PageSetup.Click
    
        ' Sets the print document's color setting to false,
        ' so that the page will not be printed in color.
        'PageSetupDialog1.Document.DefaultPageSettings.Color = False
        'PageSetupDialog1.ShowDialog()
    
        PageSetupDialog1.Document = PrintDocument1
        PageSetupDialog1.AllowOrientation = True
        PageSetupDialog1.AllowPrinter = True
        'Show the dialog storing the result.
        Dim result As DialogResult = PageSetupDialog1.ShowDialog
    
    
    
    
      End Sub
    
    
    Hope this helps.
    Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
    • Proposed as answer by AaronHall Sunday, March 13, 2011 4:28 PM
    Friday, March 11, 2011 10:02 PM
  • Hi,

    This code (original post) is great.

    I copied and pasted it all in a VB.NET class (called PrintGrid) and instantiated from my forms. It worked perfectly for Print and PrintPreview of a 4000 row grid in more than 100 pages.

     Here is a code of instantiation for those who may got error.

      Dim Prt

      Prt = New PrintGrid(DataGridView1, Title, PageSettings , "") 

      Prt.ShowPrintPreviewDialog()

      Prt = Nothing

    Thanks,


    PM


    Tuesday, May 17, 2011 5:08 PM
  • Is there a way to change the column widths? I am not sure how to do this. I need each column to be a certain width. I would settle for all of them being the same width, I just need them to be wider. The row height works but it would also be nice to know how to change that.

    Thanks guys!

    This is what I have so far:

     Dim oStringFormat As StringFormat
        Dim oStringFormatComboBox As StringFormat
        Dim oButton As Button
        Dim oCheckbox As CheckBox
        Dim oComboBox As ComboBox

        Dim nTotalWidth As Int16
        Dim nRowPos As Int16
        Dim NewPage As Boolean
        Dim nPageNo As Int16
        Dim Header As String = "YellowTag Data"
        Dim sUserName As String = ""

        Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

            oStringFormat = New StringFormat
            oStringFormat.Alignment = StringAlignment.Near
            oStringFormat.LineAlignment = StringAlignment.Center
            oStringFormat.Trimming = StringTrimming.EllipsisCharacter

            oStringFormatComboBox = New StringFormat
            oStringFormatComboBox.LineAlignment = StringAlignment.Center
            oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
            oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

            oButton = New Button
            oCheckbox = New CheckBox
            oComboBox = New ComboBox

            nTotalWidth = 0
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                nTotalWidth += oColumn.Width

            Next
            nPageNo = 1
            NewPage = True
            nRowPos = 0

        End Sub

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16

            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = e.MarginBounds.Top
            Dim nLeft As Int16 = e.MarginBounds.Left

            If nPageNo = 1 Then

                For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                    oColumnLefts.Add(nLeft)
                    oColumnWidths.Add(nWidth)
                    oColumnTypes.Add(oColumn.GetType)
                    nLeft += nWidth

                Next

            End If

            Do While nRowPos < DataGridView1.Rows.Count - 1

                Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                    DrawFooter(e, nRowsPerPage)

                    NewPage = True
                    nPageNo += 1
                    e.HasMorePages = True
                    Exit Sub

                Else

                    If NewPage Then

                        ' Draw Header
                        e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        ' Draw Columns
                        nTop = e.MarginBounds.Top
                        i = 0
                        For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                            i += 1

                        Next
                        NewPage = False

                    End If

                    nTop += nHeight
                    i = 0
                    For Each oCell As DataGridViewCell In oRow.Cells


                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                            oButton.Text = oCell.Value.ToString
                            oButton.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                            oCheckbox.Size = New Size(14, 14)
                            oCheckbox.Checked = CType(oCell.Value, Boolean)
                            Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                            oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                            Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
                            Dim oImageSize As Size = CType(oCell.Value, Image).Size
                            e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                        End If

                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                        i += 1

                    Next

                End If

                nRowPos += 1
                nRowsPerPage += 1

            Loop

            DrawFooter(e, nRowsPerPage)

            e.HasMorePages = False

        End Sub

        Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

            Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

            ' Right Align - User Name
            e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Left Align - Date/Time
            e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

            ' Center  - Page No. Info
            e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

        End Sub

    Thursday, June 23, 2011 4:56 PM
  • Hi awhiteguy,

     Yes you can change the printed out collum width. But this is a little difficult, Below is the calculation that gets the width of each collumn. If you need all the collumns wider then you could just add the amount of increase to the this line "nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)" such as nwidth += 10 after the calculation line or you can subtract an amount from this to shorten the width. This will increase/decrease all the collumns but if you want to increase/decrease just one collumn or several that contains example "line" that would require a test of the oCollum.name for that collumn name as shown in the code example

    First code example.

     If nPageNo = 1 Then
          oColumnLefts.Clear()
          oColumnWidths.Clear()
          oColumnTypes.Clear()
          For Each oColumn As DataGridViewColumn In DataGridView1.Columns
            ' This Changes the width for one particular column 
            If oColumn.Name.Contains("Line") Then
              nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16) + 10
            Else
              nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
            End If
    
            nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
            oColumnLefts.Add(nLeft)
            oColumnWidths.Add(nWidth)
            oColumnTypes.Add(oColumn.GetType)
            nLeft += nWidth
          Next
        End If
    

     There is a drawback to doing this the print out width may be too wide for the paper. All I can check with right now is a printpreview because the printer is out of ink aaaaagainnnnnnn (grand Children Playing LOL).

     

     

     

     


    Curtis Always Lost in Code. Always mark answers as correct if they answer your question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Thursday, June 23, 2011 6:39 PM
  • Thanks for you help! That definitely works.

    I see what you mean now by it not being all on one page. So my next issue is that in my page setup, after I select landscape and change the margins, and then go back into print preview, it does not change the layout for some reason. I will copy and past my entire code for the "Data form" I have created.

    Also, do you know of a way to make it fit on one page? I bet even after I print landscape and change the margins that it will not all fit on one page :/

     

    **EDIT

    I just noticed that in my print preview, that at the bottom it says "1 of 2" when there is only one page and also only prints one page. Any suggestions?

     

     

    Imports System.IO
    Imports System.Data.OleDb
    Imports System.Drawing.Printing
    
    
    Public Class DataForm
    
     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
     Dim TextFileReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("C:\Users\yellowtag.csv")
    
     TextFileReader.TextFieldType = FileIO.FieldType.Delimited
     TextFileReader.SetDelimiters(",")
    
     Dim TextFileTable As DataTable = New DataTable("TextFileTable")
    
     ' Declare variables for DataColumn and DataRow objects.
     Dim Column0 As DataColumn
     Dim Column1 As DataColumn
     Dim Column2 As DataColumn
     Dim Column3 As DataColumn
     Dim Column4 As DataColumn
     Dim Column5 As DataColumn
     Dim Column6 As DataColumn
     Dim Column7 As DataColumn
     Dim Column8 As DataColumn
     Dim Column9 As DataColumn
     Dim Column10 As DataColumn
     Dim Column11 As DataColumn
     Dim Column12 As DataColumn
     Dim Column13 As DataColumn
     Dim Column14 As DataColumn
     Dim Column15 As DataColumn
     Dim Column16 As DataColumn
     Dim Column17 As DataColumn
     Dim Column18 As DataColumn
    
     Dim Row As DataRow
    
     ' Create DataTable with 18 text columns
     Column0 = New DataColumn()
     Column0.DataType = System.Type.GetType("System.String")
     Column0.ColumnName = "Tag Number"
     Column0.Caption = "Column"
     Column0.ReadOnly = True
     Column0.Unique = False
     TextFileTable.Columns.Add(Column0)
    
     Column1 = New DataColumn()
     Column1.DataType = System.Type.GetType("System.String")
     Column1.ColumnName = "Serial Number"
     Column1.Caption = "Column"
     Column1.ReadOnly = True
     Column1.Unique = False
     TextFileTable.Columns.Add(Column1)
    
     Column2 = New DataColumn()
     Column2.DataType = System.Type.GetType("System.String")
     Column2.ColumnName = "Customer"
     Column2.Caption = "Column"
     Column2.ReadOnly = True
     Column2.Unique = False
     TextFileTable.Columns.Add(Column2)
    
     Column3 = New DataColumn()
     Column3.DataType = System.Type.GetType("System.String")
     Column3.ColumnName = "Project"
     Column3.Caption = "Column"
     Column3.ReadOnly = True
     Column3.Unique = False
     TextFileTable.Columns.Add(Column3)
    
     Column4 = New DataColumn()
     Column4.DataType = System.Type.GetType("System.String")
     Column4.ColumnName = "Code"
     Column4.Caption = "Column"
     Column4.ReadOnly = True
     Column4.Unique = False
     TextFileTable.Columns.Add(Column4)
    
     Column5 = New DataColumn()
     Column5.DataType = System.Type.GetType("System.String")
     Column5.ColumnName = "Station Number"
     Column5.Caption = "Column"
     Column5.ReadOnly = True
     Column5.Unique = False
     TextFileTable.Columns.Add(Column5)
    
     Column6 = New DataColumn()
     Column6.DataType = System.Type.GetType("System.String")
     Column6.ColumnName = "Number of Pieces"
     Column6.Caption = "Column"
     Column6.ReadOnly = True
     Column6.Unique = False
     TextFileTable.Columns.Add(Column6)
    
     Column7 = New DataColumn()
     Column7.DataType = System.Type.GetType("System.String")
     Column7.ColumnName = "Defect Description"
     Column7.Caption = "Column"
     Column7.ReadOnly = True
     Column7.Unique = False
     TextFileTable.Columns.Add(Column7)
    
     Column8 = New DataColumn()
     Column8.DataType = System.Type.GetType("System.String")
     Column8.ColumnName = "Date"
     Column8.Caption = "Column"
     Column8.ReadOnly = True
     Column8.Unique = False
     TextFileTable.Columns.Add(Column8)
    
     Column9 = New DataColumn()
     Column9.DataType = System.Type.GetType("System.String")
     Column9.ColumnName = "Supervisor Initials"
     Column9.Caption = "Column"
     Column9.ReadOnly = True
     Column9.Unique = False
     TextFileTable.Columns.Add(Column9)
    
     Column10 = New DataColumn()
     Column10.DataType = System.Type.GetType("System.String")
     Column10.ColumnName = "Employee Initials"
     Column10.Caption = "Column"
     Column10.ReadOnly = True
     Column10.Unique = False
     TextFileTable.Columns.Add(Column10)
    
     Column11 = New DataColumn()
     Column11.DataType = System.Type.GetType("System.String")
     Column11.ColumnName = "Completed By"
     Column11.Caption = "Column"
     Column11.ReadOnly = True
     Column11.Unique = False
     TextFileTable.Columns.Add(Column11)
    
     Column12 = New DataColumn()
     Column12.DataType = System.Type.GetType("System.String")
     Column12.ColumnName = "Date Completed"
     Column12.Caption = "Column"
     Column12.ReadOnly = True
     Column12.Unique = False
     TextFileTable.Columns.Add(Column12)
    
     Column13 = New DataColumn()
     Column13.DataType = System.Type.GetType("System.String")
     Column13.ColumnName = "Damage"
     Column13.Caption = "Column"
     Column13.ReadOnly = True
     Column13.Unique = False
     TextFileTable.Columns.Add(Column13)
    
     Column14 = New DataColumn()
     Column14.DataType = System.Type.GetType("System.String")
     Column14.ColumnName = "Damaged Part"
     Column14.Caption = "Column"
     Column14.ReadOnly = True
     Column14.Unique = False
     TextFileTable.Columns.Add(Column14)
    
     Column15 = New DataColumn()
     Column15.DataType = System.Type.GetType("System.String")
     Column15.ColumnName = "Corrective Action"
     Column15.Caption = "Column"
     Column15.ReadOnly = True
     Column15.Unique = False
     TextFileTable.Columns.Add(Column15)
    
     Column16 = New DataColumn()
     Column16.DataType = System.Type.GetType("System.String")
     Column16.ColumnName = "Part"
     Column16.Caption = "Column"
     Column16.ReadOnly = True
     Column16.Unique = False
     TextFileTable.Columns.Add(Column16)
    
     Column17 = New DataColumn()
     Column17.DataType = System.Type.GetType("System.String")
     Column17.ColumnName = "Tag Color"
     Column17.Caption = "Column"
     Column17.ReadOnly = True
     Column17.Unique = False
     TextFileTable.Columns.Add(Column17)
    
     Column18 = New DataColumn()
     Column18.DataType = System.Type.GetType("System.String")
     Column18.ColumnName = "Outgoing Serial Number"
     Column18.Caption = "Column"
     Column18.ReadOnly = True
     Column18.Unique = False
     TextFileTable.Columns.Add(Column18)
    
     Dim CurrentRow As String()
    
     While Not TextFileReader.EndOfData
    
     Try
    
     CurrentRow = TextFileReader.ReadFields()
     Row = TextFileTable.NewRow
     Row("Tag Number") = CurrentRow(0).ToString
     Row("Serial Number") = CurrentRow(1).ToString
     Row("Customer") = CurrentRow(2).ToString
     Row("Project") = CurrentRow(3).ToString
     Row("Code") = CurrentRow(4).ToString
     Row("Station Number") = CurrentRow(5).ToString
     Row("Number of Pieces") = CurrentRow(6).ToString
     Row("Defect Description") = CurrentRow(7).ToString
     Row("Date") = CurrentRow(8).ToString
     Row("Supervisor Initials") = CurrentRow(9).ToString
     Row("Employee Initials") = CurrentRow(10).ToString
     Row("Completed By") = CurrentRow(11).ToString
     Row("Date Completed") = CurrentRow(12).ToString
     Row("Damage") = CurrentRow(13).ToString
     Row("Damaged Part") = CurrentRow(14).ToString
     Row("Corrective Action") = CurrentRow(15).ToString
     Row("Part") = CurrentRow(16).ToString
     Row("Tag Color") = CurrentRow(17).ToString
     Row("Outgoing Serial Number") = CurrentRow(18).ToString
    
     TextFileTable.Rows.Add(Row)
    
     Catch ex As _
     Microsoft.VisualBasic.FileIO.MalformedLineException
     MsgBox("Line " & ex.Message & _
     "is not valid and will be skipped.")
     End Try
    
     End While
    
     TextFileReader.Dispose()
    
     DataGridView1.DataSource = TextFileTable
    
     End Sub
    
     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintDataButton.Click
     PrintDialog1.AllowSomePages = True
    
     ' Show the help button.
     PrintDialog1.ShowHelp = True
     PrintDialog1.Document = PrintDocument1
    
     Dim result As DialogResult = PrintDialog1.ShowDialog()
    
     ' If the result is OK then print the document.
     If (result = DialogResult.OK) Then
     PrintDocument1.Print()
     End If
    
     End Sub
    
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreviewButton.Click
     Dim dlg As New PrintPreviewDialog()
     Dim d
    
     dlg.Document = PrintDocument1
     d = PrintDocument1.DefaultPageSettings.Bounds
    
     dlg.ShowDialog()
    
     End Sub
    
    
     Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PageSetupButton.Click
     Dim psDlg As New PageSetupDialog
    
     Dim storedPageSettings As PageSettings = New PageSettings()
    
     psDlg.PageSettings = storedPageSettings
    
     psDlg.ShowDialog()
    
     End Sub
    
     Dim oStringFormat As StringFormat
     Dim oStringFormatComboBox As StringFormat
     Dim oButton As Button
     Dim oCheckbox As CheckBox
     Dim oComboBox As ComboBox
    
     Dim nTotalWidth As Int16
     Dim nRowPos As Int16
     Dim NewPage As Boolean
     Dim nPageNo As Int16
     Dim Header As String = "YellowTag Data"
     Dim sUserName As String = ""
    
     Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
    
     oStringFormat = New StringFormat
     oStringFormat.Alignment = StringAlignment.Near
     oStringFormat.LineAlignment = StringAlignment.Center
     oStringFormat.Trimming = StringTrimming.EllipsisCharacter
    
     oStringFormatComboBox = New StringFormat
     oStringFormatComboBox.LineAlignment = StringAlignment.Center
     oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
     oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
    
     oButton = New Button
     oCheckbox = New CheckBox
     oComboBox = New ComboBox
    
     nTotalWidth = 0
    
     For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    
     nTotalWidth += oColumn.Width
    
     Next
     nPageNo = 1
     NewPage = True
     nRowPos = 0
    
     End Sub
    
     Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    
     Static oColumnLefts As New ArrayList
     Static oColumnWidths As New ArrayList
     Static oColumnTypes As New ArrayList
     Static nHeight As Int16
    
     Dim nWidth, i, nRowsPerPage As Int16
     Dim nTop As Int16 = e.MarginBounds.Top
     Dim nLeft As Int16 = e.MarginBounds.Left
    
     If nPageNo = 1 Then
    
     oColumnLefts.Clear()
     oColumnWidths.Clear()
     oColumnTypes.Clear()
    
    
    
     For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    
     nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
     nWidth += 15
    
     nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
    
     oColumnLefts.Add(nLeft)
     oColumnWidths.Add(nWidth)
     oColumnTypes.Add(oColumn.GetType)
     nLeft += nWidth
    
     ' This Changes the width for one particular column 
     'If oColumn.Name.Contains("Line") Then
     ' nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16) + 10
     'Else
     ' nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
     'End If
    
     'nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
     'oColumnLefts.Add(nLeft)
     'oColumnWidths.Add(nWidth)
     'oColumnTypes.Add(oColumn.GetType)
     'nLeft += nWidth
    
     Next
    
     End If
    
     Do While nRowPos < DataGridView1.Rows.Count - 1
    
     Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)
    
     If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
    
     DrawFooter(e, nRowsPerPage)
    
     NewPage = True
     nPageNo += 1
     e.HasMorePages = True
     Exit Sub
    
     Else
    
     If NewPage Then
    
      ' Draw Header
      e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
    
      ' Draw Columns
      nTop = e.MarginBounds.Top
      i = 0
      For Each oColumn As DataGridViewColumn In DataGridView1.Columns
    
      e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
      e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
      e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
      i += 1
    
      Next
      NewPage = False
    
     End If
    
     nTop += nHeight
     i = 0
     For Each oCell As DataGridViewCell In oRow.Cells
    
    
      If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
    
      e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
    
      ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
    
      oButton.Text = oCell.Value.ToString
      oButton.Size = New Size(oColumnWidths(i), nHeight)
      Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
      oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
      e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    
      ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
    
      oCheckbox.Size = New Size(14, 14)
      oCheckbox.Checked = CType(oCell.Value, Boolean)
      Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
      Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
      oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
      oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
      e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
    
      ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
    
      oComboBox.Size = New Size(oColumnWidths(i), nHeight)
      Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
      oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
      e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
      e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)
    
      ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
    
      Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
      Dim oImageSize As Size = CType(oCell.Value, Image).Size
      e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))
    
      End If
    
      e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
    
      i += 1
    
     Next
    
     End If
    
     nRowPos += 1
     nRowsPerPage += 1
    
     Loop
    
     DrawFooter(e, nRowsPerPage)
    
     e.HasMorePages = False
    
     End Sub
    
     Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)
    
     Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString
    
     ' Right Align - User Name
     e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)
    
     ' Left Align - Date/Time
     e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)
    
     ' Center - Page No. Info
     e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)
    
     End Sub
    
    End Class


     




    Thursday, June 23, 2011 8:19 PM
  • To start with what the caluclation for nwidth does is try to resize the  the column widths so they will fit on a page but this is not always the perfect solution. you have 18 columns with each column at 15 charecters wide this comes out to 270 charectors wide so depending on the font size your print could be several pages or on one page that has very small print.

     There is printer and page setup code you can use to set the page width and layout. Here is some I use in a datagridview. This code will allow you to setup the printer and the page layout. There is a lot of print settings that can be modified using these type controls. All of theses settings depend on the type printer you have. Try adding the below code for   PageSetupDialog1.Document = PrintDocument1,  PageSetupDialog1.AllowOrientation = True,  PageSetupDialog1.AllowPrinter = True This may be the reason the orintation is not working. I had trouble with this also but don't remember what I did to correct it.

     

     Private Sub PrinterSetupToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrinterSetupToolStripMenuItem.Click
        Dim printerdialog As New PrintDialog
        printerdialog.ShowDialog()
      End Sub
      Private Sub PageSetup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PageSetup.Click
    
        ' Sets the print document's color setting to false,
        ' so that the page will not be printed in color.
        'PageSetupDialog1.Document.DefaultPageSettings.Color = False
        'PageSetupDialog1.ShowDialog()
        PageSetupDialog1.Document = PrintDocument1
        PageSetupDialog1.AllowOrientation = True
        PageSetupDialog1.AllowPrinter = True
        'Show the dialog storing the result.
        Dim result As DialogResult = PageSetupDialog1.ShowDialog
      End Sub
    

     Hope this helps you. I don't know of a real good way to print out this datagrid view but using the original calculation will reduse the size of the fields. If some of the fields are less then the column size and you could reduce those the this would help you.

     As I have time this week end I will setup your code in a project and see if I can figure out the best weay to handle this printout.

    Curtis

     

     


    Curtis Always Lost in Code. Always mark answers as correct if they answer your question and solve your problem. This way others when searching for similar problems can find the answer faster.
    Friday, June 24, 2011 4:59 AM
  • Great! I can change my page setup options now so that is good. I actually have 19 columns though because I started them at column0 and it goes up to column18. I bet if I ran a test for each column like you were saying, to find an appropriate width for each column that I could fit all of them on one page. Right now it will print 15 columns landscape with 0.1 margins, so I just need to be able to print 4 more columns on a page. Here is the updated code from top to bottom:

     

    ***EDIT

    If I set the code as follows:

     For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
                    nWidth += 5

    When nWidth += 5 is about as close as I can get to getting all the columns on the page without it skipping out on a column or having all the columns squished up. nWidth+=15 was too much. I can get 18 columns to display right now, just lacking the last column. Is there a way to change the font size? I think I can do that on the properties for the datagridview itself, but I don't know if it will affect the way it prints out.

    ***

    Imports System.IO
    Imports System.Data.OleDb
    Imports System.Drawing.Printing
    
    
    Public Class DataForm
    
     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
      Dim TextFileReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("C:\Users\yellowtag.csv")
    
      TextFileReader.TextFieldType = FileIO.FieldType.Delimited
      TextFileReader.SetDelimiters(",")
    
      Dim TextFileTable As DataTable = New DataTable("TextFileTable")
    
      ' Declare variables for DataColumn and DataRow objects.
      Dim Column0 As DataColumn
      Dim Column1 As DataColumn
      Dim Column2 As DataColumn
      Dim Column3 As DataColumn
      Dim Column4 As DataColumn
      Dim Column5 As DataColumn
      Dim Column6 As DataColumn
      Dim Column7 As DataColumn
      Dim Column8 As DataColumn
      Dim Column9 As DataColumn
      Dim Column10 As DataColumn
      Dim Column11 As DataColumn
      Dim Column12 As DataColumn
      Dim Column13 As DataColumn
      Dim Column14 As DataColumn
      Dim Column15 As DataColumn
      Dim Column16 As DataColumn
      Dim Column17 As DataColumn
      Dim Column18 As DataColumn
    
      Dim Row As DataRow
    
      ' Create DataTable with 18 text columns
      Column0 = New DataColumn()
      Column0.DataType = System.Type.GetType("System.String")
      Column0.ColumnName = "Tag Number"
      Column0.Caption = "Column"
      Column0.ReadOnly = True
      Column0.Unique = False
      TextFileTable.Columns.Add(Column0)
    
      Column1 = New DataColumn()
      Column1.DataType = System.Type.GetType("System.String")
      Column1.ColumnName = "Serial Number"
      Column1.Caption = "Column"
      Column1.ReadOnly = True
      Column1.Unique = False
      TextFileTable.Columns.Add(Column1)
    
      Column2 = New DataColumn()
      Column2.DataType = System.Type.GetType("System.String")
      Column2.ColumnName = "Customer"
      Column2.Caption = "Column"
      Column2.ReadOnly = True
      Column2.Unique = False
      TextFileTable.Columns.Add(Column2)
    
      Column3 = New DataColumn()
      Column3.DataType = System.Type.GetType("System.String")
      Column3.ColumnName = "Project"
      Column3.Caption = "Column"
      Column3.ReadOnly = True
      Column3.Unique = False
      TextFileTable.Columns.Add(Column3)
    
      Column4 = New DataColumn()
      Column4.DataType = System.Type.GetType("System.String")
      Column4.ColumnName = "Code"
      Column4.Caption = "Column"
      Column4.ReadOnly = True
      Column4.Unique = False
      TextFileTable.Columns.Add(Column4)
    
      Column5 = New DataColumn()
      Column5.DataType = System.Type.GetType("System.String")
      Column5.ColumnName = "Station Number"
      Column5.Caption = "Column"
      Column5.ReadOnly = True
      Column5.Unique = False
      TextFileTable.Columns.Add(Column5)
    
      Column6 = New DataColumn()
      Column6.DataType = System.Type.GetType("System.String")
      Column6.ColumnName = "Number of Pieces"
      Column6.Caption = "Column"
      Column6.ReadOnly = True
      Column6.Unique = False
      TextFileTable.Columns.Add(Column6)
    
      Column7 = New DataColumn()
      Column7.DataType = System.Type.GetType("System.String")
      Column7.ColumnName = "Defect Description"
      Column7.Caption = "Column"
      Column7.ReadOnly = True
      Column7.Unique = False
      TextFileTable.Columns.Add(Column7)
    
      Column8 = New DataColumn()
      Column8.DataType = System.Type.GetType("System.String")
      Column8.ColumnName = "Date"
      Column8.Caption = "Column"
      Column8.ReadOnly = True
      Column8.Unique = False
      TextFileTable.Columns.Add(Column8)
    
      Column9 = New DataColumn()
      Column9.DataType = System.Type.GetType("System.String")
      Column9.ColumnName = "Supervisor Initials"
      Column9.Caption = "Column"
      Column9.ReadOnly = True
      Column9.Unique = False
      TextFileTable.Columns.Add(Column9)
    
      Column10 = New DataColumn()
      Column10.DataType = System.Type.GetType("System.String")
      Column10.ColumnName = "Employee Initials"
      Column10.Caption = "Column"
      Column10.ReadOnly = True
      Column10.Unique = False
      TextFileTable.Columns.Add(Column10)
    
      Column11 = New DataColumn()
      Column11.DataType = System.Type.GetType("System.String")
      Column11.ColumnName = "Completed By"
      Column11.Caption = "Column"
      Column11.ReadOnly = True
      Column11.Unique = False
      TextFileTable.Columns.Add(Column11)
    
      Column12 = New DataColumn()
      Column12.DataType = System.Type.