Search code examples
c#datagridviewprintdocument

Printing DatagridView Data on Multiple page using printDOcumnet C#


So, i am trying to print datagridview data, but the problem is after the page heights crosses the limit,it does't move to next page to print the remaining data. I tried adding condition by counting the items but no success. Kindly tell me whats wrong with my code. And if i add condition of item no. the page keep increasing but all the pages have the same data.

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

        Image image = Resources.grocery;
        float pageWidth = e.PageSettings.PrintableArea.Width;
        float pageHeight = e.PageSettings.PrintableArea.Height;

        Font font = new Font("Arial", 12, FontStyle.Regular);
        float fontHeight = font.GetHeight();
        int startX = 40;
        int startY = 30;
        int offsetY = 30;

            e.Graphics.DrawImage(image, 0, 0, 250, 250);
            e.Graphics.DrawString("Invoice ID   : GO-" + saaale, font, Brushes.Black, new Point(570, offsetY));
            offsetY += (int)fontHeight;

            e.Graphics.DrawString("Invoice Date :" + theDate, font, Brushes.Black, new Point(570, offsetY+40));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("Due Date     : " + a, font, Brushes.Black, new Point(570, offsetY+80));
            offsetY += (int)fontHeight;


            e.Graphics.DrawString("Client Name: " + this.comboBox1.GetItemText(this.comboBox1.SelectedItem), font, Brushes.Black, new Point(570, offsetY + 120));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(0, 290));
            offsetY += (int)fontHeight;

           e.Graphics.DrawString("S.No", font, Brushes.Black, new Point(10, offsetY + 280));
           offsetY += (int)fontHeight;
            e.Graphics.DrawString("Product Name", font, Brushes.Black, new Point(130, offsetY + 280));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("Quantity", font, Brushes.Black, new Point(440, offsetY + 280));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("Sale Price", font, Brushes.Black, new Point(580, offsetY + 280));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("Amount", font, Brushes.Black, new Point(750, offsetY + 280));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(0, 330));
            offsetY += (int)fontHeight;
            int j = 340; //370
            int count111 = 0;

            for (int i = 0; i < dataGridView1.RowCount - 1; i++)
            {
                if (offsetY >= pageHeight)
                {
                    e.HasMorePages = true;
                    offsetY = 0;
                    return;
                }
                else
                {
                    e.Graphics.DrawString(dataGridView1.Rows[i].Cells[0].Value.ToString(), font, Brushes.Black, new Point(10, offsetY + j));
                    offsetY += (int)fontHeight;
                    e.Graphics.DrawString(dataGridView1.Rows[i].Cells[1].Value.ToString(), font, Brushes.Black, new Point(140, offsetY + j));
                    offsetY += (int)fontHeight;
                    e.Graphics.DrawString(dataGridView1.Rows[i].Cells[2].Value.ToString(), font, Brushes.Black, new Point(450, offsetY + j));
                    offsetY += (int)fontHeight;
                    e.Graphics.DrawString(dataGridView1.Rows[i].Cells[3].Value.ToString(), font, Brushes.Black, new Point(590, offsetY + j));
                    offsetY += (int)fontHeight;
                    e.Graphics.DrawString(dataGridView1.Rows[i].Cells[4].Value.ToString(), font, Brushes.Black, new Point(760, offsetY + j));
                    j = j + 30;
                    //count111++;
                    e.HasMorePages = false;

                }


            }
            e.Graphics.DrawString("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(0, offsetY + j - offsetY));
            offsetY += (int)fontHeight;
            e.Graphics.DrawString("Total Amount : Rs " + sum, new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(550, offsetY + j + offsetY));
            offsetY += (int)fontHeight;
            // e.Graphics.DrawString("Thank You For Your Buisness ", new Font("Arial", 12, FontStyle.Bold), Brushes.DarkBlue, new Point(280, j + 400));




        //multipage trial




        //end
        //Bitmap bm = new Bitmap(this.dataGridView1.Width, this.dataGridView1.Height);

        //dataGridView1.DrawToBitmap(bm, new Rectangle(0, 0, this.dataGridView1.Width, this.dataGridView1.Height));
        //e.Graphics.DrawImage(bm, 0, 350);
    }

