2 08 2017
Imprimindo direto na impressora com o Report Viewer
Em algumas situações, faz mais sentido imprimirmos informações direto na impressora, ao invés de exibirmos uma janela de pré-visualização para o usuário. Esse tipo de otimização é muito importante quando o usuário precisa de muita rapidez na operação. Uns tempos atrás eu mostrei como imprimir informações direto na impressora através da classe PrintDocument. Em uma outra oportunidade, eu mostrei como exportar relatórios do Report Viewer. Mas, até hoje eu ainda não mostrei como imprimir relatórios direto na impressora com o Report Viewer. É justamente isso que eu vou mostrar para você neste vídeo:
Referências
O conteúdo desse vídeo / artigo foi baseado no código apresentado pelo Brian Hartman no blog dele em 2009. Além disso, eu tomei também como base essa entrada na documentação do MSDN, que mostra um passo a passo simplificado para atingirmos esse objetivo. Misturando esses dois códigos, eu criei uma terceira versão mais simplificada, que funcionou perfeitamente nos testes que eu fiz e espero que funcione também com relatórios da sua aplicação.
Para imprimirmos relatórios direto na impressora com o Report Viewer, nós temos que dividir a operação em dois passos: primeiro exportamos os relatórios em memória (no formato “imagem“), depois imprimimos cada uma das imagens em uma página separada (utilizando a classe PrintDocument).
Dito isso, o “esqueleto” do nosso código de impressão direta ficaria assim:
// C# private DataSetRelatorio CriarDataSet() { var ds = new DataSetRelatorio(); for (int c = 1; c <= 200; c++) { ds.Item.AddItemRow(c, string.Format("Item {0}", c)); } return ds; } private void btImprimir_Click(object sender, EventArgs e) { using (var ds = CriarDataSet()) using (var relatorio = new Microsoft.Reporting.WinForms.LocalReport()) { relatorio.ReportPath = "Relatorio.rdlc"; relatorio.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource("DataSetRelatorio", (DataTable)ds.Item)); Exportar(relatorio); Imprimir(relatorio); } }
' VB.NET Private Function CriarDataSet() As DataSetRelatorio Dim Ds = New DataSetRelatorio() For C As Integer = 1 To 200 Ds.Item.AddItemRow(C, String.Format("Item {0}", C)) Next Return Ds End Function Private Sub btImprimir_Click(sender As Object, e As EventArgs) Handles btImprimir.Click Using ds = CriarDataSet() Using Relatorio = New Microsoft.Reporting.WinForms.LocalReport() Relatorio.ReportPath = "Relatorio.rdlc" Relatorio.DataSources.Add(New Microsoft.Reporting.WinForms.ReportDataSource("DataSetRelatorio", DirectCast(ds.Item, DataTable))) Exportar(Relatorio) Imprimir(Relatorio) End Using End Using End Sub
Note que temos um método que retorna um DataSet para o nosso relatório. Nesse exemplo, esse método está simplesmente gerando algumas linhas em uma DataTable, que será enviada para o relatório. Obviamente, você deverá substituir esse método com o carregamento correto dos dados para o seu relatório, dependendo de como você estiver trabalhando com os dados na sua aplicação.
Exportando as páginas em memória
Como mencionei anteriormente, o primeiro passo na impressão direta do Report Viewer é a exportação das páginas em memória. A ideia nessa etapa é gerarmos uma MemoryStream para cada página do nosso relatório, sendo que cada uma dessas Streams armazenará a imagem de uma página que deverá ser impressa.
Para implementarmos essa funcionalidade, utilizaremos o método “Render” do nosso relatório. Esse é o método que utilizamos para exportarmos o relatório nos mais diversos formatos suportados, como demonstrei neste outro artigo.
Uma das sobrecargas do método “Render” recebe um call-back de geração de Streams (CreateStreamCallback). Com essa sobrecarga, nós teremos as imagens armazenadas em Streams. Para ficar mais fácil de explicar, vamos ver como é que fica o código:
// C# private void Exportar(Microsoft.Reporting.WinForms.LocalReport relatorio) { Microsoft.Reporting.WinForms.Warning[] warnings; LimparStreams(); relatorio.Render("image", CriarDeviceInfo(relatorio), CreateStreamCallback, out warnings); } private List<System.IO.Stream> _streams = new List<System.IO.Stream>(); public System.IO.Stream CreateStreamCallback(string name, string extension, Encoding encoding, string mimeType, bool willSeek) { var stream = new System.IO.MemoryStream(); _streams.Add(stream); return stream; } private void LimparStreams() { foreach (var stream in _streams) { stream.Dispose(); } _streams.Clear(); }
' VB.NET Private Sub Exportar(Relatorio As Microsoft.Reporting.WinForms.LocalReport) Dim Warnings As Microsoft.Reporting.WinForms.Warning() LimparStreams() Relatorio.Render("image", CriarDeviceInfo(Relatorio), AddressOf CreateStreamCallback, Warnings) End Sub Private Streams As New List(Of System.IO.Stream)() Public Function CreateStreamCallback(Name As String, Extension As String, Encoding As System.Text.Encoding, MimeType As String, WillSeek As Boolean) As System.IO.Stream Dim Stream = New System.IO.MemoryStream() Streams.Add(Stream) Return Stream End Function Private Sub LimparStreams() For Each Stream In Streams Stream.Dispose() Next Streams.Clear() End Sub
Note que essa sobrecarga do método “Render” recebe o formato que queremos utilizar (nesse caso, “image“), uma string com um “device info” (que eu explicarei logo mais), um CreateStreamCallback e um array de Warnings (não utilizado no nosso exemplo). A ideia é que, para cada página do relatório, o Report Viewer chamará o método de call-back, que deverá retornar uma Stream onde a página atual deverá ser armazenada. No nosso caso, nós criamos e retornamos uma MemoryStream, mantendo a referência na nossa lista interna.
Um detalhe importante é que, para cada chamada do método “Imprimir“, nós temos que limpar a nossa lista de Streams (com o método “LimparStreams“), senão a lista interna acumulará as Streams que tiverem sido geradas em chamadas anteriores desse método.
Gerando o DeviceInfo
Como você pode perceber, um dos parâmetros do método “Render” é o “DeviceInfo“. E o que seria isso? O parâmetro “DeviceInfo” é um XML contendo as informações dos tamanhos de página e margens que devem ser consideradas na exportação. Veja um exemplo desse XML na documentação do MSDN:
Não sei se você sabe, mas os arquivos rdlc nada mais são que arquivos XML com a definição do relatório. Dentro do XML do arquivo rdlc, nós encontramos as informações de página e margem, veja só:
Isso quer dizer que nós podemos ler as propriedades de tamanho de página e margem do nosso relatório (utilizando o método “GetDefaultPageSettings“) para gerarmos o XML do “DeviceInfo” dinamicamente. O código para fazer essa geração dinâmica ficaria assim:
// C# private string CriarDeviceInfo(Microsoft.Reporting.WinForms.LocalReport relatorio) { var pageSettings = relatorio.GetDefaultPageSettings(); return string.Format( System.Globalization.CultureInfo.InvariantCulture, @"<DeviceInfo> <OutputFormat>EMF</OutputFormat> <PageWidth>{0}in</PageWidth> <PageHeight>{1}in</PageHeight> <MarginTop>{2}in</MarginTop> <MarginLeft>{3}in</MarginLeft> <MarginRight>{4}in</MarginRight> <MarginBottom>{5}in</MarginBottom> </DeviceInfo>", pageSettings.PaperSize.Width / 100m, pageSettings.PaperSize.Height / 100m, pageSettings.Margins.Top / 100m, pageSettings.Margins.Left / 100m, pageSettings.Margins.Right / 100m, pageSettings.Margins.Bottom / 100m); }
' VB.NET Private Function CriarDeviceInfo(Relatorio As Microsoft.Reporting.WinForms.LocalReport) As String Dim PageSettings = Relatorio.GetDefaultPageSettings() Return String.Format( System.Globalization.CultureInfo.InvariantCulture, "<DeviceInfo><OutputFormat>EMF</OutputFormat><PageWidth>{0}in</PageWidth><PageHeight>{1}in</PageHeight><MarginTop>{2}in</MarginTop><MarginLeft>{3}in</MarginLeft><MarginRight>{4}in</MarginRight><MarginBottom>{5}in</MarginBottom></DeviceInfo>", PageSettings.PaperSize.Width / 100D, PageSettings.PaperSize.Height / 100D, PageSettings.Margins.Top / 100D, PageSettings.Margins.Left / 100D, PageSettings.Margins.Right / 100D, PageSettings.Margins.Bottom / 100D) End Function
Imprimindo as imagens geradas em memória
Uma vez geradas as Streams contendo as páginas do nosso relatório em memória, chegou a hora de efetivamente imprimirmos essas Streams. Para isso, nós utilizaremos um PrintDocument, que é uma classe disponível no namespace System.Drawing.Printing que implementa a possibilidade de imprimirmos informações direto na impressora (nesse caso, as imagens representando as páginas do nosso relatório).
O código para fazermos a impressão não é muito complicado. Primeiramente, temos que configurar mais uma vez as informações de página e margens do PrintDocument, copiando essas informações do relatório. Em seguida, nós configuramos o evento “PrintPage” do nosso PrintDocument e chamamos o método “Print” para iniciarmos a impressão.
Dentro da implementação do evento “PrintPage“, nós temos que imprimir a informação de cada uma das páginas do nosso relatório. Esse método será chamado para cada página que deverá ser impressa, por isso, temos que utilizar uma variável de controle para sabermos qual página estamos imprimindo no ciclo atual.
Para imprimirmos a Stream que foi gerada anteriormente, nós utilizamos um objeto do tipo “Metafile“, que é o tipo mais genérico de imagem. Como o construtor dessa classe recebe uma Stream, nós simplesmente passamos a Stream que foi exportada anteriormente e tudo deve funcionar perfeitamente. Nós só não podemos esquecer de rebobinar a Stream (utilizando o método “Seek“), senão a impressão sairá em branco!
Por fim, a última operação dentro do evento “PrintPage” será a configuração da propriedade “HasMorePages“. É através dessa propriedade que o PrintDocument saberá se o evento “PrintPage” deverá ser chamado mais uma vez (para imprimir a próxima página) ou não.
O código final para fazermos a impressão das Streams é o seguinte:
// C# private void Imprimir(Microsoft.Reporting.WinForms.LocalReport relatorio) { using (var pd = new System.Drawing.Printing.PrintDocument()) { pd.PrinterSettings.PrinterName = "PrimoPDF"; var pageSettings = new System.Drawing.Printing.PageSettings(); var pageSettingsRelatorio = relatorio.GetDefaultPageSettings(); pageSettings.PaperSize = pageSettingsRelatorio.PaperSize; pageSettings.Margins = pageSettingsRelatorio.Margins; pd.DefaultPageSettings = pageSettings; pd.PrintPage += Pd_PrintPage; _streamAtual = 0; pd.Print(); } } private int _streamAtual; private void Pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { var stream = _streams[_streamAtual]; stream.Seek(0, System.IO.SeekOrigin.Begin); using (var metadata = new System.Drawing.Imaging.Metafile(stream)) { e.Graphics.DrawImage(metadata, e.PageBounds); } _streamAtual++; e.HasMorePages = _streamAtual < _streams.Count; }
' VB.NET Private Sub Imprimir(Relatorio As Microsoft.Reporting.WinForms.LocalReport) Using Pd = New System.Drawing.Printing.PrintDocument() Pd.PrinterSettings.PrinterName = "PrimoPDF" Dim PageSettings = New System.Drawing.Printing.PageSettings() Dim PageSettingsRelatorio = Relatorio.GetDefaultPageSettings() PageSettings.PaperSize = PageSettingsRelatorio.PaperSize PageSettings.Margins = PageSettingsRelatorio.Margins Pd.DefaultPageSettings = PageSettings AddHandler Pd.PrintPage, AddressOf Pd_PrintPage StreamAtual = 0 Pd.Print() End Using End Sub Private StreamAtual As Integer Private Sub Pd_PrintPage(sender As Object, e As System.Drawing.Printing.PrintPageEventArgs) Dim Stream = Streams(StreamAtual) Stream.Seek(0, System.IO.SeekOrigin.Begin) Using metadata = New System.Drawing.Imaging.Metafile(Stream) e.Graphics.DrawImage(metadata, e.PageBounds) End Using StreamAtual += 1 e.HasMorePages = StreamAtual < Streams.Count End Sub
Utilizando a classe ReportPrintDocument
Se você achou todo esse código muito complicado, não se preocupe. Como eu mencionei no início do artigo, o Brian Hartman implementou uma classe que encapsula toda essa parafernalha que eu mostrei até agora. Para utilizá-la, basta baixar o arquivo correspondente a adicioná-lo no seu projeto. Você pode baixar a versão em C# aqui ou a versão em VB.NET aqui, e depois você pode adicionar no seu projeto utilizando a opção “Add -> Existing Item“:
Uma vez que você tiver adicionado essa classe no projeto, a utilização é muito simples. Basta criarmos uma instância da classe “ReportPrintDocument” (que fica no namespace “PrintReportSample“) passando o relatório e, em seguida, chamamos o método “Print“:
// C# private void btImprimir_Click(object sender, EventArgs e) { using (var ds = CriarDataSet()) using (var relatorio = new Microsoft.Reporting.WinForms.LocalReport()) { relatorio.ReportPath = "Relatorio.rdlc"; relatorio.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource("DataSetRelatorio", (DataTable)ds.Item)); using (var rpd = new PrintReportSample.ReportPrintDocument(relatorio)) { rpd.Print(); } } }
' VB.NET Private Sub btImprimir_Click(sender As Object, e As EventArgs) Handles btImprimir.Click Using ds = CriarDataSet() Using Relatorio = New Microsoft.Reporting.WinForms.LocalReport() Relatorio.ReportPath = "Relatorio.rdlc" Relatorio.DataSources.Add(New Microsoft.Reporting.WinForms.ReportDataSource("DataSetRelatorio", DirectCast(ds.Item, DataTable))) Using Rpd = New PrintReportSample.ReportPrintDocument(Relatorio) Rpd.Print() End Using End Using End Using End Sub
Bem mais simples, não é mesmo? Porém, é muito importante sabermos o que está por trás de todo o código implementado nessa classe. Dessa forma, caso algo não funcione 100% corretamente para algum relatório específico, fica mais fácil de procurarmos a origem do erro. Foi justamente por isso que eu decidi mostrar primeiramente um passo a passo de como podemos fazer essa impressão de forma manual, sem utilizar essa classe utilitária do Brian Hartman.
Baixe o projeto de exemplo
Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.
Concluindo
O processo de impressão direta de relatórios do Report Viewer não é nem tão simples, nem tão complicado. Como nós não temos um método que implementa esse tipo de impressão nativamente, nós precisamos primeiramente exportar as páginas do nosso relatório em memória e, em seguida, imprimimos cada página utilizando um PrintDocument.
Como você pode observar, se você não estiver a fim de aprender o que está por trás de toda essa implementação, não tem problema. Basta baixar e utilizar a classe “ReportPrintDocument” implementada pelo Brian Hartman, que eu disponibilizei tanto em C# (original do Brian Hartman) e VB.NET (que eu converti por conta própria).
E você, já precisou imprimir relatórios do Report Viewer direto na impressora? Você já tinha conhecimento dessa classe do Brian Hartman ou você fez a implementação “na mão” utilizando o tutorial do MSDN? No final das contas deu tudo certo ou teve algum relatório em que a impressão direta não funcionou? Fico aguardando os seus comentários logo abaixo!
Até a próxima!
André Lima
Trabalhando com data binding no Windows Forms Aplicações Android com Xamarin – Parte 4 de N – Customizando o controle ListView
Muito interessante este post, vai me ajudar em um monte de casos. Aproveitando para te fazer uma pergunta, pois estou com um grave problema aqui. Há um tempo atrás me ajudou muito um dos seus post e até conversamos trocando informações. Aqui na empresa tínhamos vários relatórios que estavam com página A3 e quando imprimíamos em impressora, o documento era reduzido e impresso em folha A4 automático sem cortar nada, mas de um tempo para cá não tem acontecido isso os documentos só são reduzidos agora quando impressos em PDF e depois enviados a impressora. Sabe o que pode ter sido alterado para isso não acontecer mais?
Olá Elcio!
Infelizmente, não faço ideia.. Não teve nenhuma alteração de hardware? A impressora é a mesma, os drivers são os mesmos? Se vocês não alteraram nada na aplicação, acredito que só possa ser algo no ambiente mesmo..
Abraço!
André Lima
André,
Sempre um bom trabalho.
Muito obrigado, Airton! Que bom que você gostou.. :)
Abraço!
André Lima
Olá Andre muto bom o vídeo e de muita utilidade, gostaria de baixar o projeto como devo proceder? Ja tenho assinatura da página
Olá Diego! Muito obrigado pelo comentário, fico feliz que você tenha gostado.. :)
Mandei o link para baixar os projetos de exemplo no seu email.. Qualquer coisa é só entrar em contato..
Abraço!
André Lima
E o que fazer quando o erro:
FileNotFoundException: Não foi possível localizar o arquivo ‘C:\Users\Marcos\Documents\Visual Studio 2017\Projects\Gestor\Gestor\bin\Debug\OrdemServico.rdlc’.
aparece?
Como eu passo, qndo o RDLC está dentro de uma pasta no projeto?
Olá Marcos!
Como é que ficou o seu código? Igual ao do artigo? Ali no lugar onde eu coloco “Relatorio.rdlc”, você pode passar o caminho completo do relatório também.. Se você não passar caminho nenhum, ele tentará abrir da pasta onde o executável está localizado..
Quando você fizer o deployment da aplicação, o relatório estará no mesmo diretório da aplicação? Caso positivo, você pode simplesmente selecionar o relatório no seu projeto e, na janela de propriedades do Visual Studio, você pode escolher para copiar o arquivo rdlc automaticamente para a pasta da aplicação (opção “Copy always”)..
Abraço!
André Lima
Boa tarde Andre, gostei muito do artigo, mas não estou conseguindo baixar o exemplo do projeto para poder entender alguns pontos, como faço para pegar esse exemplo?
Olá Damião!
Acabei de te enviar um e-mail com o link.. Qualquer problema é só falar..
Abraço!
André Lima
Oi, André, tudo bem?
Eu estou tentando fazer uma impressão via reportviewer, sem que mostre o preview do relatório. Gostaria que, ao clicar, mostrasse apenas a caixa de diálogo para escolha da impressora. Pesquisando, descobri o PrintDialog, que eu uso assim:
rptViewer.RefreshReport();
rptViewer.PrintDialog();
Isso me dá o seguinte erro:
A operação não é válida devido ao estado atual do objeto.
Pesquisando mais, descobri que deveria colocar o PrintDialog dentro do evento RenderingComplete, o que eu já fiz e continuo com o mesmo erro.
Sabe o que estou fazendo de errado?
Olá Mariana!
A aplicação seria desktop ou web? Se for desktop você poderia seguir justamente as instruções deste vídeo onde você fez esse comentário, que eu mostro como imprimir os relatórios sem precisar mostrar o preview.. Você não tentou da maneira que eu expliquei no vídeo/artigo?
Abraço!
André Lima
Eu estava tentando manter o padrão que já temos para a impressão com preview, mas acho que não vai dar certo.
Poderia me mandar o seu projeto de exemplo?
Estou tentando implementar o seu código. Eu consigo colocar esse trecho em uma classe ou precisa ser em um form? Percebi que dá erro quando coloco em classe.
using (var relatorio = new Microsoft.Reporting.WinForms.LocalReport())
{
using (var rpd = new claReportPrintDocument(relatorio))
{
rpd.Print();
}
}
Olá novamente, Mariana!
Qual é o erro exatamente que você está recebendo com esse código que você postou? Para baixar os projetos de exemplo, é só assinar a minha newsletter (link “Inscreva-se” ali em cima no menu) e no e-mail de confirmação você recebe o link para baixar todos os projetos..
Abraço!
André Lima
Opa, vi aqui que você já é inscrita na newsletter.. Acabei de te enviar o link para baixar os projetos..
Abraço!
André Lima
ESTOY MUY AGRADECIDO POR TU GRAN AYUDA.
TENGO UNA CONSULTA TU PROYECTO QUE DESCARGUE ESTA BIEN ..IMPRIME
PERO CUANDO QUIERO ADAPTARLO A MI PROYECTO ME BOTA ESTE ERROR
overload resolution failed because no accessible ‘new’ accepts this number of arguments
ESTA EN LA LINEA DE CODIGO Ds.generar_comprobante.Addgenerar_comprobanteRow(C, String.Format(“Item {0}”, C)) PARA SER MAS EXACTO EN Addgenerar_comprobanteRow
Private Function CriarDataSet() As marketDataSet
Dim Ds = New marketDataSet()
For C As Integer = 1 To 200
Ds.generar_comprobante.Addgenerar_comprobanteRow(C, String.Format(“Item {0}”, C))
Next
Return Ds
End Function
SI ME PUEDES AYUDAR PORFAVOR…
MI CODIGO REPORTVIEWER ES ESTA
Me.generar_comprobanteTableAdapter.Fill(Me.marketDataSet.generar_comprobante, idventa:=txtidventa.Text)
Me.ReportViewer.RefreshReport()
Olá Steban!
Muito provavelmente esse erro está acontecendo porque a estrutura da sua DataTable tem uma quantidade de colunas diferente do que você está passando no método “Addgenerar_comprobanteRow”.. Quantas colunas você tem na sua DataTable? Você precisa passar exatamente as informações para cada uma das colunas dela (na ordem correta, com os tipos corretos) no método “Addgenerar_comprobanteRow”..
Abraço!
André Lima
Podrias apoyarme,recien estoy empezando como desarrollador en .net yo pagare tus servicios brindados.
Olá Steban.
Eu até presto alguns tipos de serviço de consultoria, mas não se encaixa muito bem para iniciantes (sem falar na diferença de idioma que é um grande complicador nesse caso).. Mas, enfim, você pode dar uma olhada nas opções neste página:
http://www.andrealveslima.com.br/blog/index.php/consultoria/
Abraço!
André Lima
GRACIAS POR TU GRAN AYUDA…LA VERDAD TRATE DE COMUNICARME CONTIGO QUE ME AYUDES….NO SE QUE ESTOY HACIENDO MAL..
TE DEJO EL CODIGO
https://mega.nz/#!KsAyXbKC!FNy-BAFfCqRqulzTCTrzd00tkjKNR-6OLaIdf_KdjK0
Olá novamente Steban.
Só com o código fica difícil de ajudar.. Você precisa falar o que você já tentou fazer, os erros que você está recebendo, etc.. Mas, levando em consideração o seu primeiro comentário, aquele erro que você estava tendo ao adicionar uma linha no DataSet é justamente o que eu te falei.. A sua DataTable “generar_comprobante” tem uma infinidade de campos (venta, nombre, apelidos, etc).. Na hora de utilizar o método “Addgenerar_comprobanteRow”, você tem que passar as informações para cada uma dessas colunas, conforme indicado pelo IntelliSense:
No código que você me mandou anteriormente, você só está tentando passar o valor para algumas colunas, e isso não faz sentido.. Ao utilizar esse método você precisa passar o valor para todas as colunas..
Abraço!
André Lima
O artigo me ajudou bastante. Porém ainda estou com um problema na renderização – a emf criado ficou maior do que o layout do relatório. Com isso , o que era pra ser impresso em uma página, está sendo impresso em 2, com as fontes distorcidas. Ainda não consegui achar o problema, pois pelo debug aparece exatamente o tamanho do report.
Olá Bruno!
Que estranho.. Nunca tive esse tipo de problema.. Será que não está com algum problema na margem? Se quiser mandar o rdlc (ou o projeto) para eu dar uma testada aqui, fique à vontade.. Meu e-mail é o contato [arroba] andrealveslima [ponto] com [ponto] br
Abraço!
André Lima
André, muito obrigado. Pelo debug percebi que a imagem não renderizava com a página em modo paisagem. Na hora da geração de imagem, passei a verificar qual o formato em que ela se encontrava para inverter os valores de width e height. A partir dessa mudança funcionou normalmente. Pode ser que exista outra forma pra ajustar isso, mas como no momento foi a única que encontrei – resolveu.
Maravilha, hein Bruno.. Que bom que você conseguiu resolver.. :)
Qualquer outra dificuldade, é só entrar em contato..
Abraço!
André Lima
Andre, buen dia
Me fue de gran utilidad el proyecto de ejemplo para probar la impresion directa del report viewer. Precisaria de tu asesoramiento ya que preciso incluir un codigo de barras en el report viewer para imprimirlo de forma directa.
Utilice el siguiente tutorial para generar el codigo de barra y enviarlo como imagen al report viewer
http://www.andrealveslima.com.br/blog/index.php/2017/11/08/trabalhando-com-codigo-de-barras-no-report-viewer/
No logro replicar esto para la impresion directa.
Saludos
Franco
Olá Franco!
Muito obrigado pelo comentário.. Eu respondi o e-mail que você me mandou.. Não entendi muito bem a sua dúvida, mas vamos continuar a conversa por lá.. Fico aguardando o seu retorno..
Abraço!
André Lima
Olá André, primeiramente parabéns pelo post e vídeo aula, te sigo no youtube e acompanho seu post, são de grande ajuda.
Gostaria de tirar uma duvida com você, como que faz para passar o parâmetro na hora da visualização e impressão.
Exemplo: No dataset o select precisa de um parâmetro para exibir os dados corretamente, na exibição do reportview normal, eu costumo passar desta forma:
this.reciboTableAdapter.Fill(this.Data_relatório.recibo,id);
Saberia me falar como ficaria passando na hora de imprimir sem a visualização?
Obrigado.
Abraço!
Olá Renato, muito obrigado pelo comentário!
Nesse caso, na realidade você está passando o parâmetro para o método “Fill” do DataAdapter, que a princípio é independente do relatório.. Repare no exemplo do vídeo que eu passo os dados para o relatório na linha com a chamada “relatorio.DataSources.Add…”.. Nesse exemplo eu estou passando a DataTable “Item” que foi preenchida pelo método “CriarDataSet”.. No seu caso, você vai passar a sua DataTable “recibo”, que foi preenchida pelo método “Fill” anteriormente utilizando o parâmetro indicado..
Entendeu a ideia? O parâmetro do método “Fill” do Adapter é independente do relatório..
Abraço!
André Lima
Olá André, obrigado por responder. Entendi a ideia.
Fiz igual a você criei um DataTable e deu certo.
Porem agora surgiu uma outra dúvida…rsrs
Como que eu passo um parâmetro normal, por aqui:
var ds = CriarDataSet();
FormRelatorio.ShowReport(“Relatorio.rdlc”, false, new Dictionary() { { “DataSetRelatorio”, (DataTable)ds.Item } });
}
Para cair corretamente neste método:
// reportParameters.
if (reportParameters != null)
{
var reportParameterCollection = new List();
foreach (var parameter in reportParameters)
{
var reportParameter = new Microsoft.Reporting.WinForms.ReportParameter(parameter.Key, parameter.Value.ToString());
reportParameterCollection.Add(reportParameter);
}
this.reportViewer.LocalReport.SetParameters(reportParameterCollection);
}
Obrigado
Olá Renato!
É só passar as combinações de chave/valor no quarto parâmetro da chamada.. Exemplo:
Abraço!
André Lima
Boa noite caríssimo André Alves Lima, tenho um leitor Biométrico SDK da Nitgen, mas infelizmente não consigo fazer o cadastro das impressões digitais no SQL Server e para posteriormente fazer o login. Estou usando o Visual Studio (Visual Basic)
Olá Raul!
Infelizmente vou ficar te devendo essa.. Não tenho nenhum dispositivo biométrico aqui para poder testar, então fica difícil ajudar.. Mas, normalmente os fabricantes dos dispositivos têm exemplos para download em diversas linguagens.. Você já deu uma procurada para ver se não acha um exemplo pronto em .NET?
Abraço!
André Lima
Olá André, estou tendo problema em gerar um relatório com a propriedade EnableExternalImages… No relatório, apenas visualizando, funciona normalmente. Nas propriedades dele já está habilitado esta questão da imagem. Porém ao passar pra toda essa metodologia de imprimir direto; dá erro dizendo que a propriedade das imagens externas está desabilitado. Coloquei no método CriarDeviceInfo a linha: relatorio.EnableExternalImages = true; que resolve este erro e passa a ser outro:
na linha relatorio.Render(“image”…..); dá o seguinte erro:
ReportProcessingException: Não é possível criar um leitor de dados para o conjunto de dados ‘MeuDataSet’.
Penso que falta eu acrescentar alguma linha no xml do device info… Já viu este erro?
Muito obrigado.
Oi André, o problema foi resolvido, estava ainda vacilando com os nomes dos datasets. Tem um que a gente nomeia quando cria uma fonte de dados, este é o nome pra se usar na definição… Mais uma vez obrigado. A questão das imagens externas além da definição no próprio RDLC, tem que apenas inserir esta linha que inseri e já resolve o problema de dar erro.
CriarDeviceInfo(…)
relatorio.EnableExternalImages = true;
Forte abraço.
Olá Kayo!
Obrigado pelo retorno.. Fico feliz que você tenha conseguido solucionar o problema.. E obrigado pelo toque referente à propriedade “EnableExternalImages”..
Abraço!
André Lima
André, Parabéns pelo post e pela explicação!
Estava precisando mesmo de criar um de meus relatórios de uma forma direta da impressora.
Aproveitando, peço uma ajuda sua (tentei de várias forma e não obtive sucesso!).
É:
– Tenho um relatório que não é “tipado” onde passo parâmetros para alguns campos. Bom, em um determinado campo, na base de dados, tem vários itens para o do cliente que está sendo impresso.
Pergunto (dúvida):
Como faço para passar o parâmetro para esses itens?
Para ser mais claro, estou imprimindo uma Ordem de Serviço e é no momento de imprimir os itens de produtos.
Fico no aguardo de uma ajuda nessa minha dúvida. Ah!, já tenho assinatura da página.
Desde já, agradeço pelas ótimas “DIKAS”, explicações e vídeos seus!
Jorge Kharuf
Olá Jorge, obrigado pelo comentário!
Não consegui entender muito bem o que você quis dizer.. Será que você poderia explicar de outra maneira?
Se você estiver com dificuldades na hora de passar os parâmetros para o seu relatório, recomendo que você dê uma olhada neste artigo:
Trabalhando com parâmetros no Report Viewer
Abraço!
André Lima
Gracias Andres, un abrazo desde Iquitos-Perú, buen video, me pudieras hacer llegar tu proyecto por favor. Gracias
Olá Jorge!
Para ter acesso aos projetos de exemplo, inscreva-se na minha lista:
Inscreva-se
Abraço!
André Lima