Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Print more than one page in C#

Tags:

c#

.net

before I am committed to the insane asylum I thought I'd give this a try: How do you write the code to print more than one page?

I have been trying all the examples I could find on stackoverflow (and other places) but am not having any success! It really is making me crazier than I already am! All the other examples I found were dealing with issues that didn't relate to what I am trying to do. The example I am trying to fix would print 0 - 100 integers on two pages, i.e., 0-80 on page 1 and 81-100 on page 2. Despite all the techniques suggested all I can get is one page that is overwritten with page 2's data on top.

e.HasMorePages = true; is supposed to start the next page but is not working.

I created a very simple Winform program for this and here is the code. Any ideas would be greatly appreciated:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace PrintMultiplePages_v2
{
    public partial class Form1 : Form
    {
        ArrayList al = new ArrayList();
        private int fontcount;
        private int fontposition = 1;
        private float ypos;
        private string textToPrint;
        private PrintPreviewDialog previewDlg = null;
        private PrintDocument pd = null;

        private int counter = 0;
        private int amtperpage = 80; // The amount of lines per page


        public Form1()
        {
            InitializeComponent();

            for (int i = 0; i < 100; i++)
                al.Add(i.ToString());
        }

        private void buttonPrint_Click(object sender, EventArgs e)
    {
        PrintDocument pd = new PrintDocument();

        pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
        pd.Print();
    }

    private void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        float leftMargin = 70.0f;
        float topMargin = 20.0f;
        float lineInc = 20.0f;

        Font printFontArial10 = new Font("Arial", 10, FontStyle.Regular);

        Graphics g = e.Graphics;

        double pageCount = (double)al.Count / (double)amtperpage;
        int pageRequired = Convert.ToInt32(Math.Ceiling(pageCount));

        counter = 0;

        for (int page = 1; page <= pageRequired; page++)
        {
            int counterMax = amtperpage * page;
            if (counterMax > al.Count)
                counterMax = al.Count;

            for (int x = counter; x < counterMax; x++)
            {
                textToPrint = al[x].ToString() + " - test";
                e.Graphics.DrawString(textToPrint, printFontArial10, Brushes.Black, leftMargin, topMargin + lineInc);

                lineInc += 12;
                counter++;
            }

            if (counter == counterMax)
            {
                if (counter != al.Count)
                {
                    e.HasMorePages = true;
                    counter++;
                    lineInc = 20.0f;
                }
            }
            else
                e.HasMorePages = false;
        }
    }
}

}

The corrected code is:

private int page = 0;

    private void buttonPrint_Click(object sender, EventArgs e)
    {
        page = 0;

        PrintDocument pd = new PrintDocument();
        pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
        pd.Print();
    }

    private void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        float leftMargin = 70.0f;
        float topMargin = 20.0f;
        float lineInc = 20.0f;

        Font printFontArial10 = new Font("Arial", 10, FontStyle.Regular);

        Graphics g = e.Graphics;

        int stop = counter + amtperpage;

        if (stop > al.Count)
            stop = al.Count;

        while (counter < stop)
        {
            textToPrint = al[counter].ToString() + " - test";
            e.Graphics.DrawString(textToPrint, printFontArial10, Brushes.Black, leftMargin, topMargin + lineInc);

            lineInc += 12;
            counter++;
        }

        page++;
        e.HasMorePages = counter < al.Count;
    }
like image 960
Bob T Avatar asked Jan 17 '14 16:01

Bob T


People also ask

How do I Print on multiple pages?

Choose File > Print. From the Page Scaling pop-up menu, select Multiple Pages Per Sheet.

How do I Print multiple pages on one page and front?

Click File > Print. In the Printer list, select the printer you want to use. In Settings, choose Print on Both Sides – Flip sheets on long edge or Print on Both Sides – Flip sheets on long edge.


2 Answers

The PrintPage event is supposed to be called repeatedly until e.HasMorePages becomes false. It's up to that event to print one page at a time. You have it only being called once and are feeding it both pages in a single for loop. In other words, that for loop is killing you. Logically, you should be tracking which page you are currently on (outside of pd_PrintPage) and incrementing the counter as it continues. You can tell you have this wrong because counter is being set to zero in pd_PrintPage whereas is should be set to zero in buttonPrint_Click.

So pull "int page" out of pd_PrintPage and have the loop be something like

int stop = counter + amtperpage;
if (stop >= al.Count)
    stop = al.Count - 1; // - 1 to prevent index out of range error.

while (counter <= stop)
{
    textToPrint = al[counter].ToString() + " - test";
    e.Graphics.DrawString(textToPrint, printFontArial10, Brushes.Black, leftMargin, topMargin + lineInc);

    lineInc += 12;
    counter++;
}

page++;
e.HasMorePages = counter < al.Count - 1; // pesky zero-based array issue again.
like image 101
Jacob Proffitt Avatar answered Sep 20 '22 12:09

Jacob Proffitt


Try using a FlowDocument and IDocumentPaginator as shown below :

public void PrintDocument(MemoryStream outputStream)
{
    FlowDocument fd = new FlowDocument();
    TextRange tr = new TextRange(fd.ContentStart, fd.ContentEnd);
    tr.Load(outputStream, System.Windows.DataFormats.Rtf);

    PrintDialog printDlg = new PrintDialog();
    fd.PageHeight = printDlg.PrintableAreaHeight;
    fd.PageWidth = printDlg.PrintableAreaWidth;
    fd.PagePadding = new Thickness(25);

    fd.ColumnGap = 0;
    fd.ColumnWidth = (fd.PageWidth -
                           fd.ColumnGap -
                           fd.PagePadding.Left -
                           fd.PagePadding.Right);

    if (printDlg.ShowDialog() == true)
    {              
        IDocumentPaginatorSource idpSource = fd;
        idpSource.DocumentPaginator.PageSize = new Size { Height = 600, Width = 600 };
        printDlg.PrintDocument(idpSource.DocumentPaginator, "Printing Document");
    }
}
like image 31
Praveena Avatar answered Sep 22 '22 12:09

Praveena