Solution

  • Unfortunately, I do not think the DataGridView supports a PrintDocument. Therefore, you will have to manage looping through the grid yourself. The posted code appears to making things more complicated than it has to be. The main issue is that you are checking for more pages INSIDE the loop of the grids rows. This will not work.

    Currently the PrintPage method appears to be looping through the grid, however, as you noticed in your question… it ALWAYS starts at the begging of the rows in the grid for each page. Using the for loops i index as an index into the current grid row being printed won’t work this way. It certainly explains why it always starts at the beginning, but it also most likely never ends and is an endless loop.

    Because of this, it is clear that you are going to have to keep a GLOBAL index variable that holds the row index of the current row to print. This way, each time you enter the PrintPage method, you can use this global variable index to keep track of the current row to print.

    This suggest there are TWO (2) conditions that need to be meet that would signal a new page is needed… i.e.… You have more rows to print AND you have reached the bottom of the print page.

    The pseudo code below is a simple guide to help with this issue.

    First, make a global variable to keep track of which row currently needs to be printed. It may be beneficial to have a global variable that keeps track of WHERE the current (vertical) print row position is in relation to the page height.

    int CurrentDGVRowIndex = 0;
    currentPrint_Vertical_Value = 30;
    

    Then in the PrintPage method, we can use these variables to check to see if we have reached the end of the printed rows in the grid, in addition, we can use them to see if there are more rows to print and we have reached the bottom of the page.

    private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) {
      float pageHeight = e.PageSettings.PrintableArea.Height;
      currentPrint_Vertical_Value = 30;
      PrintHeader(e);
    
     // keep printing until either there are no more rows to print OR we reach the end of the page
      while ((currentPrint_Vertical_Value < pageHeight) &&
             (CurrentDGVRowIndex < dataGridView1.Rows.Count - 1)) {
       // print a single row
        e.Graphics.DrawString(dataGridView1.Rows[CurrentDGVRowIndex].Cells[0].Value.ToString(), font, Brushes.Black, new Point(10, currentPrint_Vertical_Value));
        e.Graphics.DrawString(dataGridView1.Rows[CurrentDGVRowIndex].Cells[1].Value.ToString(), font, Brushes.Black, new Point(140, currentPrint_Vertical_Value));
        e.Graphics.DrawString(dataGridView1.Rows[CurrentDGVRowIndex].Cells[2].Value.ToString(), font, Brushes.Black, new Point(450, currentPrint_Vertical_Value));
        e.Graphics.DrawString(dataGridView1.Rows[CurrentDGVRowIndex].Cells[3].Value.ToString(), font, Brushes.Black, new Point(590, currentPrint_Vertical_Value));
        e.Graphics.DrawString(dataGridView1.Rows[CurrentDGVRowIndex].Cells[4].Value.ToString(), font, Brushes.Black, new Point(760, currentPrint_Vertical_Value));
        currentPrint_Vertical_Value = currentPrint_Vertical_Value + 30;
       // increment to the next grid row
        CurrentDGVRowIndex++;
      }
    

    Once we exit this while loop we know one (or both) conditions have been meet.

    1) We ran out of rows to print

    2) We have reached the bottom of the page.

    Given this, we simply check to see if we need to print more pages. Check the row index of the last printed row. If it equals the total rows in the grid then we are done. If not, then we know we have reached the end of the printable area and need to call the PrintPage method again.

      if (CurrentDGVRowIndex == dataGridView1.RowCount - 1) {
        // no more rows in the grid to print – print summary and exit/
        PrintFooter(e);
        e.HasMorePages = false;
      }
      else {
        // there are more rows to print therefore we have more pages
        e.HasMorePages = true;
      }
    }
    

    I hope this helps.