vb .pdf impresão.pdf

7

Click here to load reader

Upload: cristiano-ribeiro-lessa

Post on 25-Dec-2015

57 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 1/7

VB .NET - Impressão usando oSystem.Drawing.Printing

Uma das grandes lacunas existentes no VB é impressão. Com a versão do VB5 e VB6 tínhamosas seguintes opções para gerar relatórios e imprimir documentos:

Crystal Reports - fácil de usar mas acarretava o acréscimo de mais dll´s no seu projeto ;sem contar os problemas de registro de componentes que a ocx do crystal causava.Data Report - indicado apenas para relatórios mais simples. Sempre apresentou problemase nunca convenceu ninguém do motivo a que veio ser incluída no VB.O objeto Printer - permitia uma certa liberdade e independência para o desenvolvedor masexigia codificação extra o que para relatórios mais complexos exigia malabarismos. Tudoisto sem falar em funcionalidades básicas como a visualização da impressão que exigiauma implementação a parte ou a utilização de controle de terceiros.

A respeito deste panorama sombrio com relação a impressão no VB eu tenho duas notícias: umaboa e uma ruim. A ruim é que o VB .NET não resolveu todos os problemas existentes , e a boa éque ficou muito mais fácil imprimir documentos e gerar relatórios no VB .NET.

Neste artigo vou procurar mostrar como podemos usar o namespace System.Drawing.Printing , osucessor do objeto Printer do VB , para criar relatórios usando código VB.NET.

Para começar vamos dar uma olhada nas principais classes para impressão .

PrintDocument :

é usada para enviar a saida para uma impressora.Você instancia um PrintDocument , define algumas propriedades descrevendo oque deseja imprimir e chama o método Print.Esta classe dispara o evento PrintPage para cada página a ser impressa.Você geralmente inclui o seu código para impressão para um gerenciador deevento para este evento.

PrinterSettings : Fornece informações sobre como um documento será impresso.PageSettings : Fornece informações sobre como uma página será impressa.PrintPageEventArgs : Dados para o evento PrintPage de PrintDocument.PrintEventArgs : Dados para os eventos BeginPrint e EndPrint em um PrintDocument. Permitecancelar o trabalho de impressão.PrintPreviewControl : Um controle que exibe um PrintDocument. Permite criar um diálogo devisualizar a impressão.PrintPreviewDialog : Diálogo que exibe um PrintDocument usando o PrintPreviewControl.PageSetupDialog : Diálogo das propriedades da página.PrintController : Controla um PrintDocument que é impresso. Temos dois PrintController

DefaultPrintController - renderiza para a impressoraPreviewPrintController - renderiza para o PrintPreviewControl.

Basicamente a lógica para uma impressão até feita usando os eventos de PrintDocument .Quando o método PrintDocument.Print() é chamado temos a seguinte sequência de eventos:

1. BeginPrint2. PrintPage3. EndPrint

O tipo de argumentos do evento PrintPage possui a propriedade HasMorePages. Se ela for

Page 2: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 2/7

definida como True quando o evento retornar , PrintDocument define uma nova página e levantao evento PrintPage novamente. Desta forma a lógica do seu código para impressão no eventoPrintPage deverá ser basicamente a seguinte :

Imprimir o conteúdo da página usando a informação nos argumentos do evento. Elescontém Graphics para a impressora, PageSettings para a página , as margens da página eo tamanho das margens.Determine se existem mais páginas a serem impressas.Se existir mais páginas defina HasMorePages como True caso contrário defina como False

Da teoria para a prática

Vou mostrar como podemos criar relatórios via código usando o System.Drawing.Printing usandocomo exemplo a criação de um relatório que exibe os dados contidos em uma tabela de umbanco de dados. Iremos portanto realizar as seguintes tarefas:

Acessar e abrir um banco de dadosExibir os dados de uma tabela deste banco de dadosTrabalhar com fontes de formatos diferentes no relatórioTrabalhar com cabeçalhos , rodapés e números de páginaTrabalhar com imagens no relatórioVisualizar o relatório de dadosImprimir o relatório na impressora

