4 05 2016
Como podemos exportar relatórios do Report Viewer?
Uma necessidade muito comum quando trabalhamos com relatórios nos nossos sistemas é a questão da exportação dos relatórios. A exibição dos relatórios é somente uma parte do processo de geração de relatórios. Muitas vezes o usuário precisa de uma versão em DOC ou PDF para arquivar ou até mesmo para mandar por e-mail.
Como toda ferramenta de relatórios que se preze, o Report Viewer possui a opção de exportação para alguns formatos bem conhecidos: Word, Excel, PDF e imagem. Neste artigo eu vou mostrar para você como exportar relatórios do Report Viewer diretamente no controle visualizador, como desabilitar formatos de exportação específicos, como habilitar alguns formatos escondidos por padrão e, por fim, como exportar os relatórios sem utilizar o preview. Vamos lá?
Criando o projeto de exemplo
Para começarmos esse artigo, vamos criar um relatório extremamente simples, que será a base para todos os exemplos de exportação. Como o foco do artigo não é a geração do relatório em si, não vou perder muito tempo com essa explicação, OK?
Nota: se você quiser conferir, eu já escrevi diversos outros artigos onde eu mostro mais detalhes sobre a geração de relatórios como, por exemplo, este aqui onde eu explico como criar um relatório mestre/detalhe com Report Viewer + Entity Framework. Ah, e claro, além disso tem o meu livro sobre Report Viewer também, caso você queira se aprofundar nesse tema.
Enfim, para o exemplo básico deste artigo, vamos criar um projeto do tipo “Windows Forms Application“. Nesse projeto, vamos adicionar uma classe “Funcionario“, que servirá de fonte de dados para o nosso relatório de exemplo:
// C# public class Funcionario { public string Nome { get; set; } public string Sobrenome { get; set; } public DateTime DataNascimento { get; set; } public string Cargo { get; set; } public DateTime DataAdmissao { get; set; } public DateTime DataDemissao { get; set; } }
' VB.NET Public Class Funcionario Public Property Nome As String Public Property Sobrenome As String Public Property DataNascimento As DateTime Public Property Cargo As String Public Property DataAdmissao As DateTime Public Property DataDemissao As DateTime End Class
Antes de continuarmos, compile o projeto. Caso contrário, a engine do Report Viewer não reconhecerá essa nova classe na hora de criarmos o DataSet do relatório. Feito isso, vamos adicionar um relatório básico, que listará os funcionários. Dê o nome de “RelatorioFuncionarios” para o novo relatório e adicione um DataSet (do tipo “Object DataSource“, escolhendo a classe “Funcionario” que criamos anteriormente) e dê o nome de “DataSetFuncionario“. No corpo do relatório, adicione uma Table a arraste os campos do DataSet para dentro dessa tabela:
Em seguida, vamos voltar ao formulário para adicionarmos o controle do Report Viewer. Configure o controle de forma que ele aponte para o relatório que acabamos de criar:
No code-behind, dentro do evento “Load“, vamos criar alguns funcionários que deverão ser listados no relatório:
// C# private void FormRelatorio_Load(object sender, EventArgs e) { FuncionarioBindingSource.Add(new Funcionario() { Nome = "André", Sobrenome = "Lima", DataNascimento = new DateTime(1984, 1, 1), Cargo = "Programador", DataAdmissao = new DateTime(2008, 2, 1) }); FuncionarioBindingSource.Add(new Funcionario() { Nome = "Fulano", Sobrenome = "de Tal", DataNascimento = new DateTime(1973, 4, 15), Cargo = "Gerente", DataAdmissao = new DateTime(1998, 4, 1) }); FuncionarioBindingSource.Add(new Funcionario() { Nome = "Beltrano", Sobrenome = "Silva", DataNascimento = new DateTime(1959, 2, 23), Cargo = "Diretor", DataAdmissao = new DateTime(1993, 1, 1) }); FuncionarioBindingSource.Add(new Funcionario() { Nome = "João", Sobrenome = "Souza", DataNascimento = new DateTime(1989, 8, 14), Cargo = "Estagiário", DataAdmissao = new DateTime(2010, 6, 1), DataDemissao = new DateTime(2012, 12, 31) }); this.reportViewer.RefreshReport(); }
' VB.NET Private Sub FormRelatorio_Load(sender As Object, e As EventArgs) Handles MyBase.Load FuncionarioBindingSource.Add(New Funcionario() With {.Nome = "André", .Sobrenome = "Lima", .DataNascimento = New DateTime(1984, 1, 1), .Cargo = "Programador", .DataAdmissao = New DateTime(2008, 2, 1)}) FuncionarioBindingSource.Add(New Funcionario() With {.Nome = "Fulano", .Sobrenome = "de Tal", .DataNascimento = New DateTime(1973, 4, 15), .Cargo = "Gerente", .DataAdmissao = New DateTime(1998, 4, 1)}) FuncionarioBindingSource.Add(New Funcionario() With {.Nome = "Beltrano", .Sobrenome = "Silva", .DataNascimento = New DateTime(1959, 2, 23), .Cargo = "Diretor", .DataAdmissao = New DateTime(1993, 1, 1)}) FuncionarioBindingSource.Add(New Funcionario() With {.Nome = "João", .Sobrenome = "Souza", .DataNascimento = New DateTime(1989, 8, 14), .Cargo = "Estagiário", .DataAdmissao = New DateTime(2010, 6, 1), .DataDemissao = New DateTime(2012, 12, 31)}) Me.ReportViewer.RefreshReport() End Sub
Pronto! Execute o projeto e veja o resultado:
Desabilitando a exportação
Agora que já temos o nosso relatório de exemplo sendo exibido, vamos começar a trabalhar com a exportação. A primeira coisa que temos que aprender é como habilitar ou desabilitar a exportação por completo. Isso pode ser feito de maneira muito fácil através da propriedade “ShowExportButton” (no controle desktop) ou “ShowExportControls” (no controle web):
Se deixarmos essa propriedade como “true” (que é o padrão), as opções de exportação serão exibidas na barra de tarefas do controle:
Por outro lado, ao configurarmos essa propriedade para “false“, o botão de exportação não será exibido:
Desabilitando alguns formatos de exportação
OK, agora que já vimos como desabilitar as opções de exportação por completo, vamos ver como conseguimos desabilitar somente alguns formatos de exportação?
Basicamente, para desabilitarmos somente alguns formatos de exportação, temos que recuperar os formatos utilizando o método “ListRenderingExtensions” e, via reflection, alteramos o atributo “m_isVisible” para false nos formatos que desejarmos. Por exemplo, para desabilitarmos a exportação para o Excel, podemos utilizar esse trecho de código no evento “Load” do controle do Report Viewer:
// C# private void reportViewer_Load(object sender, EventArgs e) { var fieldInfo = typeof(Microsoft.Reporting.WinForms.RenderingExtension).GetField("m_isVisible", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); foreach (var extension in this.reportViewer.LocalReport.ListRenderingExtensions()) { if (string.Compare("EXCELOPENXML", extension.Name) == 0) fieldInfo.SetValue(extension, false); } }
' VB.NET Private Sub ReportViewer_Load(sender As Object, e As EventArgs) Handles ReportViewer.Load Dim fieldInfo As System.Reflection.FieldInfo = GetType(Microsoft.Reporting.WinForms.RenderingExtension).GetField("m_isVisible", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic) For Each extension As Microsoft.Reporting.WinForms.RenderingExtension In ReportViewer.LocalReport.ListRenderingExtensions() If (String.Compare("EXCELOPENXML", extension.Name) = 0) Then fieldInfo.SetValue(extension, False) End If Next End Sub
Habilitando formatos de exportação escondidos
Ao mesmo tempo que podemos desabilitar algumas opções de exportação utilizando reflection, podemos utilizar a mesma metodologia para habilitarmos algumas opções de exportação que ficam escondidas por padrão. Por exemplo, não sei se você sabe, mas, é possível exportarmos o relatório para os formatos antigos do Office (Word .doc e Excel .xls) e também no formato imagem.
Para habilitarmos esses formatos de exportação que ficam escondidos por padrão, ao invés de alterarmos o valor do campo “m_isVisible” para “false“, nós iremos alterá-lo para “true” em todos os casos:
// C# private void reportViewer_Load(object sender, EventArgs e) { var fieldInfo = typeof(Microsoft.Reporting.WinForms.RenderingExtension).GetField("m_isVisible", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); foreach (var extension in this.reportViewer.LocalReport.ListRenderingExtensions()) { fieldInfo.SetValue(extension, true); } }
' VB.NET Private Sub ReportViewer_Load(sender As Object, e As EventArgs) Handles ReportViewer.Load Dim fieldInfo As System.Reflection.FieldInfo = GetType(Microsoft.Reporting.WinForms.RenderingExtension).GetField("m_isVisible", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic) For Each extension As Microsoft.Reporting.WinForms.RenderingExtension In ReportViewer.LocalReport.ListRenderingExtensions() fieldInfo.SetValue(extension, True) Next End Sub
Com isso, execute a aplicação e note que algumas novas opções de exportação apareceram:
Exportando sem o preview
Até agora nós vimos como exportar o relatório do Report Viewer utilizando o botão existente dentro do próprio controle visualizador. Agora, pode ser que você deve estar se perguntando: “tem como exportar o relatório sem o controle visualizador?“. Tem! E é justamente isso que eu vou te mostrar agora.
A classe LocalReport possui um método chamado Render. Ao chamarmos esse método passando o formato desejado (PDF, por exemplo), um array de bytes será retornado com o conteúdo da exportação. Para fazermos uso desse método, podemos simplesmente carregar uma instância de LocalReport manualmente (sem a utilização do viewer). Vamos conferir como podemos fazer isso?
O primeiro passo para demonstrarmos a exportação direta é a criação de um novo formulário. Nesse formulário, adicione dois botões (“pdfButton” e “docxButton“):
Feito isso, no code-behind, vamos adicionar um atributo do tipo LocalReport (que dei o nome de “report“) e vamos fazer o carregamento manual do relatório no construtor do formulário (ou no “Load“, caso você esteja trabalhando com VB.NET):
// C# Microsoft.Reporting.WinForms.LocalReport report; public FormExport() { InitializeComponent(); report = new Microsoft.Reporting.WinForms.LocalReport(); report.ReportEmbeddedResource = "ReportViewerExport.RelatorioFuncionarios.rdlc"; var funcionarios = new List<Funcionario>(); funcionarios.Add(new Funcionario() { Nome = "André", Sobrenome = "Lima", DataNascimento = new DateTime(1984, 1, 1), Cargo = "Programador", DataAdmissao = new DateTime(2008, 2, 1) }); funcionarios.Add(new Funcionario() { Nome = "Fulano", Sobrenome = "de Tal", DataNascimento = new DateTime(1973, 4, 15), Cargo = "Gerente", DataAdmissao = new DateTime(1998, 4, 1) }); funcionarios.Add(new Funcionario() { Nome = "Beltrano", Sobrenome = "Silva", DataNascimento = new DateTime(1959, 2, 23), Cargo = "Diretor", DataAdmissao = new DateTime(1993, 1, 1) }); funcionarios.Add(new Funcionario() { Nome = "João", Sobrenome = "Souza", DataNascimento = new DateTime(1989, 8, 14), Cargo = "Estagiário", DataAdmissao = new DateTime(2010, 6, 1), DataDemissao = new DateTime(2012, 12, 31) }); var dataSource = new Microsoft.Reporting.WinForms.ReportDataSource("DataSetFuncionario", funcionarios); report.DataSources.Add(dataSource); report.Refresh(); }
' VB.NET Private Report As Microsoft.Reporting.WinForms.LocalReport Private Sub FormExport_Load(sender As Object, e As EventArgs) Handles MyBase.Load Report = New Microsoft.Reporting.WinForms.LocalReport() Report.ReportEmbeddedResource = "ReportViewerExport.VB.RelatorioFuncionarios.rdlc" Dim Funcionarios As New List(Of Funcionario) Funcionarios.Add(New Funcionario() With {.Nome = "André", .Sobrenome = "Lima", .DataNascimento = New DateTime(1984, 1, 1), .Cargo = "Programador", .DataAdmissao = New DateTime(2008, 2, 1)}) Funcionarios.Add(New Funcionario() With {.Nome = "Fulano", .Sobrenome = "de Tal", .DataNascimento = New DateTime(1973, 4, 15), .Cargo = "Gerente", .DataAdmissao = New DateTime(1998, 4, 1)}) Funcionarios.Add(New Funcionario() With {.Nome = "Beltrano", .Sobrenome = "Silva", .DataNascimento = New DateTime(1959, 2, 23), .Cargo = "Diretor", .DataAdmissao = New DateTime(1993, 1, 1)}) Funcionarios.Add(New Funcionario() With {.Nome = "João", .Sobrenome = "Souza", .DataNascimento = New DateTime(1989, 8, 14), .Cargo = "Estagiário", .DataAdmissao = New DateTime(2010, 6, 1), .DataDemissao = New DateTime(2012, 12, 31)}) Dim dataSource As New Microsoft.Reporting.WinForms.ReportDataSource("DataSetFuncionario", Funcionarios) Report.DataSources.Add(dataSource) Report.Refresh() End Sub
Em seguida, vamos adicionar um método que fará a exportação do relatório, recebendo o formato da exportação e o nome do arquivo:
// C# private void ExportarRelatorio(string formato, string nomeArquivo) { var bytes = report.Render(formato); System.IO.File.WriteAllBytes(nomeArquivo, bytes); }
' VB.NET Private Sub ExportarRelatorio(Formato As String, NomeArquivo As String) Dim Bytes = Report.Render(Formato) System.IO.File.WriteAllBytes(NomeArquivo, Bytes) End Sub
Por fim, vamos implementar o handler para o evento “Click” dos botões passando o formato desejado e o caminho do arquivo a ser gerado:
// C# private void pdfButton_Click(object sender, EventArgs e) { ExportarRelatorio("PDF", "relatorio2.pdf"); } private void docxButton_Click(object sender, EventArgs e) { ExportarRelatorio("WORDOPENXML", "relatorio2.docx"); }
' VB.NET Private Sub pdfButton_Click(sender As Object, e As EventArgs) Handles pdfButton.Click ExportarRelatorio("PDF", "relatorio2.pdf") End Sub Private Sub docxButton_Click(sender As Object, e As EventArgs) Handles docxButton.Click ExportarRelatorio("WORDOPENXML", "relatorio2.docx") End Sub
Execute o aplicativo, clique no botão de exportação desejado e veja o resultado sendo gerado na pasta bin/debug da aplicação:
Concluindo
Exportar relatórios do Report Viewer não é uma tarefa difícil de ser realizada. Se o botão de exportação do próprio controle visualizador for o suficiente para você, a dificuldade é praticamente nula. Nesse caso, o máximo que você poderia customizar seriam os formatos para exportação, desabilitando alguns dos formatos caso necessário ou exibindo os formatos que ficam escondidos por padrão.
Por outro lado, caso você não queira disponibilizar o botão de exportação no próprio viewer ou caso você queira fazer a exportação diretamente sem exibir o relatório, podemos fazer isso através do método Render da classe LocalReport.
Todas essas opções você conferiu em detalhes neste artigo. Agora que você virou um expert em exportação de relatórios do Report Viewer, conte pra gente nos comentários: você já precisou exportar relatórios do Report Viewer na sua aplicação? Caso positivo, qual das opções você utilizou? Você sabia que alguns formatos de exportação vinham escondidos por padrão? Aguardamos os seus comentários na caixa logo abaixo!
Antes de me despedir, convido você a inscrever-se na minha newsletter. Ao fazer isso, você receberá um e-mail toda semana sobre o artigo publicado, ficará sabendo em primeira mão sobre o artigo da próxima semana e receberá também dicas “bônus” que eu só compartilho por e-mail. Além disso, você já deve ter percebido que eu recebo muitas sugestões de temas e eu costumo dar prioridade às sugestões vindas de inscritos da minha newsletter. Inscreva-se utilizando o formulário logo abaixo.
Até a próxima!
André Lima
Image by Pixabay used under Creative Commons
https://pixabay.com/en/calculator-calculation-insurance-1044173/
Ajustando o formulário dependendo da resolução no Windows Forms Trabalhando com o Crystal Reports no WPF
André muito bons seus artigos sobre relatórios, agora uma pergunta, existe a possibilidade de exportação nativa para CVS no Report Viewer?
Obrigado!
Olá Fábio, muito obrigado pelo comentário!
Desculpe a demora em responder.. É que meu segundo filho nasceu no final de semana retrasado e eu tirei a semana passada off..
Quanto à sua questão sobre exportação nativa para CSV no Report Viewer, eu nunca precisei fazer isso.. Pelo que pesquisei aqui, não dá para ser feito.. Não sei se você já viu esta thread no StackOverflow:
Export to CSV in LocalReport of ReportViewer of winform
Nessa thread, uma das pessoas que respondeu sugeriu implementar essa funcionalidade “na mão”, exportando a própria DataTable que está alimentando o relatório para CSV através de um item customizado na Toolbar do controle..
Tem também este artigo no CodeProject (que diga-se de passagem, eu não testei) que mostra uma gambiarra para adicionar algumas opções de exportação disponíveis para o Server Report (SQL Server Reporting Services) no LocalReport.. Parece bem complicado:
Adding DOC, RTF, and OOXML Export Formats to the Microsoft Report Viewer Control
Por fim, já existe a sugestão no Visual Studio User Voice para que o formato CSV seja suportado nativamente no Report Viewer.. Vote lá:
Visual Studio User Voice: Allow users to export to CSV from reportviewer when using local processing mode
Abraço!
André Lima
Olá André!
Primeiro quero lhe parabenizar pelo nascimento do seu filho, Deus abençoe e que tenha muita saúde!
Obrigado pela resposta. Já havia visto sim estes posts porém como sabia que existia a funcionalidade do Report Server pensei que pudesse haver algo no Report Viewer.
Vou primeiro tentar convencer ao cliente em usar o Excel ao invés do CSV, caso não seja possível vou tentar implementar via Hard Code como nos artigos que mandou.
Obrigado pela atenção!
Abraço!
Fábio de Oliveira Santps
Olá Fábio!
Muito obrigado!
Beleza então.. Depois volta aqui e conta pra gente se você conseguiu convencer o seu cliente ou se você implementou a exportação para CSV “na mão”.. Boa sorte!
Abraço!
André Lima
Artigo muito detalhado e, sobretudo, muito útil.
Olá Fausto! Muito obrigado pelo comentário! Fico feliz que você tenha gostado do conteúdo..
Abraço!
André Lima
Olá André!
Utilizei o código que você ensinou para desabilitar a exportação do reportviewer para excel, contudo está dando erro na parte de LocalReport! Estou utilizando o Visual Basic 2013.
Você pode me ajudar?!
Desde já agradeço!
Olá Ana, tudo bem?
Qual o erro que você está recebendo? Você poderia dar mais detalhes para eu conseguir te ajudar melhor?
Abraço!
André Lima
[…] algumas semanas atrás eu mostrei como exportar relatórios do Report Viewer. Esta semana eu decidi escrever novamente sobre o tema exportação de relatórios, só que dessa […]
Andre Boa tarde,
Gostei muito do seu código para exportar o report Viewer via código C#, estou usando nos meus sistemas, mas eu gostaria de saber se tem como exportar no formato .jpg ou .bnp?
Grato
Olá Luiz, obrigado pelo comentário!
Diretamente para jpg ou bmp você não consegue exportar pelo Report Viewer.. Porém, o que você pode fazer é exportar para TIFF (que também é um formato de imagem) e depois converter de TIFF para JPG ou BMP.. Esta thread do StackOverflow mostra como converter TIFF para JPG:
Convert tiff to jpg format
Abraço!
André Lima
Olá André, obrigado pela atenção
Eu consegui Exportar para Image .jpg
Segue o código que eu usei
string diretorio_programa1 = @”C:\Users\User\Desktop\Relatório Contador\”;
string formulario = “Relatorio”;
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
byte[] bytes = reportViewer1.LocalReport.Render(
“Image”, null, out mimeType, out encoding,
out extension,
out streamids, out warnings);
FileStream fs = new FileStream(diretorio_programa1 + formulario + “.jpg”, FileMode.Create);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
Olá Luiz, obrigado pelo retorno! Muito interessante o código que você utilizou.. Não tinha pensado nessa alternativa de utilizar o método Render.. Vivendo e aprendendo.. :)
Abraço!
André Lima
Opa tudo bem Luiz.
Você colocou esse codigo no evento click do botão?
Olá André! Que maravilha de artigo!
Acho que é a primeira vez que vejo alguém realmente tentando explicar o funcionamento do reportviewer.
Me ajudou em várias coisas, mas ainda fiquei com uma dúvida:
Ao gerara exportação para word excel, o relatório fica perfeito. Porém ao gerar para PDF, são geradas algumas páginas a mais, como no excel quando você manda imprimir e as células são maiores que a largura da página.
Há alguma forma de configurar o reportviewer para gerar todo o relatório em uma página horizontalmente?
Obrigado,
Olá Marco, obrigado pelo comentário!
Esse tipo de problema normalmente acontece quando o tamanho da página e as margens do relatório ultrapassam o tamanho da página definida nas propriedades do relatório.. A sua aplicação é desktop ou web? Se for desktop, quando você altera para o modo impressão, as páginas a mais também são geradas?
Abraço!
André Lima
Bom dia André,
Sim, as páginas extras são geradas e a aplicação é desktop.
Refiz o posicionamento conforme as dimensões do relatório e tudo funciona, exceto a exportação para PDF…hehehehe
Se eu gerar a impressão no “Microsoft Print to PDF” funciona certinho. Mas exportar para PDF não tem jeito!
Olá Marco! Que estranho hein.. Você poderia me mandar por e-mail o seu arquivo rdlc e o código exato que você está utilizando para exportar para PDF (ou você está exportando pelo próprio controle?).. Meu e-mail é: contato [arroba] andrealveslima [ponto] com [ponto] br..
Abraço!
André Lima
André, boa tarde.
Man, pelo que vi, esse exemplo você cria um relatório e insere os dados no seu carregamento, correto?
Como eu poderia fazer para exportar um relatório com dataset tipado, onde já defini todas as informações que eu preciso. No meu caso, meu report é uma proposta de prestação de serviços, com 3, 4 páginas. Eu preciso exporta-lo para o pdf para que seja enviada para os clientes via e-mail. Muito obrigado pela atenção.
Olá Rodrigo!
A parte da exportação independe da maneira que você carrega os dados no relatório.. Nesse artigo eu utilizei direto no BindingSource criado pelo Visual Studio e mais pra frente utilizei também uma lista de objetos (da classe Funcionario).. Você poderia carregar o seu relatório com o DataSet tipado sem problema algum, passando as informações através do método DataSources.Add, aí o código da exportação seria idêntico..
Tem um artigo que eu escrevi uns tempos atrás mostrando como podemos trabalhar com datasets não tipados no Report Viewer.. Nesse artigo eu alimento o relatório via código com esse dataset.. Você pode utilizar exatamente a mesma ideia, só que passando o seu dataset tipado.. Dá uma olhada e veja se te ajuda:
Passando um DataSet não tipado para o Report Viewer
Abraço!
André Lima
André, tudo bem?
Eu estou passando por um problema estranho nesse sentido.
Se eu exporto como PDF, sai normalmente.
Porém se eu exporto como Word, ele não reconhece a margem como maneira correta.
Exemplo:
João – Ele quer que funcione dessa forma, sempre desse jeito, sempre dessa maneira.
Em PDF sai:
João – Ele quer que funcione dessa forma,
sempre desse jeito, sempre dessa
maneira.
Porém, se exporto o mesmo texto em Word ou Excel ele não faz Word Wrap corretamente e fica tudo numa linha só (ficando além do fim da folha).
Imagina o que pode ser isso?
Olá Paulo!
Estranho hein.. Nunca vi esse problema.. Qual componente você está utilizando no relatório? TextBox mesmo, ou Matrix/Tablix?
Você já tentou criar um relatório em branco só com um texto que tenha word wrap para ver se o problema não está nesse relatório especificamente?
Abraço!
André Lima
Como eu faço para salvar duas paginas do report em arquivos PDF diferentes cada um com uma pagina?
Olá Luccas!
Você terá que fazer a exportação manual utilizando o método Render, como eu mostrei na seção “Exportando sem o preview” aqui desse artigo mesmo que você comentou.. Só que, além de passar o nome do formato, você terá que passar um “DeviceInfo”, que nada mais é que um XML contendo as informações de página do relatório.. Eu mostro como construir um DeviceInfo no meu vídeo / artigo sobre impressão direta do Report Viewer..
Além das informações que eu estou utilizando na construção do DeviceInfo naquele artigo (método CriarDeviceInfo), você pode também passar a página inicial e final com os atributos StartPage e EndPage.. Por exemplo, para imprimir somente da segunda para a terceira página, você poderia passar StartPage = 2 e EndPage = 3:
Abraço!
André Lima
bom dia desde já agradeço pelo conteúdo difícil de achar alguém falando sobre esse tema.
Fiz tudo da forma que você falou porém está dando um erro.
O erro acontece exatamente nessa linha:
var bytes = report.Render(formato);
A msg do erro diz somente(Ocorreu um erro durante o processamento de relatórios local.)
Acontece logo após o click do botão.
Se poder me ajudar ficarei muito grato.
Olá Jeferson!
Esse é o erro mais genérico possível que o Report Viewer retorna quando qualquer coisa dá errado na hora de renderizar o relatório.. A mensagem de erro propriamente dita fica escondida na “InnerException”.. Você já chegou a dar uma olhada no conteúdo dela?
Abraço!
André Lima
Boa tarde André,
Olhando aqui na InnerException está assim: {“A definição do relatório ‘RelatorioFuncionarios’ não foi especificada”}
mais umas linhas pra baixo tem outra inner exception que tem a seguinte msg: {“Referência de objeto não definida para uma instância de um objeto.”}
Não faço idéia o que pode ser pois eu já fiz e refiz os exemplos duas vezes
Olá Jeferson!
Que estranho hein.. Como é que ficou o seu código? Ficou idêntico ao que eu postei aqui no artigo ou você fez alguma alteração? Poderia postar para darmos uma olhada? Outra pergunta: você está trabalhando com sub-relatórios?
Abraço!
André Lima
Boa tarde, André
Estou com o mesmo erro do colega acima, quando tento setar os parâmetros, nesta linha
objRelatorio.SetParameters(objParam);
Estou usando sub-relatórios, que estão sendo carregados antes disso. Pode me ajudar?
Olá Mariana!
Estranho.. Como é que ficou o seu código (completo)?
Abraço!
André Lima
Oi, André! Tinha respondido no comentário acima, mas não consigo responder ele kkk
Então, ontem eu acabei descobrindo por acaso o que faltava… Eu não tinha passado o ReportPath com o caminho do arquivo na máquina. Passando esse parâmetro deu certo.
Obrigada mesmo assim e obrigada por compartilhar seu conhecimento em ReportViewer conosco! Você não sabe o quanto isso nos ajuda!
Olá Mariana! Que bom que deu certo a solução para esse erro no carregamento do relatório..
Abraço!
André Lima
Boa tarde, André, estou com problema na linha:
Dim Bytes = Report.Render(Formato)
Trás o seguinte erro: Referência de objeto não definida para uma instância de um objeto.
O que preciso fazer?
Agradeço!
Olá Aguinaldo!
Pela mensagem de erro, eu imagino que a variável “Report” ainda está nula neste ponto do código.. Será que você não pulou alguma parte do tutorial? Poste o seu código completo para darmos uma analisada..
Abraço!
André Lima
Bom dia André, abaixo meu código:
Private Sub BtnExportar_Click(sender As Object, e As EventArgs) Handles BtnExportarPDF.Click
Try
ExportarRelatorioPDF(“PDF”, “Cotação.pdf”)
Catch ex As Exception
Exit Sub
End Try
End Sub
Private Sub ExportarRelatorioPDF(Formato As String, NomeArquivo As String)
Try
Dim Bytes = Report.Render(Formato)
System.IO.File.WriteAllBytes(NomeArquivo, Bytes)
Dim conn As MySqlConnection
conn = New MySqlConnection
conn.ConnectionString = “server=localhost; port=3306; user id=root; password=; database=tivolli”
SQL = “Select * From Cotacao_Detalhes Where Numero_Cotacao = ” & Me.LblIdentifica.Text
Try
conn.Open()
Try
myCommand.Connection = conn
myCommand.CommandText = SQL
myAdapter.SelectCommand = myCommand
myAdapter.Fill(myData)
Dim dataSource As New Microsoft.Reporting.WinForms.ReportDataSource(“DataSet1”, myData)
Report.DataSources.Add(dataSource)
Report.ReportEmbeddedResource = “ReportViewerExport.VB.Relatorio.rdlc”
Catch myerro As MySqlException
MsgBox(“Erro de leitura no banco de dados : ” & myerro.Message)
End Try
‘MessageBox.Show(“Conexão aberta com sucesso”)
conn.Close()
Catch myerro As MySqlException
MessageBox.Show(“Erro ao conectar com o Banco de dados : ” & myerro.Message)
Finally
conn.Dispose()
End Try
Me.Report.Refresh()
Catch ex As Exception
Exit Sub
End Try
End Sub
Olá Aguinaldo, obrigado por enviar o código..
Então.. Essa variável “Report”, pelo que eu vi no código que você enviou, você não está declarando ela em lugar nenhum.. Você precisa carregar ela com o relatório que deve ser exportado.. Observe que no código de exemplo do artigo, eu seto essa variável para o relatório correspondente no evento Load do formulário:
Provavelmente é isso que está faltando no seu código..
Abraço!
André Lima
Boa tarde, André ela esta sendo declarada no escopo do form da seguinte maneira:
Private Report As Microsoft.Reporting.WinForms.LocalReport
Mas quando rodo o sistema da o erro:
Dim Bytes = Report.Render(Formato)
Trás o seguinte erro: Referência de objeto não definida para uma instância de um objeto.
Olá Aguinaldo!
Sim, ela está sendo declarada no form, mas provavelmente você esqueceu de instanciá-la (dar um “new” e setar o relatório que deve ser exportado) no evento Load do formulário.. Veja esta parte do artigo onde eu instancio e seto o relatório a ser exportado:
Abraço!
André Lima
Olá André ótimos ensinamento, show de bola. fiz e deu certinho, mais o que me ocorre é o seguinte:
Como posso alterar a pasta para onde vai o relatório gerado, gostaria de configurar para salvar em uma pasta dentro da pasta raiz do programa mesmo porem em tipo: “bin\RelatoriosGerados.
É possível?
Olá Paulo!
Se você quiser salvar em um sub-diretório dentro do diretório da aplicação, você só precisa colocar o nome da pasta antes do nome do arquivo.. Por exemplo:
A única coisa que você tem que se atentar é que essa pasta já deve estar criada antes de você tentar salvar alguma coisa dentro dela..
Abraço!
André Lima
Muito obrigado… Me salvou.
Maravilha, Paulo! Fico feliz por ter conseguido ajudar.. :)
Qualquer coisa estamos aí..
Abraço!
André Lima
Olá André! Tudo bem?
Gostaria de agradecer por este artigo! Me ajudou demais!
Você tem algum relacionado a nfe? rs
Olá Müller, obrigado pelo comentário!
Infelizmente eu não tenho material sobre NFE.. Não tenho experiência nenhuma com a geração desses tipos de documento.. :(
Mas, esse é um tema que muitas pessoas perguntam.. Se você encontrar algum material bacana, avisa aqui a gente também..
Abraço!
André Lima
Olá André!
Primeiramente, parabéns pelo blog e pela disponibilidade em compartilhar informações.
Tenho um problema e acredito que você possa me ajudar.
Estou precisando exportar um relatório para o formarto Word(.doc) sem que no Word os textos e tabelas fiquem dentro de caixas de textos. É possível ?
Abraço!
Olá Rodrigo, muito obrigado pelo comentário!
Infelizmente, até onde eu sei, não é possível controlar a maneira como os relatórios são exportados.. No caso do Word, ele vai criar TextBoxes nos lugares onde você tiver TextBox no relatório..
Mas, se você encontrar alguma maneira de customizar isso, volta aqui e conta pra gente como você conseguiu..
Abraço!
André Lima
Bom dia André.
Estou com um impasse na formatação de um relatório, exportado para Excel. Se puder me sugerir alguma solução, pode ser de grande valia.
O relatório em questão, possui uma quantidade de colunas dinâmica, as quais são definidas pelo usuário, em tempo de execução. Tentei utilizar uma Matrix, no meu RDLC, para tratar a questão das colunas dinâmicas, entretanto não obtive êxito, talvez devido a falta de conhecimento mais avançado na construção do RDLC.
Encontrei uma solução na web, onde o DataSet é transformado em um MemoryStream, e posteriormente o stream é passado para o controle ReportViewer, da seguinte forma:
RptControleReportViewerExemplo.LocalReport.LoadReportDefinition(stream);
Após isto, eu faço a exportação para Excel, usando o método Render. Desta forma, independente de quantas colunas vierem, o arquivo Excel será gerado, com todos os dados. Contudo, não existe nenhum tipo de formatação no conteúdo do arquivo. O tamanho das colunas é desproporcional, e o relatório se encontra visualmente muito ruim.
Sendo assim, você teria alguma sugestão de como eu posso formatar os dados, que são exportados? Se eu tiver controle ao menos, da formatação do nome das colunas já será útil.
Ou se conhecer outra alternativa, para criar relatórios onde as colunas são dinâmicas, pode ser que sirva.
Desde já agradeço.
Att,
Olá André!
Não sei exatamente como esse método que você está utilizando monta o relatório, mas dificilmente você conseguirá tratar a maneira como a exportação para o Excel funciona, uma vez que não existe ponto de extensibilidade relacionado a essa funcionalidade no Report Viewer..
Eu particularmente investiria mais tempo tentando montar o relatório com Matrix, dessa forma o Report Viewer tentará exportar para o Excel da maneira mais próxima possível do que estiver sendo exibido no viewer.. Você disse que tentou, mas não obteve êxito.. Qual foi o problema exatamente?
Outra opção seria montar um relatório com a quantidade máxima de colunas e esconder as que não forem necessárias através de parâmetros..
Abraço!
André Lima
André, bom dia.
Tenho o seguinte código:
codRecebimento = dgvCRecebe.CurrentRow.Cells[0].Value.ToString();
codPagto = dgvBoletos.CurrentRow.Cells[0].Value.ToString();
cliente = dgvCRecebe.CurrentRow.Cells[1].Value.ToString();
ReportViewer Rv = new ReportViewer();
ReportParameter[] Rp = new ReportParameter[2];
BindingSource Bs = new BindingSource();
ReportDataSource Rds = new ReportDataSource();
DataTable Dt = new DataTable(“BoletosDataSet”);
Rp[0] = new ReportParameter(“codrecebe”, codRecebimento);
Rp[1] = new ReportParameter(“codbolrecebe”, codPagto);
Rv.RefreshReport();
DataRow Dr = Dt.NewRow() ;
Dt.Columns.Add(“NumProposta”, typeof(string));
Dt.Columns.Add(“NomeCT”, typeof(string));
Dt.Columns.Add(“BancoCT”, typeof(string));
Dt.Columns.Add(“CNPJCT”, typeof(string));
Dt.Columns.Add(“ContaCT”, typeof(string));
Dt.Columns.Add(“DDDCT”, typeof(string));
Dt.Columns.Add(“FoneCT”, typeof(string));
Dt.Columns.Add(“EmailCT”, typeof(string));
Dt.Columns.Add(“CelularCT”, typeof(string));
Dt.Columns.Add(“NomeLograCT”, typeof(string));
Dt.Columns.Add(“BairroCT”, typeof(string));
Dt.Columns.Add(“CidadeCT”, typeof(string));
Dt.Columns.Add(“UFCT”, typeof(string));
Dt.Columns.Add(“NomeFanCT”, typeof(string));
Dt.Columns.Add(“NumCT”, typeof(string));
Dt.Columns.Add(“ComplementoCT”, typeof(string));
Dt.Columns.Add(“CepCT”, typeof(string));
Dt.Columns.Add(“NomeServico”, typeof(string));
Dt.Columns.Add(“NomeCliente”, typeof(string));
Dt.Columns.Add(“CnpjCliente”, typeof(string));
Dt.Columns.Add(“CodDDD”, typeof(string));
Dt.Columns.Add(“FoneCliente”, typeof(string));
Dt.Columns.Add(“NumeroCliente”, typeof(string));
Dt.Columns.Add(“NomeContato”, typeof(string));
Dt.Columns.Add(“NomeLogra”, typeof(string));
Dt.Columns.Add(“Bairro”, typeof(string));
Dt.Columns.Add(“Cidade”, typeof(string));
Dt.Columns.Add(“UF”, typeof(string));
Dt.Columns.Add(“EmailCliente”, typeof(string));
Dt.Columns.Add(“RazSocialCliente”, typeof(string));
Dt.Columns.Add(“ComplementoCliente”, typeof(string));
Dt.Columns.Add(“Origem”, typeof(string));
Dt.Columns.Add(“Vencimento”, typeof(string));
Dt.Columns.Add(“Valor”, typeof(double));
Dt.Columns.Add(“IDBoleto”, typeof(string));
Dt.Columns.Add(“NumParcela”, typeof(string));
Dt.Columns.Add(“NumBoleto”, typeof(string));
Dt.Columns.Add(“RazSocial”, typeof(string));
Dt.Columns.Add(“NomeBanco”, typeof(string));
Dt.Columns.Add(“CondPagto”, typeof(string));
Dt.Columns.Add(“StatusBoleto”, typeof(string));
Dt.Rows.Add(Dr);
Bs.DataSource = Dt;
Rds.Name = Dt.TableName;
Rds.Value = Bs.DataSource;
Rv.ProcessingMode = ProcessingMode.Local;
Rv.LocalReport.ReportPath = @”C:\Dropbox\QualitowersERP\ControleEstoque\Reports\rptDocCobranca.rdlc”;
Rv.LocalReport.SetParameters(Rp);
Rv.LocalReport.DataSources.Add(Rds);
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
byte[] bytes = Rv.LocalReport.Render(
“Pdf”, null, out mimeType, out encoding,
out extension,
out streamids, out warnings);
Meu relatório exporta em branco. Adicionei os parâmetros no report. Na query que gera os dados para o relatório, eu já tentei com os parâmetros e sem e mesmo assim não funciona.
Peguei este código pronto, porém, na página informa que é necessário setar o DataSet, mas mesmo setando, o código não faz referência ao DS.
Olá Rodrigo!
Estranho hein.. Ele exporta completamente em branco (a página toda em branco)? Ou pelo menos as partes fixas do relatório são exportadas corretamente? Você já tentou exibir esse relatório no viewer utilizando o mesmo código, ao invés de exportá-lo? Só para ver se o problema está no código ou na exportação..
Abraço!
André Lima
Olá André!
Não tentei não. O relatório já tem um DataSet.
Ele exporta, somente as partes fixas, ou seja, somente o layout do documento, sem os dados.
Olá Rodrigo!
Que estranho.. Se o relatório aparece com as partes fixas, então, não deve ser problema na exportação.. Como é que está o seu relatório exatamente? Você está exibindo as informações dos parâmetros ou do DataSet? Está utilizando um controle List, Matrix, Tablix? Está com algum filtro configurado?
Abraço!
André Lima
Bom dia André.
Consegui resolver da seguinte maneira.
Criei uma query que busca os mesmos dados da query que gera o relatório, aí, passo o resultado desta query para os DataRows, ficando parecido com isso:
private void ExportaDocCobranca()
{
codRecebimento = dgvCRecebe.CurrentRow.Cells[0].Value.ToString();
codPagto = dgvBoletos.CurrentRow.Cells[0].Value.ToString();
cliente = dgvCRecebe.CurrentRow.Cells[1].Value.ToString();
enderecoArquivo = @”C:\Dropbox\Qualitowers\Cobrança\Informativo Financeiro-” + cliente + “-” + codRecebimento + “-” + codPagto + “.pdf”;
if (!System.IO.File.Exists(enderecoArquivo))
{
dto.CodRecebe = codRecebimento;
dto.NumDocumento = codPagto;
bll.EmiteBoleto(dto);
ReportViewer Rv = new ReportViewer();
ReportParameter[] Rp = new ReportParameter[2];
BindingSource Bs = new BindingSource();
ReportDataSource Rds = new ReportDataSource(“QualitowersDataSet.qryGeraBoleto”);
DataTable Dt = new DataTable(“BoletosDataSet”);
DataSet ds = new DataSet(“QualitowersDataSet.xsd”);
DataRow Dr = Dt.NewRow();
Rp[0] = new ReportParameter(“codrecebe”, codRecebimento);
Rp[1] = new ReportParameter(“codbolrecebe”, codPagto);
Rv.RefreshReport();
Dt.Columns.Add(“NumProposta”, typeof(string));
Dt.Columns.Add(“NomeCT”, typeof(string));
Dt.Columns.Add(“BancoCT”, typeof(string));
Dt.Columns.Add(“CNPJCT”, typeof(string));
Dt.Columns.Add(“ContaCT”, typeof(string));
Dt.Columns.Add(“DDDCT”, typeof(string));
Dt.Columns.Add(“FoneCT”, typeof(string));
Dt.Columns.Add(“EmailCT”, typeof(string));
Dt.Columns.Add(“CelularCT”, typeof(string));
Dt.Columns.Add(“NomeLograCT”, typeof(string));
Dt.Columns.Add(“BairroCT”, typeof(string));
Dt.Columns.Add(“CidadeCT”, typeof(string));
Dt.Columns.Add(“UFCT”, typeof(string));
Dt.Columns.Add(“NomeFanCT”, typeof(string));
Dt.Columns.Add(“NumCT”, typeof(string));
Dt.Columns.Add(“ComplementoCT”, typeof(string));
Dt.Columns.Add(“CepCT”, typeof(string));
Dt.Columns.Add(“NomeServico”, typeof(string));
Dt.Columns.Add(“NomeCliente”, typeof(string));
Dt.Columns.Add(“CnpjCliente”, typeof(string));
Dt.Columns.Add(“CodDDD”, typeof(string));
Dt.Columns.Add(“FoneCliente”, typeof(string));
Dt.Columns.Add(“NumeroCliente”, typeof(string));
Dt.Columns.Add(“NomeContato”, typeof(string));
Dt.Columns.Add(“NomeLogra”, typeof(string));
Dt.Columns.Add(“Bairro”, typeof(string));
Dt.Columns.Add(“Cidade”, typeof(string));
Dt.Columns.Add(“UF”, typeof(string));
Dt.Columns.Add(“EmailCliente”, typeof(string));
Dt.Columns.Add(“RazSocialCliente”, typeof(string));
Dt.Columns.Add(“ComplementoCliente”, typeof(string));
Dt.Columns.Add(“Origem”, typeof(string));
Dt.Columns.Add(“Vencimento”, typeof(DateTime));
Dt.Columns.Add(“Valor”, typeof(double));
Dt.Columns.Add(“IDBoleto”, typeof(string));
Dt.Columns.Add(“NumParcela”, typeof(string));
Dt.Columns.Add(“NumBoleto”, typeof(string));
Dt.Columns.Add(“RazSocial”, typeof(string));
Dt.Columns.Add(“NomeBanco”, typeof(string));
Dt.Columns.Add(“CondPagto”, typeof(string));
Dt.Columns.Add(“StatusBoleto”, typeof(string));
Dt.Rows.Add(Dr);
Dr[“NumProposta”] = dto.NumProposta;
Dr[“NomeCT”] = dto.NomeCT;
Dr[“BancoCT”] = dto.BancoCT;
Dr[“CNPJCT”] = dto.CnpjCT;
Dr[“ContaCT”] = dto.ContaCT;
Dr[“DDDCT”] = dto.DDDCT;
Dr[“FoneCT”] = dto.FoneCT;
Dr[“EmailCT”] = dto.EmailCT;
Dr[“CelularCT”] = dto.CelularCT;
Dr[“NomeLograCT”] = dto.NomeLograCT;
Dr[“BairroCT”] = dto.BairroCT;
Dr[“CidadeCT”] = dto.CidadeCT;
Dr[“UFCT”] = dto.UFCT;
Dr[“NomeFanCT”] = dto.NomeFanCT;
Dr[“NumCT”] = dto.NumCT;
Dr[“ComplementoCT”] = dto.ComplementoCT;
Dr[“CepCT”] = dto.CepCT;
Dr[“NomeServico”] = dto.NomeServico;
Dr[“NomeCliente”] = dto.NomeCliente;
Dr[“CnpjCliente”] = dto.CnpjCliente;
Dr[“CodDDD”] = dto.CodDDD;
Dr[“FoneCliente”] = dto.FoneCliente;
Dr[“NumeroCliente”] = dto.NumeroCliente;
Dr[“NomeContato”] = dto.NomeContato;
Dr[“NomeLogra”] = dto.NomeLogra;
Dr[“Bairro”] = dto.Bairro;
Dr[“Cidade”] = dto.Cidade;
Dr[“UF”] = dto.UF;
Dr[“EmailCliente”] = dto.EmailCliente;
Dr[“RazSocialCliente”] = dto.RazSocialCliente;
Dr[“ComplementoCliente”] = dto.ComplementoCliente;
Dr[“Origem”] = dto.Origem;
Dr[“Vencimento”] = String.Format(“{0:d}”, dto.Vencimento);
Dr[“Valor”] = double.Parse(dto.Valor);
Dr[“IDBoleto”] = dto.IDBoleto;
Dr[“NumParcela”] = dto.NumParcela;
Dr[“NumBoleto”] = dto.NumBoleto;
Dr[“RazSocial”] = dto.Razaosocial;
Dr[“NomeBanco”] = dto.NomeBanco;
Dr[“CondPagto”] = dto.CondPagto;
Dr[“StatusBoleto”] = dto.StatusBoleto;
Bs.DataSource = Dt;
Rds.Name = Dt.TableName;
Rds.Value = Bs.DataSource;
Rv.ProcessingMode = ProcessingMode.Local;
Rv.LocalReport.ReportPath = @”C:\Dropbox\QualitowersERP\ControleEstoque\Reports\rptDocCobranca.rdlc”;
Rv.LocalReport.SetParameters(Rp);
Rv.LocalReport.DataSources.Add(Rds);
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
byte[] bytes = Rv.LocalReport.Render(
“Pdf”, null, out mimeType, out encoding,
out extension,
out streamids, out warnings);
FileStream fs = new FileStream(enderecoArquivo, FileMode.Create);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
}
}
Fiz isso com todas as colunas da query e na hora de exportar, gerou o relatório perfeitamente.
Um pouco trabalhoso devido à quantidade de colunas que tem esta query (42), mas consegui resolver dessa maneira.
Em todo caso, muito obrigado pela atenção e espero contribuir de alguma maneira.
Olá Rodrigo!
Legal.. O que importa é que você conseguiu resolver o problema no final das contas.. :)
Obrigado por ter compartilhado a solução aqui..
Abraço!
André Lima