.NET - Imprimindo o conteúdo de um ListBox

 


 No artigo de hoje vou mostrar como podemos imprimir o conteúdo de um controle ListBox usando a linguagem VB .NET e também C#.

Hoje vamos preencher um controle ListBox a partir de uma base de dados e imprimir o seu conteúdo usando o objeto PrintDocument.

Para simplificar vou usar o banco de dados Northwind.mdb e exibir o nome do produto encontrado na tabela Products.

A seguir usando os controles PrintDocument e PrintDialog irei imprimir os nomes dos produtos.

Já sabemos que a classe PrintDocument é o coração do processo de impressão no Visual Basic e ao usá-la em seu programa será criada uma instância desta classe com os eventos que serão usados para a impressão.

O objeto PrintDocument dispara quatro eventos chaves básicos:

  1. BeginPrint - Este evento é lançado quanto a impressão vai começar; neste momento o programa pode iniciar estrutura de dados, carregar dados, efetuar a conexão com a fonte de dados e realizar qualquer outra operação necessária antes de iniciar a impressão;
  2. QueryPageSettings - Este evento é acionado antes do programa imprimir uma página. Neste momento o programa pode modificar os dados do documento como alterar as margens da página, etc.;
  3. PrintPage - Este evento ocorre para gerar a página. O programa necessita capturar este evento e usar o objeto Graphics fornecido pelos parâmetros do manipulador de eventos para gerar a saída do relatório , ao final o manipulador de eventos deverá definir o valor de e.HashMorePages para True ou False e devolver para o objeto PrintDocument informando se existem mais páginas a serem geradas;
  4. EndPrint - Este evento será lançado ao término da impressão. Ele pode ser capturado para liberar os recursos usados, fechar conexões, etc.;

Depois que você criou um objeto PrintDocument e definiu os manipuladores de eventos você pode fazer 3 coisas com ele:

  1. Chamar o método Print do objeto para enviar o documento de imediato para a impressão padrão selecionada;
  2. Definir um controle PrintPreviewDialog e atribuir a sua propriedade Document um objeto PrintDocument e então chamar o método ShowDialog do controle. O controle PrintPreviewDialog exibe a janela para visualizar a impressão e usar o objeto PrintDocument para gerar a saída que será exibida. O controle possui um botão para enviar o documento para a impressora;

NotaO controle PrintPreviewControl exibe uma janela de visualização da impressão com a diferença que ele fica no seu formulário e não apresenta os mesmos botões  do PrintPreviewDialog mas possui métodos que permitem simular o mesmo comportamento.

  1. Definir um controle PrintDialog e atribuir a sua propriedade Document um objeto PrintDocument e então chamar o método ShowDialog do controle. O usuário pode selecionar a impressora e definir suas propriedades , quando o usuário clicar na opção para imprimir o objeto PrintDocument envia o documento para impressora;

Recursos usados

Criando o projeto no VS Community

Abra o VS Community 2015  e clique em New Project;

A seguir selecione Other Project Types -> Blank Solutin

Informe o nome Imprimindo_ListBox e clique no botão OK;

A seguir no menu File clique em Add -> New Project;

Selecione o template Visual Basic -> Windows -> Windows Forms Application;

Informe o nome Imprimindo_ListBox.VBNET e clique no botão OK;

Agora vamos definir no formulário form1.vb a declaração do namespace:

Imports System.Data.OleDb
Imports
System.IO
Imports
System.Drawing.Printing

Defina também no formulário as seguintes variáveis :

Dim conexao As New OleDbConnection()
Dim dadosListBox As StringReader

A primeira cria um objeto do tipo OledbConnection para realizar a conexão com o banco de dados Northwind.mdb

A segunda define um objeto do tipo StringReader que irá receber os dados do ListBox que desejamos imprimir.

A seguir a partir da ToolBox inclua no formulário form1.vb os seguintes controles:

Disponha os controles no formulário conforme o leiaute da figura abaixo:

1- Preenchendo o ListBox a partir de um banco de dados

No evento Click do botão de comando - Carregar Dados - inclua o código a seguir:

    Private Sub btnCarregarDados_Click(sender As Object, e As EventArgs) Handles btnCarregarDados.Click
        conexao.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\dados\Northwind.mdb"
        carregaListBox(lbDados, "Select ProductName from products")
    End Sub
private void btnCarregarDados_Click(object sender, EventArgs e)
{
     conexao.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\dados\\Northwind.mdb";
     carregaListBox(lbDados, "Select ProductName from products");
}

Neste código após definir a string de conexão, estamos chamando o método carregaListBox() que passa o controle e o comando SQL para retornar os dados da tabela Products.

A seguir temos o código do método carregaListBox() :

  Private Sub carregaListBox(ByVal lst As ListBox, ByVal query As String)
        lst.Items.Clear()
        ' abre a conexao
        conexao.Open()
        ' cria um comando select.
        Dim cmd As New OleDb.OleDbCommand(query, conexao)
        ' executa a consulta
        Dim db_reader As OleDbDataReader = cmd.ExecuteReader(CommandBehavior.Default)
        ' exibe os resultados
        Dim texto As String
        Dim i As Integer
        Do While db_reader.Read
            texto = db_reader.Item(0).ToString
            For i = 1 To db_reader.FieldCount - 1
                texto &= vbTab & db_reader.Item(i).ToString
            Next i
            lst.Items.Add(texto)
        Loop
        ' fecha a conexao
        conexao.Close()
    End Sub
private void carregaListBox(ListBox lst, string query)
{
	lst.Items.Clear();
	// abre a conexao
	conexao.Open();
	// cria um comando select.
	OleDb.OleDbCommand cmd = new OleDb.OleDbCommand(query, conexao);
	// executa a consulta
	OleDbDataReader db_reader = cmd.ExecuteReader(CommandBehavior.Default);
	// exibe os resultados
	string texto = null;
	int i = 0;
	while (db_reader.Read) {
		texto = db_reader.Item(0).ToString;
		for (i = 1; i <= db_reader.FieldCount - 1; i++) {
			texto += Constants.vbTab + db_reader.Item(i).ToString;
		}
		lst.Items.Add(texto);
	}
	// fecha a conexao
	conexao.Close();
}

Nessa abordagem estamos usando um DataReader para acessar os dados da tabela Products; a seguir percorremos o datareader e obtemos a informação armazenando-a na variável texto que é incluída no ListBox.

Executando o projeto e acionando este botão de comando do formulário teremos o seguinte resultado:

2- Imprimindo o conteúdo do ListBox

A lógica para impressão é usar o evento PrintPage do objeto PrintDocument definindo nele o código para imprimir o conteúdo do ListBox.

No evento Click do botão de comando  - Imprimir ListBox - temos o código abaixo:

  Private Sub btnImprimirListbox_Click(sender As Object, e As EventArgs) Handles btnImprimirListbox.Click
        printDialog1.Document = PrintDocument1
        Dim strTexto As String = ""
        For Each x In lbDados.Items
            strTexto = (strTexto & x.ToString()) + vbLf
        Next
        dadosListBox = New StringReader(strTexto)
        If printDialog1.ShowDialog() = DialogResult.OK Then
            Me.printDocument1.Print()
        End If
    End Sub
private void btnImprimirListbox_Click(object sender, EventArgs e)
{
	printDialog1.Document = PrintDocument1;
	string strTexto = "";

	foreach (void x_loopVariable in lbDados.Items)
             {
		x = x_loopVariable;
		strTexto = (strTexto + x.ToString()) + Constants.vbLf;
	}

	dadosListBox = new StringReader(strTexto);

	if (printDialog1.ShowDialog() == DialogResult.OK) {
		this.printDocument1.Print();
	}
}