Para não termos muito trabalho vou escolher uma tabela de um banco de dados já existente. Oescolhido é o já famoso saco de pancadas Northwind.mdb . Iremos acessar a tabela produtosdeste banco de dados e exibir em um relatório os campos : Código do Produto, Nome doProduto , Preço Unitário

A estrutura da tabela produtos do banco de dados Northwind.mdb é a seguinte :

O layout do relatório deverá ser algo parecido com :

O acesso aos dados

Como iremos montar um relatório que vai exibir os dados da tabela Pedidos teremos que criaruma conexão e extrair os dados que desejemos exibir via instrução SQL.

Page 3: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 3/7

Como iremos acessar uma base de dados Access irei usar o namespace System.Data.OleDb e oprovedor "Provider=Microsoft.Jet.OLEDB.4.0;".

Vamos utilizar um objeto DataReader para obter as informações da tabela via objetoOleDbCommand.

Conforme já mostrei no artigo - ADO.NET - Uma visão geral I : Objetos Connection , Command eDataReader - o código para conexão com uma base de dados Access em c:\teste\northwind.mdbusando um DataReader pode ser expresso assim : Dim conn As New OleDbConnection()conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\teste\northwind.mdb"Dim cmd As OleDbCommand = conn.CreateCommand

cmd.CommandText = "Select CódigoDoProduto,NomeDoProduto, PreçoUnitário from Produtos"

conn.Open()Dim leitor As OleDbDataReader = cmd.ExecuteReader()

Try While leitor.Read() 'código para visualizar o relatório End While leitor.Close() conn.Close()

Catch erro As Exception MsgBox("Erro " & vbCrLf & erro.ToString, MsgBoxStyle.Critical, "Erro")End TryEnd Sub Apenas para recordar temos que :

O objeto OleDbCommand representa uma instrução SQL que será executada para extrair os dados da tabelaPedidosO método ExecuteReader() retorna um conjunto de registros de somente leituraO objeto OleDbDataReader precisa de uma conexão ativa para ser criado (podemos compará-lo ao antigoRecordset de somente leitura)Você precisa fechar o objeto OleDbDataReader para poder liberar a conexão que ele esta usando.O objeto DataReader é alimentado via método ExecuteReader do objeto Command.Para percorrer todos os registros que foram extraídos usamos o método Read()

No interior loop While/End While iremos é que vamos colocar o código que permite avisualização da impressão pois e no interior do loop que estaremos lendo os registros da tabelaProdutos. Devemos fazer o seguinte:

Criar um objeto PrintDocumentEstabelecer uma relação entre o evento PrintPage e o relatório a ser gerado.

Nota: Para saber mais leia o artigo : Impressão e Visualização. O que há de novo ?

O código deverá ficar assim :

While drProdutos.Read 'cria um novo documento para impressão Dim pd As PrintDocument = New PrintDocument() 'relaciona o objeto pd ao procedimento rptProdutos AddHandler pd.PrintPage, AddressOf Me.rptProdutos 'cria uma nova instância do objeto PrintPreviewDialog() objPrintPreview = New PrintPreviewDialog() 'define algumas propriedades do obejto With objPrintPreview 'indica qual o documento vai ser visualizado

Page 4: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 4/7

.Document = pd .WindowState = FormWindowState.Maximized .PrintPreviewControl.Zoom = 1 'maxima a visualização .Text = "Catálogo de Produtos" 'exibe a janela de visualização para o usuário .ShowDialog() End With End While

A única novidade seria o código que relaciona o objeto PrintDocument com o evento rptProdutos:

AddHandler pd.PrintPage, AddressOf Me.rptProdutos

Aqui estamos usando a declaração AddHandler e o operador AddressOf .

Neste caso estou associando o procedimento rptProdutos ao evento pd.PrintPage , ou seja , oprocedimento rptProdutos irá os dados enviados pelo objeto DataReader e gerará o relatórioformatado para visualização/impressão.

Agora só falta definir o código do procedimento rptProdutos. Embora seja um pouco trabalhosoo código é simples. Vamos a ele:

1- Primeiro vamos definir o procedimento que irá receber os dados do objeto DataReader suadeclaração é a seguinte:

Private Sub rptProdutos(ByVal sender As Object, ByVal Relatorio AsSystem.Drawing.Printing.PrintPageEventArgs)

O procedimento possui um argumento do tipo PrintPageEventArgs chamado de Relatorio queiremos usar para definir a formatação do relatório através de cabeçalho, rodapé , título , fontes ,linhas , imagens , texto, etc.

Antes de prosseguir vamos assumir que: Estamos imprimindo na impressora padrão. Agoravamos definir os itens que irão formatar o nosso relatório:

- Margens : vamos assumir as margens definidas pela impressora padrão para isto vamos usara propriedade MarginBounds do objeto

Dim margemEsq As Single = Relatorio.MarginBounds.LeftDim margemSup As Single = Relatorio.MarginBounds.TopDim margemDir As Single = Relatorio.MarginBounds.RightDim margemInf As Single = Relatorio.MarginBounds.Bottom

- Fontes : você pode usar a fonte que desejar com tamanho e estilos a sua escolha. Eu voutrabalhar com a fonte Verdana definida para Título , rodapé e normal. Para isto vou usar a classeFont.

Dim fonteTitulo As FontDim fonteRodape As FontDim fonteNormal As Font fonteTitulo = New Font("Verdana", 15, FontStyle.Bold)fonteRodape = New Font("Verdana", 8)fonteNormal = New Font("Verdana", 10)

- Linhas , imagens e texto : Para imprimir linhas , imagens e/ou texto vamos usar os métodosdo objeto PrintPageEventArgs(relatorio) conforme abaixo:

- Linhas - Para imprimir um a linha reta entre dois pontos usa o método :relatorio.Graphics.DrawLine - DrawLine ( pen , point1, point2) :

Page 5: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 5/7

pen : define a cor , estilo e espessura da linhaPoint1 : define o ponto inicialPoint2 : define o ponto final

- Imagens - Para imprimir uma imagem (bmp,wmf, gif ou jpg) usamos o método:relatorio.Graphics.DrawImage - DrawImage(image,point):

image - indica o caminho e nome do arquivo de imagem que vamos imprimirpoint - indica as coordenadas para o eixo x e y que referencia a posição da imagem nodocumento

- Textos - Para imprimir uma string usamos o método : relatorio.Graphics.DrawString -DrawString( string ,font, brush, point, format)

String : é o texto a ser impressoBrush : define a cor , espessura e estilo da fontePoint : indica as coordenadas para o eixo x e y que referencia a posição da string nodocumentoFormat : indica parâmetros de formatação avançada: ( impressão vertical , etc.)

Então a seguir vou mostrar como podemos imprimir as secções do relatório usando os métodose propriedades já vistos até aqui.

- Impressão do cabeçalho: Abaixo temos uma imagem do cabeçalho que desejamos:

e a seguir o código que implementa isto :

Relatorio.Graphics.DrawLine(caneta, margemEsq, 60, margemDir, 60)Relatorio.Graphics.DrawImage(Image.FromFile("c:\teste\" & "maco10.gif"), 100, 68)Relatorio.Graphics.DrawLine(caneta, margemEsq, 160, margemDir, 160)Relatorio.Graphics.DrawString("Catálogo de Produtos", fonteTitulo, Brushes.Blue, margemEsq +275, 80, New StringFormat()) - Impressão dos títulos das colunas do relatório. O título das colunas irá exibir os nomes : Código , Produto e Preço no relatório. O código estaabaixo: 'impressão do titulo das colunasRelatorio.Graphics.DrawString("Código", fonteColuna, Brushes.Red,margemEsq, 140, New StringFormat())Relatorio.Graphics.DrawString("Produto", fonteColuna, Brushes.Red,margemEsq + 100, 140, New StringFormat())Relatorio.Graphics.DrawString("Preço", fonteColuna, Brushes.Red,margemEsq + 500, 140, New StringFormat())Relatorio.Graphics.DrawLine(caneta, margemEsq, 170, margemDir, 170) o resultado é :

Page 6: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 6/7

Nota : As variáveis leitor e paginaAtual declaradas deforma serem visíveis pelo projeto:Private leitor As OleDbDataReaderPrivate paginaAtual As Integer = 1

Precisamos definir o número de linhas por página conforme a área de impressão , assimpoderemos ajeitar o rodapé na página. O código para isto é o seguinte:

'define o número de linhas por página'para isto faço a divisão da área de impressão pelotamanho da fonte subtraido do valor 10linhasPorPagina = Relatorio.MarginBounds.Height /fonteNormal.GetHeight(Relatorio.Graphics) - 10

Vamos a seguir atribuir os dados da fonte de dados para as variáveis já definidas

'para imprimir os dados da base de dados no relatório teremosque atribuir as variáveis os valores'através do objeto OleDbDatareadercodigoProduto = leitor(0) 'codigo do produtonomeProduto = leitor(1) 'nome do produtoprecoProduto = leitor(2) 'preco do produto

Finalmente iremos iniciar o laço While/End e ler enquanto a linha atual for menor que onúmero de linhas por página e houver dados. Quando o número de linhas atual for maior que opermitido iremos criar o rodapé , verificar se ainda há dados para serem lidos e , se for o caso ,continuar a impressão na próxima página.

'agora vamos dar um laço através dos registros do DataReader levando em conta o númerode linhas'permitido para a página. Enquanto a linha atual for menor que o número de linhas porpágina e não'final de arquivo estaremo no loopWhile (linhaAtual < linhasPorPagina And leitor.Read())'acompanha a posição da linha atualposicaoDaLinha = margemSup + (linhaAtual * fonteNormal.GetHeight(Relatorio.Graphics))'imprime os dados relativo ao codigo , nome do produto e preço do produtoRelatorio.Graphics.DrawString(codigoProduto, fonteNormal, Brushes.Black, margemEsq,posicaoDaLinha, New StringFormat())Relatorio.Graphics.DrawString(nomeProduto, fonteNormal, Brushes.Black, margemEsq +100, posicaoDaLinha, New StringFormat())Relatorio.Graphics.DrawString(FormatCurrency(precoProduto), fonteNormal,Brushes.Black, margemEsq + 500, posicaoDaLinha, New StringFormat())'faz o incremento no número de linhalinhaAtual += 1'verifica se ainda podemos imprimir , ou seja , se a linha atual é menor que o número'de linhas permitido pela página. Se for continuamos a atribuir os dados e a imprimirIf (linhaAtual < linhasPorPagina) Then codigoProduto = leitor(0) 'codigo do produto nomeProduto = leitor(1) 'nome do produto precoProduto = leitor(2) 'preco do produtoEnd If End While

Page 7: VB .pdf Impresão.pdf

18/11/2014 VB .NET - Imprimindo via código

http://www.macoratti.net/vbn_prn2.htm 7/7

'imprime o rodape no relatorioRelatorio.Graphics.DrawLine(caneta, margemEsq, margemInf, margemDir, margemInf)Relatorio.Graphics.DrawString(System.DateTime.Now, fonteRodape, Brushes.Black,margemEsq, margemInf, New StringFormat())Relatorio.Graphics.DrawString("Pag. " & paginaAtual.ToString, fonteRodape,Brushes.Black, margemDir - 50, margemInf, New StringFormat())'incrementa a página atualpaginaAtual += 1'vamos verificar se ainda existem registros para serem impressosIf (leitor(0) <> Nothing) Then Relatorio.HasMorePages = TrueElse Relatorio.HasMorePages = FalseEnd IfEnd Sub

O resultado da visualização da impressão será o seguinte :

Usando as classes do System.Drawing.Printing podemos criar relatórios completos comrecursos de visualização sem precisar recorrer a soluções de terceiros.

Até o próximo artigo VB.NET

Referências:

Impressão e Visualização. O que há de novo ?VB .NET - Imprimindo via códigoVisualizandoa impressão no VBVB 2008 - Cadastro de Alunos

José Carlos Macoratti