How to print the entire string if the length exceeds the page

Posted on

Question :

I have to print a string that can vary in size. What I need is if this string does not fit on the page the remaining text is printed on another. I know for this I need to do something using e.HasMorePages but I do not know how. I’ve been researching but I do not find anything relevant. Take a look at some of the code that appears in the event printPage :

string textoFinal = "nnnnnnnnnnn" + cabInf + cab + sb.ToString() + soma + stringObs + final + final2;

StringFormat alinhar = new StringFormat(StringFormatFlags.NoClip);

alinhar.Alignment = StringAlignment.Near;

e.Graphics.DrawString(textoFinal, Fonte, Brushes.Black, e.MarginBounds, alinhar);

e.HasMorePages = false;

If I go to true o e.HasMorePages when printing I get a page count loop. I need something to check if the string has exceeded the page limit, and if it passed, the text that did not fit should be printed on another page.

I have this code to print:

string textoFinal;
string stringCopia;

internal void Imprimir()
    Cliente cliente = Clientes[listaClientes.SelectedIndex];

    StringBuilder sb = new StringBuilder();
    foreach (var cli in cliente.Produtos)
        sb.AppendFormat("nn{0}.....................Valor: R${1} - Data: {2}", cli.NomeProduto, cli.ValorProduto, cli.DataCompra);
    textoFinal = sb.ToString();
    stringCopia = textoFinal;
    printDocumento.PrintPage += printDocumento_PrintPage;
    Margins margem = new Margins(20, 20, 20, 20);
    printDocumento.DefaultPageSettings.Margins = margem;

In event printPage consists:

int caracteresNaPagina = 0;
int linhasPorPagina = 0;

var Fonte = new Font("Arial", 9);

e.Graphics.DrawImage(Properties.Resources.logoI, 20, 20);

StringFormat alinhar = new StringFormat(StringFormatFlags.NoClip);

alinhar.Alignment = StringAlignment.Near;

e.Graphics.MeasureString(stringCopia, Fonte, e.MarginBounds.Size, alinhar, out caracteresNaPagina, out linhasPorPagina);

e.Graphics.DrawString(stringCopia, Fonte, Brushes.Black, e.MarginBounds, alinhar);

stringCopia = stringCopia.Substring(caracteresNaPagina);

e.HasMorePages = stringCopia.Length > 0;

if (!e.HasMorePages)
    stringCopia = textoFinal;

In this way the rest of the text that did not fit the page is being written at the beginning of the same page, shuffling the texts instead of moving to another page.

It worked perfectly after removing the line printDocumento.PrintPage += printDocumento_PrintPage;
Why? Because I’m developing this in winforms and I already had this method pointing to the event. In this way, the text was written twice in the print document and shuffled.


Answer :

What you need to do and measure the text you are going to print:

int caracteresNaPagina = 0;
int linhasPorPagina = 0;

e.Graphics.MeasureString(textoFinal, font,
    e.MarginBounds.Size, StringFormat.GenericTypographic,
    out charactersOnPage, out linesPerPage);

Then prints the text and removes the characters that have already been printed to the original text. If there are still characters, put the property HasMorePages to true .

e.Graphics.DrawString(textoFinal, font, Brushes.Black,
    e.MarginBounds, StringFormat.GenericTypographic);

textoFinal= textoFinal.Substring(caracteresNaPagina);

e.HasMorePages = (textoFinal.Length > 0);

In this way the event will continue to be called until characters no longer exist to print, i.e. when HasMorePages is set to false.

Note that the text to be printed must be pre-created (outside of the print event).


The% control of% you are using to make the preview of the document to be printed calls twice the PrintPreviewDialog event. The first time when you are creating the preview and the second time if the print button is loaded (and printing is done).

Due to this and assuming that the text was created outside the PrintPage event, due to the logic to calculate the extra pages, the text will be removed until there are no remaining characters to print.

textoFinal= textoFinal.Substring(caracteresNaPagina);

e.HasMorePages = (textoFinal.Length > 0);

The problem with this, and the second time you print, when you reuse PrintPage , there are no characters to print, so the actual print will appear blank. The solution to this will then be.

  • Create text to print
  • Create a copy of the text to be printed
  • Use the copy created within the textoFinal

That is:

string textoFinal = [crie aqui o seu texto];
string copiaTextoFinal = textoFinal; // Copia do texto. Vao ser removidos caracteres a medida que a impressao ocorre.
PrintPreviewDialog dialog = new PrintPreviewDialog
        Document = new PrintDocument()

dialog.Document.PrintPage += (sender, e) =>
        int charactersOnPage;
        int linesPerPage;

        var fonte = new Font("Arial", 18);

        e.Graphics.MeasureString(copiaTextoFinal, fonte,
                e.MarginBounds.Size, StringFormat.GenericTypographic,
                out charactersOnPage, out linesPerPage);

        e.Graphics.DrawString(copiaTextoFinal, fonte, Brushes.Black, e.MarginBounds, StringFormat.GenericTypographic);

        copiaTextoFinal = copiaTextoFinal.Substring(charactersOnPage);

        // Verifica se ainda existem caracteres para imprimir. Se não, marca a 
        // propriedade como falsa.
        e.HasMorePages = copiaTextoFinal.Length > 0;

        // Se não houverem mais paginas a imprimir, volta a copiar o texto original
        // para a variável de copia. Assim, da próxima vez que o evento for chamado, 
        // tem o texto completo, pronto a imprimir.
        if (!e.HasMorePages)
            copiaTextoFinal = textoFinal;



Leave a Reply

Your email address will not be published. Required fields are marked *