Neste código percorremos o ListBox e obtemos os dados armazenando cada linha na variável strTexto; a seguir usando a classe StringReader, que  Implementa um TextReader lido de uma cadeia de caracteres, armazenamos todas as informações do conteúdo do ListBox na variável dadosListBox.

A classe StringReader permite ler de forma síncrona ou assíncrona uma cadeia de caracteres. Você pode ler um caractere em vez com Read ou o método de ReadAsync , uma linha por vez usando ReadLine ou o método de ReadLineAsync e em uma cadeia de caracteres inteira usando ReadToEnd ou o método de ReadToEndAsync .

Após isso apresentamos a caixa de diálogo para impressão e se o usuário confirmar chamamos o método Print do objeto PrintDocument1.

Agora tudo que precisamos é definir o código no evento PrintPage conforme a seguir:

 Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage

        'define objetos usados na impressão
        Dim LinhasPorPagina As Single = 0
        Dim yPosicao As Single = 0
        Dim contador As Integer = 0
        Dim MargemEsquerda As Single = e.MarginBounds.Left
        Dim MargemTopo As Single = e.MarginBounds.Top
        Dim linha As String = Nothing
        Dim FonteImpressao As Font = lbDados.Font
        ' Calcula o numero de linhas por pagina
        LinhasPorPagina = e.MarginBounds.Height / FonteImpressao.GetHeight(e.Graphics)
        ' Itera sobre o arquivo imprimindo cada linha
        While contador < LinhasPorPagina
            linha = dadosListBox.ReadLine()
            If linha Is Nothing Then
                Exit While
            End If
            yPosicao = MargemTopo + contador * FonteImpressao.GetHeight(e.Graphics)
            e.Graphics.DrawString(linha, FonteImpressao, Brushes.Black, MargemEsquerda, yPosicao, New StringFormat())
            contador += 1
        End While
        ' Se existir mais linhas então imprime na outra pagina
        If (linha IsNot Nothing) Then
            e.HasMorePages = True
        Else
            e.HasMorePages = False
        End If
    End Sub
Private void PrintDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
	//define objetos usados na impressão
	float LinhasPorPagina = 0;
	float yPosicao = 0;
	int contador = 0;
	float MargemEsquerda = e.MarginBounds.Left;
	float MargemTopo = e.MarginBounds.Top;
	string linha = null;
	Font FonteImpressao = lbDados.Font;

	// Calcula o numero de linhas por pagina
	LinhasPorPagina = e.MarginBounds.Height / FonteImpressao.GetHeight(e.Graphics);

	// Itera sobre o arquivo imprimindo cada linha
	while (contador < LinhasPorPagina) {
		linha = dadosListBox.ReadLine();
		if (linha == null)
                         {
		      break; 		
                          }
		yPosicao = MargemTopo + contador * FonteImpressao.GetHeight(e.Graphics);
		e.Graphics.DrawString(linha, FonteImpressao, Brushes.Black, MargemEsquerda, yPosicao, new StringFormat());
		contador += 1;
	}

	// Se existir mais linhas então imprime na outra pagina
	if ((linha != null)) {
		e.HasMorePages = true;
	} else {
		e.HasMorePages = false;
	}
}

Neste código definimos os objetos usados na impressão, definimos o número de linha por página e fazemos a iteração na variável dadosListBox, enquanto o contador for menor que o número de linhas por página, onde lemos e imprimimos cada linha.

Ao final verificamos se ainda existem dados a serem impressos e em caso afirmativo o processo se repete até ao final da impressão.

Executando o projeto novamente temos o seguinte resultado para uma impressão para um arquivo PDF:

Dessa forma fizemos uma abordagem bem simples usando os recursos dos objetos PrintDocument e PrintDialog para imprimir o conteúdo do controle ListBox.

Pegue o projeto completo aqui :  Imprimindo_ListBox.zip

(Disse Jesus) - Em verdade, em verdade vos digo que vem a hora, e agora é, em que os mortos ouvirão a voz do Filho de Deus, e os que a ouvirem viverão.
João 5:25

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

     Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti