Search code examples
c#printingdatagridviewdatatableprintdocument

Use PrintDocument to print each row in DataTable to seperate page


I have an application with a DataTable and I need to print each row in the DataTable to a separate page and I'm having a hell of a time trying to get it to work. I've found plenty of posts related to printing more than one page and printing DataGridViews but I can't find anything about printing each row in a DataTable to separate pages.

Anyways, here is what I have put together so far and it doesn't quite work.

private void btnPrint_Click(object sender, EventArgs e)
{
    printTag.DefaultPageSettings.Landscape = true;
    PrintPreviewDialog preview = new PrintPreviewDialog();
    preview.Document = printTag;
    preview.Show();
}

private void printTag_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
    PrintRow = 0;
    //Here I set my Fonts, String Formats and Pen Styles

    int maxRows = _dtTags.Rows.Count;
    for (int lines = 0; lines < maxRows; ++lines)
    {
        PrintRow++;
        if (PrintRow >= _dtTags.Rows.Count)
        {
            e.HasMorePages = PrintRow < _dtTags.Rows.Count;
            return; //Done Printing
        }

        var row = _dtTags.Rows[PrintRow];

        //Pass data from current Row of DataTable to variables which are used to populate the e.Graphic
        jobNum = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Job");
        machInfo = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Job Desc");
        jobNote = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Job Note");
        color = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Color");
        parts = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Parts");
        empName = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Employee");

        //Here my e.Graphic is created, located and filled out

    }
}

So, here is what it does with the above code:

  1. If my table has only has one row the print preview comes out blank.
  2. If my table has more than one row, the last row isn't printed.
  3. Each row in the table (with the exception of the last and if there is only one) prints on the same page.

So basically my preview looks like I fed the same paper into the printer multiple times and printed over it.

Any help or advice on getting this to work would be immensely appreciated.


Solution

  • It seems you misunderstood how the PrintPage event works. e.HasMorePages in the PrintPage event indicates whether an additional page should be printed, and so whether the PrintPage event should be raised again.

    • The logic to set e.HasMorePages is wrong as @rleffler pointed out.

      PrintRow++;
      if (PrintRow >= _dtTags.Rows.Count)
      {
          e.HasMorePages = PrintRow < _dtTags.Rows.Count;
          return; //Done Printing
      }
      

      e.HasMorePages can never be set to true with your logic, and therefore will never print more than one page.

    • PrintRow number must be reseted before printing, not inside the PrintPage event.

    • No need to iterate DGV rows in PrintPage event, just get the current row corresponding to its index (PrintRow value -1 in this case).

    private void btnPrint_Click(object sender, EventArgs e)
    {
        printTag.DefaultPageSettings.Landscape = true;
        PrintPreviewDialog preview = new PrintPreviewDialog();
    
        // Reset before printing
        PrintRow = 0;
    
        preview.Document = printTag;
        preview.Show();
    }
    
    
    private void printTag_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
        //Here I set my Fonts, String Formats and Pen Styles
    
        int maxRows = _dtTags.Rows.Count;
        if (maxRows == 0) {
            return;
        }
    
        PrintRow++;
        e.HasMorePages = PrintRow < _dtTags.Rows.Count;
    
        int lines = PrintRow - 1;
        var row = _dtTags.Rows(lines);
    
        //Pass data from current Row of DataTable to variables which are used to populate the e.Graphic
        jobNum = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Job");
        machInfo = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Job Desc");
        jobNote = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Job Note");
        color = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Color");
        parts = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Parts");
        empName = _dsTags.Tables["Paint Tags"].Rows[lines].Field<string>("Employee");
    
        //Here my e.Graphic is created, located and filled out
    
    
    
    }