Question

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.

Was it helpful?

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



}

OTHER TIPS

The problem here is partly your logic.

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

This is the only place that you are setting e.HasMorePages. If PrintRow is greater than or equal to the row count of _dtTags then your statement to set e.HasMorePages will always be false because it then asks if PrintRow is less than that row count. e.HasMorePages when set to true and returned will cause the handler to be called again. If you want more pages then you need to set it to true somewhere, and false when you want to stop printing. Your main problem is that e.HasMorePages can never be set to true with your logic, and therefore will never print more than one page.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top