André Alves de Lima

Talking about Software Development and more…

Quebra de página condicional no Report Viewer

O conceito de quebra de páginas no desenvolvimento de relatórios é algo básico a ser dominado. É rara a situação em que um relatório ocupa somente uma página, principalmente quando falamos de relatórios mais complexos. O que pode ser algo muito básico pode se tornar um pesadelo para os desenvolvedores que utilizam o Report Viewer como ferramenta de relatórios. Isso porque não é tão simples e muito menos intuitivo criarmos uma quebra de página condicional no Report Viewer. Mas, não se preocupe. No artigo de hoje eu vou desmistificar esse tema para você.

Relatório sem quebra de páginas

Quando criamos um relatório no Report Viewer, por padrão, ele não tem quebra de página customizada. Ou seja, as informações serão impressas na primeira página e, somente quando não tiver mais espaço na primeira página é que o Report Viewer quebrará o relatório em uma segunda página, e assim por diante.

Para conseguirmos entender o conceito de quebra de páginas, vamos criar um relatório bem simples utilizando um projeto do tipo “Windows Forms Application“. Como eu costumo dizer, poderíamos utilizar outros tipos de projeto (WPF, Web Forms, MVC), mas, escolhi o Windows Forms por ser mais simples.

Vamos supor que nós temos um sistema que gerencia livros. O nosso relatório mostrará uma lista dos livros cadastrados no sistema. Dessa forma, a primeira coisa que temos que fazer é criarmos uma nova classe, chamada “Livro“. Mais para frente, o nosso relatório receberá uma lista de instâncias dessa classe, que será justamente a fonte de dados do relatório:

    // C#
    public class Livro
    {
        public int ID { get; set; }
        public string Nome { get; set; }
        public string GeneroLiterario { get; set; }
        public string TipoGeneroLiterario { get; set; }
    }
' VB.NET
Public Class Livro
    Public Property ID As Integer
    Public Property Nome As String
    Public Property GeneroLiterario As String
    Public Property TipoGeneroLiterario As String
End Class

Uma vez adicionada a classe, compile o projeto. Esse é um passo muito importante, uma vez que, caso esqueçamos de compilar o projeto antes de criarmos o relatório, o mecanismo do Report Viewer não reconhecerá essa classe.

Com o projeto compilado, vamos adicionar um novo relatório do Report Viewer, dando o nome de “RelatorioListaLivros” para esse novo relatório. Dentro do relatório, adicione uma nova Table. Quando adicionamos uma Table no relatório, o Report Viewer perguntará informações sobre a fonte de dados que deverá ser utilizada para alimentar essa Table. No nosso caso, vamos criar uma nova fonte de dados do tipo “Object Data Source“:

Na próxima tela, encontre a classe “Livro” e conclua o assistente:

Em seguida, dê o nome de “DataSetLivro” para o DataSet que será criado:

Por fim, arraste os campos do DataSet para dentro das colunas da Table, de forma que o relatório fique parecido com a imagem abaixo:

Nada demais, não é mesmo? Vamos exibir esse relatório em tempo de execução para conferirmos o resultado? Para isso, abra o designer do formulário e arraste um controle do Report Viewer para dentro dele. Na smart tag do controle, escolha o relatório que acabamos de criar e, no code-behind do formulário, vamos passar uma lista de livros como fonte de dados do relatório:

        // C#
        private void FormRelatorio_Load(object sender, EventArgs e)
        {
            var livros = new List<Livro>();
            livros.Add(new Livro() { ID = 1, Nome = "Ilíada", GeneroLiterario = "Epopéia", TipoGeneroLiterario = "Narrativo" });
            livros.Add(new Livro() { ID = 2, Nome = "A divina comédia", GeneroLiterario = "Epopéia", TipoGeneroLiterario = "Narrativo" });
            livros.Add(new Livro() { ID = 3, Nome = "Memórias póstumas de Brás Cubas", GeneroLiterario = "Romance", TipoGeneroLiterario = "Narrativo" });
            livros.Add(new Livro() { ID = 4, Nome = "Macunaíma", GeneroLiterario = "Romance", TipoGeneroLiterario = "Narrativo" });
            livros.Add(new Livro() { ID = 5, Nome = "Morte e vida Severina", GeneroLiterario = "Poesia", TipoGeneroLiterario = "Lírico" });
            livros.Add(new Livro() { ID = 6, Nome = "As vespas", GeneroLiterario = "Comédia", TipoGeneroLiterario = "Dramático" });
            livros.Add(new Livro() { ID = 7, Nome = "O misantropo", GeneroLiterario = "Comédia", TipoGeneroLiterario = "Dramático" });
            livros.Add(new Livro() { ID = 8, Nome = "Auto da compadecida", GeneroLiterario = "Drama", TipoGeneroLiterario = "Dramático" });
            this.reportViewer1.LocalReport.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource("DataSetLivro", livros));

            this.reportViewer1.RefreshReport();
        }
    ' VB.NET
    Private Sub FormRelatorio_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim Livros As New List(Of Livro)
        Livros.Add(New Livro() With {.ID = 1, .Nome = "Ilíada", .GeneroLiterario = "Epopéia", .TipoGeneroLiterario = "Narrativo"})
        Livros.Add(New Livro() With {.ID = 2, .Nome = "A divina comédia", .GeneroLiterario = "Epopéia", .TipoGeneroLiterario = "Narrativo"})
        Livros.Add(New Livro() With {.ID = 3, .Nome = "Memórias póstumas de Brás Cubas", .GeneroLiterario = "Romance", .TipoGeneroLiterario = "Narrativo"})
        Livros.Add(New Livro() With {.ID = 4, .Nome = "Macunaíma", .GeneroLiterario = "Romance", .TipoGeneroLiterario = "Narrativo"})
        Livros.Add(New Livro() With {.ID = 5, .Nome = "Morte e vida Severina", .GeneroLiterario = "Poesia", .TipoGeneroLiterario = "Lírico"})
        Livros.Add(New Livro() With {.ID = 6, .Nome = "As vespas", .GeneroLiterario = "Comédia", .TipoGeneroLiterario = "Dramático"})
        Livros.Add(New Livro() With {.ID = 7, .Nome = "O misantropo", .GeneroLiterario = "Comédia", .TipoGeneroLiterario = "Dramático"})
        Livros.Add(New Livro() With {.ID = 8, .Nome = "Auto da compadecida", .GeneroLiterario = "Drama", .TipoGeneroLiterario = "Dramático"})
        Me.ReportViewer1.LocalReport.DataSources.Add(New Microsoft.Reporting.WinForms.ReportDataSource("DataSetLivro", Livros))

        Me.ReportViewer1.RefreshReport()
    End Sub

Execute o projeto e veja o resultado:

Nota: me perdoe se os gêneros literários desse exemplo estiverem errados. Tudo o que eu lembro de literatura é o que eu estudei no colegial, lá por volta do ano 2000.

Agora você deve estar pensando: “OK, André, esse tipo de relatório eu estou cansado de fazer. Como é que eu faço a quebra de página baseada em uma regra de negócio? Não era isso que você ia mostrar nesse artigo?“.

Calma! Não se estresse. Acompanhe logo abaixo alguns tipos de quebra condicional que você pode adicionar nos seus relatórios do Report Viewer.

Quebrando página a cada N registros

O primeiro tipo de quebra condicional que eu quero mostrar neste artigo é a quebra de página a cada “N” registros. Tomando como base o nosso exemplo, vamos supor que nós queiramos mostrar somente quatro livros por página. Como é que nós fazemos isso?

Como o Report Viewer não suporta a definição de uma expressão para quebra de páginas, a alternativa é criarmos um agrupamento baseado na expressão desejada e, em seguida, configurarmos a quebra de página entre instâncias desse agrupamento. Pareceu complicado? Não se preocupe. Até que é bem simples, veja só.

Em primeiro lugar, vamos adicionar um agrupamento no relatório. Para isso, vamos até a janela de “Row Groups“, clicamos no dropdown dos detalhes e escolhemos a opção “Add Group => Parent Group“:

E é na próxima tela que mora todo o segredo. Na tela de criação de agrupamentos, temos que clicar no botão “fx” para configurarmos a expressão que será utilizada para fazer a quebra de página:

A expressão para quebrarmos a página a cada 4 registros seria a seguinte:

=Math.Ceiling(RowNumber(Nothing) / 4)

Note que estamos utilizando a função RowNumber passando “Nothing“, que retornará o número do registro considerando o DataSet como um todo. Se quiséssemos o número da linha considerando um agrupamento, teríamos que passar o nome do agrupamento como parâmetro para a função RowNumber.

Além disso, estamos utilizando também a função Math.Ceiling, que retorna o inteiro mais próximo acima do valor passado. Essa função é tipo um arredondamento forçado para cima. Dessa forma, na primeira linha, teremos RowNumber 1 dividido por 4, resultando em 0,25, arredondado para cima = 1. O resultado será o mesmo para as linhas de 1 até 4. A partir da linha 5, o resultado começa a ser 2 (5 / 4 = 1,25 => arredondado para cima = 2). Com isso, teremos um valor em comum entre as linhas que queremos agrupar.

Um pequeno detalhe é que, após a criação do grupo, o Report Viewer criará automaticamente uma coluna na tabela com o seu valor. Essa coluna pode ser excluída, porém, temos que tomar cuidado para excluirmos somente a coluna (e não o agrupamento):

Agora só falta configurarmos a quebra de página entre as instâncias do grupo e nós teremos o resultado esperado. Para configurarmos a quebra de página, temos que ir até as propriedades do agrupamento e, dentro da categoria “Page Breaks“, temos que marcar a opção “Between each instance of a group“:

Pronto! Tente executar o projeto e receba este belo erro de compilação:

A sort expression for tablix ‘Tablix1’ uses the RowNumber function. RowNumber cannot be used in sort expressions.

Esse erro acontece porque, quando criamos um agrupamento no Report Viewer, ele automaticamente configura a expressão correspondente ao agrupamento como a sua expressão de ordenação. Porém, nesse caso, como estamos utilizando a função RowNumber, nós não podemos utilizar essa expressão na ordenação do agrupamento. Dessa forma, temos que ir até as propriedades do grupo e, dentro da categoria “Sorting“, temos que excluir a expressão de ordenação:

Agora sim! Execute o projeto e veja o resultado:

Como você pode perceber, agora temos quatro registros por página. Obviamente, para o layout ficar completo, teríamos que mover a linha de cabeçalho para dentro do cabeçalho do grupo (para que a linha de cabeçalho seja repetida em todas as páginas).

Quebra de página baseada em uma expressão customizada

Da mesma forma que configuramos uma expressão para quebrarmos a página a cada “N” registros, nós podemos configurar qualquer expressão que quisermos para controlarmos a quebra de página. Por exemplo, digamos que nós precisemos quebrar o relatório em livros do tipo “Dramáticos” e “Não Dramáticos” (livros dramáticos em uma página e livros não dramáticos em outra página). Nesse caso, nós poderíamos seguir o mesmo processo, só que utilizando a seguinte expressão:

=IIf(Fields!TipoGeneroLiterario.Value = "Dramático", 1, 0)

E o resultado seria o seguinte:

Ativando ou desativando a quebra de página

Por fim, existe aquela famosa situação em que alguns clientes querem o relatório com a quebra de página e outros clientes querem o relatório sem a quebra de página. Como fazer nesse caso? Criar duas versões do relatório, uma com quebra e outra sem quebra? É claro que não! Nós podemos utilizar um parâmetro para controlar se a quebra de página está ativa ou não!

Para isso, primeiramente temos que criar um novo parâmetro no nosso relatório. Vamos chamar esse parâmetro de “AtivaQuebra“, configurando o tipo “Boolean” e a opção “Allow null value“:

Em seguida, temos que clicar no agrupamento (na janela “Row Groups“) e, na janela de propriedades, temos que navegar até a propriedade “Group => Page Break => Disabled” para configurarmos uma expressão para essa propriedade:

A expressão para essa propriedade deve ser a seguinte:

=Not Parameters!AtivaQuebra.Value

Após essa alteração, a quebra de páginas customizada só estará ativa caso nós passemos o valor “True” para esse parâmetro antes de exibirmos o relatório, caso contrário a quebra de páginas será ignorada. Isso pode ser feito no code-behind do formulário, antes da chamada de “RefreshReport“:

            // C#
            // Se comentarmos a linha abaixo, a quebra de páginas customizada será ignorada.
            this.reportViewer1.LocalReport.SetParameters(new Microsoft.Reporting.WinForms.ReportParameter("AtivaQuebra", "True"));
            this.reportViewer1.RefreshReport();
        ' VB.NET
        ' Se comentarmos a linha abaixo, a quebra de páginas customizada será ignorada.
        Me.ReportViewer1.LocalReport.SetParameters(New Microsoft.Reporting.WinForms.ReportParameter("AtivaQuebra", "True"))
        Me.ReportViewer1.RefreshReport()

Concluindo

Quebra de página condicional no Report Viewer é algo nada intuitivo, mas, totalmente possível de ser feito. Através de criação de grupos com expressões customizadas, podemos criar quebras de páginas com qualquer regra de negócio que desejarmos. Nesse artigo você conferiu como quebrar o relatório a cada “N” registros, como configurar a quebra de páginas com expressões customizadas e como fazer para ativar ou desativar a quebra de página através de parâmetros.

E você, já precisou configurar uma quebra de página condicional no Report Viewer? Qual era a situação em que você teve que criar essa quebra de página customizada? Funcionou direitinho através da criação de agrupamentos? Conte-nos mais detalhes na caixa de comentários.

Por fim, convido você a inscrever-se na minha newsletter. Ao fazer isso, 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 logo abaixo.

Até a próxima!

André Lima

Image by Pixabay used under Creative Commons
https://pixabay.com/en/calculator-calculation-insurance-1044173/

Newsletter do André Lima

* indicates required



Powered by MailChimp

77 thoughts on “Quebra de página condicional no Report Viewer

  • Glauco Moro disse:

    Como sempre excelente artigo! Parabéns!

  • Luiz Eugênio disse:

    Bom dia André, estou com a seguinte dúvida, estou tentando gerar um relatório onde eu tenho 2 agrupamentos em linha, por RECIBO e por VIA do recibo (mais o Details), que fica assim:
    ->Via
    ->->Recibo
    ->->->Details
    Ou seja, cada via do recibo tem seus dados, mais os dados dos recibos, e, caso eu queira imprimir duas vias, tudo se repete.
    O problema é o seguinte, quando dão duas vias, se couber em uma página deve ficar, porém se for quebrar na última linha, então toda a segunda via deve quebrar para outra página. Não gostaria de deixar sempre uma quebra após encerrar o agrupamento VIA, pois mesmo que as duas caibam na mesma folha irá quebrar igual. Não estou conseguindo aplicar a fórmula de contador de linhas, achas que é funcional neste meu caso usar essa lógica de quebra de páginas usando contador de linhas?

    • andrealveslima disse:

      Olá Luiz!

      Acho que, se você souber exatamente o limite de registros cuja quebra de página não é necessária, esse esquema da quebra de página condicional serviria certinho para o seu relatório (seção “Quebrando página a cada N registros” que eu apresentei no meu artigo).. Você tentou implementar dessa forma e não funcionou? O que aconteceu? Você recebeu um erro ou coisa parecida?

      Se você quiser me mandar por e-mail o seu arquivo rdlc para eu dar uma olhada, fique à vontade.. O endereço é contato [arroba] andrealveslima [ponto] com [ponto] br..

      Abraço!
      André Lima

      • Luiz Eugênio disse:

        A princípio eu saberia sim a cada quantos registros necessitaria a quebra, o problema neste caso é que por exemplo, tenho três vias, cada uma tem um agrupamento de recibo e o recibo por si tem 7 títulos. Em uma página cabem duas vias com um recibo e 7 títulos. Se tiverem 8 títulos, então cada via deve aparecer em uma página. Tentei fazer um agrupamento por fora da via contando as linhas e quando chegasse em x mandaria quebrar, mas simplesmente nada acontecia.

        Acabei fazendo de outro modo, não 100% ortodoxo. Joguei a tabela inteira dentro de outra tabela com agrupamento por via com apenas uma linha e uma coluna, quando existe mais que uma via e a junção de duas na mesma página excede o tamanho da mesma, ocorre a quebra logo após a primeira via, então acabei conseguindo a quebra que eu queria.

        Mesmo assim, agradeço seu desprendimento de tempo e atenção pela minha dúvida. Estou inscrito e seu site está em meus favoritos, não tenha dúvida que aparecerei com perguntas novamente.

        Abraço.

        • andrealveslima disse:

          Olá Luiz!

          Entendi.. Que probleminha sinistro, hein? Realmente tem que dar uma boa estudada para resolver com quebra a cada X linhas.. Mas, fico feliz que você tenha conseguido resolver dessa outra maneira com a tabela dentro de outra tabela.. Não tinha pensado nessa alternativa..

          Enfim, se surgirem outras dúvidas, pode ficar a vontade.. Entre em contato aqui ou por e-mail..

          Abraço!
          André Lima

  • Edward Gómez disse:

    Buen día André,

    Excelente explicación y muy útil me ha sido de mucha utilidad.

    Saludos desde Colombia.

    • andrealveslima disse:

      Olá Edward!

      Muito obrigado pelo comentário! Fico feliz que o conteúdo do artigo tenha sido de muita utilidade nos seus projetos.. :)

      Abraço!
      André Lima

  • GALBAS PORTES disse:

    Olá Andre!
    Tenho um problema mais complicado. Meu report tem várias linhas e várias colunas, ou seja, pode estourar o tamanho da página na largura e na altura. Gostaria de colocar uma quebra de páginas baseada no número de colunas. É possível? Se sim, isso pode ser feito no código VB.NET ou preciso fazer com uma expressão no report?
    Obrigado.

    • andrealveslima disse:

      Olá Galbas!

      Não entendi exatamente o layout do seu relatório e qual é a lógica que você está querendo fazer para quebrar a página.. Você poderia talvez enviar uns screenshots para entendermos melhor o seu relatório? Se possível, me mande o seu arquivo rdlc e mais informações sobre a quebra de página que você está querendo fazer..

      Abraço!
      André Lima

      • GALBAS PORTES disse:

        Bom dia André!
        Imagine que posso ter de 1 a 100 colunas de resultados e de 1 a 1000 linhas.
        A visibilidade das colunas são setadas através de parâmetros. Esses parâmetros são passados via código em VB.NET
        Tenho dois problemas:
        1. Como fazer a quebra de página a cada 10 colunas por exemplo?
        2. Aparentemente mesmo que as colunas sejam invisíveis, é acrescentado uma nova página em branco.

        Como posso enviar anexos neste blog?
        Obrigado,
        Galbas

        • andrealveslima disse:

          Olá Galbas!

          Teoricamente você precisaria utilizar as informações dos parâmetros que você está mandando para o relatório.. Mas isso depende muito de como você está estruturando o relatório..

          Não dá para mandar anexos aqui pelo blog, mas você pode me mandar direto por e-mail: contato [arroba] andrealveslima [ponto] com [ponto] br..

          Abraço!
          André Lima

          • GALBAS PORTES disse:

            Bom dia André!
            Lhe enviei o rdlc por email.
            Obrigado.

          • andrealveslima disse:

            Olá Galbas!

            Dei uma olhada no seu relatório e estou começando a entender melhor.. Você tem as 48 colunas dinâmicas que são exibidas caso o parâmetro correspondente seja diferente de uma string vazia..

            Só não entendi o quê você quer fazer de especial com a quebra de página.. Como é que você gostaria que o relatório fosse exibido? Por exemplo, digamos que as 48 colunas estejam sendo exibidas, como é que você imaginou a quebra de página nesse cenário? E quando tiver 20 colunas ativas?

            Abraço!
            André Lima

          • GALBAS PORTES disse:

            Bom dia André!
            Obrigado pela resposta.
            O problema é quando o número de linhas ultrapassa o tamanho da página. Eu gostaria de poder definir o número de colunas em uma página e com quantas linhas vai ficar.
            Você reparou que no relatório na folha 1 tem um gráfico e abaixo os resultados? Quando imprime a segunda página os resultados são impressos na mesma posição da primeira página, ou seja, deslocados para o meio da página. Eu gostaria de ter o controle sobre isso também. Acho que se resolver o problema da quebra de página por colunas isso será solucionado.
            Obrigado.

          • andrealveslima disse:

            Olá Galbas!

            Que complexo hein.. Infelizmente eu não sei exatamente como eu resolveria esse problema.. As quebras de página são feitas por linhas, e não por colunas..

            O que eu talvez tentaria fazer é criar várias tables somente com a quantidade máxima de colunas que você quer por página, adicionando quebra de página entre cada tabela.. Digamos que você quer somente 6 colunas por página e que você tenha 20 possíveis colunas no total.. Nesse caso você teria 4 tables (três com 6 colunas e uma com as 2 últimas colunas restantes).. Aí você exibiria em cada table as somentes colunas correspondentes (na primeira table as 6 primeiras colunas, na segunda table as próximas 6 colunas, e por aí vai)..

            Entendeu mais ou menos a ideia?

            Abraço!
            André Lima

          • GALBAS PORTES disse:

            Bom dia André!
            Obrigado pela resposta.
            Se eu conseguir avançar com suas dicas lhe darei um retorno.
            Obrigado.

          • andrealveslima disse:

            Beleza Galbas.. Fico no aguardo!

            Abraço!
            André Lima

  • Luis Fernando Beniti disse:

    Boa tarde, André!!!

    Estou com problema na quebra de um relatório tipo Contrato (um texto grande), ele não imprime nenhuma linha na primeira página e joga o texto na segunda.
    Este texto grande vem de um campo da tabela que jogo em um textbox.

    • andrealveslima disse:

      Olá Luis!

      Como é que está o layout do seu relatório? Esse campo está dentro de um Tablix ou é um TextBox direto no relatório? Será que você poderia me mandar um screenshot do relatório para eu tentar entender direito o que está acontecendo? Pode ser por e-mail: contato [arroba] andrealveslima [ponto] com [ponto] br

      Abraço!
      André Lima

  • Luis Fernando Beniti disse:

    Desculpe, mandei a mensagem sem dizer um Obrigado e perguntar se você tem alguma ideia de onde posso mudar para que ele passe a imprimir algumas linhas na página 1 e só depois termine na 2.
    Obrigado desde já.

    • andrealveslima disse:

      Magina Luis, sem problema.. Dá uma olhada lá na resposta que eu acabei de postar.. Fico no aguardo..

      Abraço!
      André Lima

    • andrealveslima disse:

      Olá Fernando!

      Obrigado por enviar mais informações no meu e-mail.. Acho que consegui entender o problema agora.. Acredito que, caso você configure como “False” a propriedade KeepTogether tanto do TextBox quanto da linha do componente List, as informações serão exibidas como você está esperando..

      Quando essa propriedade é configurada como “True” (que é o padrão), o Report Viewer tenta manter todo o conteúdo da linha em uma mesma página.. Nesse seu caso, isso só é possível se o Report Viewer adicionar uma quebra de página..

      Tenta aí e depois me avisa se deu certo..

      Abraço!
      André Lima

  • Frederico Simões disse:

    Olá André,

    Como sempre vem superando as nossas expectativas no conteúdo didático. Muito bom o artigo e a forma como ensina. Muito obrigado como sempre. Tenho aprendido muito com você.

    Poderia me ajudar mais uma vez? No ReportViewer é possível fazer algo do tipo: Dimensionar, ou melhor, ajustar o percentual da página em relação ao seu tamanho normal? No Excel por exemplo para ganhar mais espaço, temos essa opção para dimensionar a página. No ReportViewer existe algo parecido?

    Às vezes preciso de mais espaço na minha página em A4 e não sei o que fazer. Você já se deparou com essa necessidade? Como fez para resolver esse problema?

    Agradeço antecipadamente mais uma vez por sua colaboração em ajudar.

    • andrealveslima disse:

      Olá Frederico! Muito obrigado pelo comentário e pelo elogio! :)

      Isso é realmente um negócio chato do Report Viewer.. Que eu saiba, não existe uma maneira de redimensionar o relatório fazendo com que ele caiba na página na hora de imprimir (como no Excel que você mencionou)..

      O que eu faço normalmente é definir o tamanho da página e margens (A4, por exemplo) e só trabalhar com aquele espaço horizontal que o Report Viewer me dá, sem aumentar a área de design.. Se necessário, eu diminuo a fonte das células do Tablix para que as colunas caibam no espaço disponível.. Infelizmente, um trabalho bem manual.. :(

      Se você descobrir uma maneira mais fácil, volta aqui e avisa a gente, OK?

      Abraço!
      André Lima

      • Frederico disse:

        Olá André.

        Muito obrigado pelo retorno. Só recorri aos universitários por que já estava cansado de procurar na internet e não achar nada a respeito. Mas enfim, acho que o negócio é ter paciência e muita criatividade para colocar muita informação é um único espaço. :(

        Muito obrigado pelo retorno. Se souber de alguma coisa relacionado ao assunto, pode deixar que retornarei aqui no site e post a solução.

        Um grande abraço.

        • andrealveslima disse:

          Magina, Frederico! Se eu descobrir uma alternativa melhor eu te aviso também.. Coloquei aqui na minha lista para dar uma pesquisada mais detalhada quando encontrar um tempinho..

          Abraço!
          André Lima

  • GALBAS PORTES disse:

    Bom dia André!
    Continuo na luta com meu relatório. Você pode me informar como faço a quebra de paginas com a seguinte condição:
    Meu relatório tem um gráfico e 100 registros. Eu gostaria de colocar o gráfico na primeira página juntamente com 15 registros e nas demais páginas os outros 85 registros. A partir da página 2, vou imprimir 35 registros por página.
    Uma coisa estranha que está acontecendo é que sempre na quebra da pagina,esta sendo inserida uma nova em branco somente com o cabeçalho.
    Você pode me ajudar?
    Obrigado

    • andrealveslima disse:

      Olá Galbas!

      Não é tão difícil fazer a quebra dessa maneira.. Você só precisa de um identificador distinto para os primeiros 15 registros e outro identificador distinto para cada um dos 35 registros subsequentes.. Por exemplo, você poderia utilizar esta expressão no seu agrupamento:

      =IIf(RowNumber(Nothing) <= 15, 0, Math.Ceiling((RowNumber(Nothing) - 15) / 35))
      

      Preparei um projetinho de exemplo que você pode baixar através deste link:

      https://www.dropbox.com/s/8tmameouwx830pn/WindowsFormsApplication29.zip?dl=0

      Abraço!
      André Lima

      • GALBAS PORTES disse:

        Obrigado André! Funcionou perfeitamente conforme você informou. Para variar, agora tenho outro problema. Estou fazendo a estatística de todos valores das colunas. Algumas colunas não são numéricas e, gostaria que o campo estatístico ficasse em branco no caso de campo não numérico. Já tentei várias alternativas mas esse campo não numérico me mostra #Erro
        Nunca pensei que um relatório fosse dar tanta dor de cabeça.
        Alguma dica?
        Galbas

        • andrealveslima disse:

          Olá Galbas!

          Pois é, relatório costuma dar dor de cabeça sim, hehehe.. Como é que você está fazendo essa estatística? Qual a fórmula que você está utilizando?

          Abraço!
          André Lima

          • GALBAS PORTES disse:

            Bom dia Andre!
            Tentei as opções:
            =IIf(IsNumeric(Fields!ResultadoString1.Value),Format(Max(CDbl(Fields!ResultadoString1.Value)),”N4″), String.Empty)

            e

            =IIf(IsNumeric(Fields!ResultadoString1.Value),FormatNumber(IIf(IsNumeric(Fields!ResultadoString1.Value),Max(Cdbl(Fields!ResultadoString1.Value)),0),4),Fields!ResultadoString1.Value)

            Essa segunda tentativa eu encontre no site StackOverflow.com

            Obrigado,
            Galbas

          • andrealveslima disse:

            Olá Galbas!

            Isso acontece porque o “IIf” sempre processa os dois lados da expressão independente do seu resultado (tanto o lado verdadeiro quanto o lado falso).. Ou seja, quando o resultado não é um número, ele está dando erro na conversão para double, mesmo você tendo conferido pelo IIf se o valor era numérico.. Você precisa checar novamente antes de converter o valor para double.. Tenta dessa forma para ver se dá certo:

            =IIf(IsNumeric(Fields!ResultadoString1.Value),Format(Max(CDbl(IIf(IsNumeric(Fields!ResultadoString1.Value), Fields!ResultadoString1.Value, 0))),”N4″), String.Empty)

            Abraço!
            André Lima

          • GALBAS PORTES disse:

            Boa tarde André! Como todas as suas dicas, obviamente que esta funcionou também!Estou fazendo a migração depois de muitos anos do VB6 para o VB.NET. Estou usando WPF e lógico que é uma grande mudança. Foi tudo bem até agora, só estou “patinando” no relatório. Resumindo, gráfico funcionando, campos ok, cabeçalho ok e rodapé ok.
            Em meu relatório eu preciso colocar um circulo em uma posição x,y do gráfico. O gráfico mostra perfeitamente mas eu não sei como colocar o circulo. Não existe esta possibilidade? Se não existir, a única forma é mostrar o gráfico como uma imagem?
            Obrigado mais uma vez!
            Galbas

          • andrealveslima disse:

            Olá Galbas!

            Que bom que deu certo o esquema de expressão.. Quanto à sua dúvida sobre o círculo, o Report Viewer não tem um controle de shape, dessa forma você não consegue desenhar um círculo.. Porém, acredito que se você fizer uma imagem png de um círculo com fundo (e centro) transparente, se você colocar essa imagem em cima do gráfico deve funcionar (eu nunca tentei, vale a pena a tentativa)..

            O problema é que a sobreposição de controles não é suportada em modo “preview”.. Ou seja, no modo preview a imagem aparecerá do lado do gráfico (e não em cima do gráfico).. No modo impressão (e exportação, se eu não estiver enganado) funcionará corretamente.. Mas no modo preview você terá esse inconveniente..

            A outra opção é fazer que nem você falou.. Gerar o gráfico como imagem por fora do relatório e mandar a imagem pronta para o rdlc..

            Abraço!
            André Lima

  • GALBAS PORTES disse:

    Boa noite André! Coloquei duas Tabelas (Tablix) uma logo abaixo da outra. Quando gero o relatório, a pré-visualização mostra corretamente os dados nas páginas, mas quando vejo no layout de impressão, os dados da Tablix2 são impressos em cima de alguns dados da Tablix1 e diminui o número de páginas a ser impresso. Estou usando formato A4 e parece estar tudo certo. Tem alguma idéia do que pode ser? Obs: Cada Tablix gera mais que uma página, pois, tem muitos registros.
    Obrigado,
    Galbas

    • andrealveslima disse:

      Olá Galbas!

      Estranho hein.. O comportamento padrão do Tablix é empurrar todo o conteúdo que estiver embaixo dele de forma que não ocorra sobreposição de informações.. Você poderia mandar o seu arquivo rdlc no meu e-mail (contato [arroba] andrealveslima [ponto] com [ponto] br) para que eu possa dar uma olhada nele?

      Algo que você poderia tentar é colocar a primeira Tablix dentro de um Rectangle e configurar a propriedade ConsumeContainerWhitespace no relatório.. Muitas vezes isso ajuda quando ocorre sobreposição nos relatórios..

      Abraço!
      André Lima

  • deuzivaldo disse:

    Bom dia professor. Hoje eu estive lendo este seu post. Muito bom mesmo. Vou trabalhar em um projeto idêntico. Me ajudou muito. Obrigado

  • italo martins disse:

    Boa tarde André,

    Sera que você poderia me ajudar?

    Tenho um relatório que preciso exibir diversos textos grandes, porém quando um desses textos não cabem inteiro na pagina ele deixa um belo espaço em branco e começa em outra página, isso só aparece quando é impresso ou exportando para o pdf, são os dóis modos que preciso.

    • andrealveslima disse:

      Olá Italo!

      Normalmente se você configurar a propriedade “KeepTogether” do TextBox como false, uma parte do texto deveria sair na primeira página e o resto na segunda.. Você já chegou a alterar o valor dessa propriedade?

      Abraço!
      André Lima

  • Mariana disse:

    Bom dia, André! Muito bom o seu artigo, parabéns!

    Você já me ajudou uma vez e queria ver se podia me ajudar novamente kkkk
    Eu tenho um relatório em Crystal e estou convertendo ele no Reportviewer. Esse relatório é uma DANFE, uma nota fiscal eletrônica.
    A minha tabela tem apenas um agrupamento (ID da nota), e é composta da seguinte forma:

    -Informações da nota
    -Itens da nota (linha Detalhe)
    -Observações da nota
    (Precisa ser nessa ordem.)

    Todos os elementos estão dentro do mesmo agrupamento.
    Meu problema é o seguinte: Eu preciso mostrar essas observações na primeira página, mesmo que os itens (linha Detalhe) não caibam na primeira página.
    Teria como fazer dessa forma? Mostrar a linha Detalhe, e se ela não saber na primeira página quebrar para a próxima, mas mantendo as observações na primeira página?
    Obs: Eu não posso colocar no rodapé, precisa estar no corpo kkkkkk (pra facilitar mais)

    Espero que meu problema tenha ficado claro.
    Obrigada

    • andrealveslima disse:

      Olá Mariana, muito obrigado!

      Essas “observações da nota” são múltiplos registros ou sempre somente um registro? Se for somente um registro, por que você não pode colocar no rodapé? Qual seria a dificuldade adicional nisso? Eu acho que essa seria a forma mais fácil de resolver esse problema.. Queria entender o motivo de você não estar querendo seguir por esse caminho..

      Abraço!
      André Lima

      • Mariana disse:

        Oi, André, obrigada pela resposta!
        Não posso colocar no rodapé porque o usuário pode selecionar mais de uma nota para imprimir, criando assim várias páginas de notas fiscais. Se colocar no rodapé, todas as notas terão as observações da primeira, mas essa informação não é igual para todas. A não ser que tenha como passar como parâmetro o ID da nota que está no corpo, se tiver como fazer isso seria excelente.

        • andrealveslima disse:

          Olá Mariana!

          Poxa, como pode imprimir mais de uma nota, aí não rola de ser no rodapé mesmo.. A não ser que você exiba o número da nota em algum campo do relatório (o que eu acredito que você esteja fazendo), aí você poderia utilizar o valor do TextBox com o número da nota para filtrar a obserção que será impressa.. Por exemplo:

          =IIF(ReportItems!TextBoxNumeroNota.Value="1", "OBSERVACAO DA NOTA 1", "OBSERVACAO DE OUTRAS NOTAS")
          

          Claro que no exemplo acima eu fiz uma expressão “fixa”, com um “IIF” mostrando observações fixas.. No seu caso você precisaria pegar a informação correta da nota correspondente, utilizando muito provavelmente a expressão Lookup..

          Conseguiu entender a ideia?

          Abraço!
          André Lima

  • Rafael disse:

    Boa tarde Andre!

    Minha duvida é a seguinte, tenho um relatorio que não contem tables, mas quero gerar uma outra pagina nele com um layout diferente do da primeira pagina. Pesquisei em muitos lugares, mandaram eu fazer um relatorio diferente, poré preciso que a segunda pagina seja parte do mesmo relatorio. como faço para chegar em um ponto do relatorio criar uma outra pagina

    Obrigado!

    • andrealveslima disse:

      Olá Rafael!

      Você vai precisar colocar as informações da segunda página dentro de um controle “Rectangle”.. Aí você configura nas propriedades desse rectangle para quebrar página antes dele (add a page break before)..

      Abraço!
      André Lima

  • Giuliano Alves Santana disse:

    André,
    Boa tarde!
    Preciso inserir um texto justificado no reportViewer, temo como fazer isso?
    Existe uma solução para elaboração de formulários em texto através do Visual studio?

    • andrealveslima disse:

      Olá Giuliano!

      Infelizmente, que eu saiba, não tem como.. Eu até já vi umas gambiarras para deixar o texto justificado, mas só funciona com fontes monoespaçadas (em que todas letras sempre têm a mesma largura em pixel)..

      Quanto à sua segunda pergunta, eu não entendi muito bem.. O que você quis dizer com “formulários em texto do Visual Studio”? Poderia explicar mais detalhadamente?

      Abraço!
      André Lima

  • fernando pinto disse:

    Bom dia André como vai ?

    Eu estou desenvolvendo um relatório onde o requisito seria imprimir 4 por pagina (caso haja mais de 4 itens na minha lista) até ai blz, mas existe um outro relatório que deve ser impresso no verso (report de instruções com valores fixo sem parâmetros e sem variaveis).
    Você saberia me dizer como eu posso fazer isso ?

    muito obrigado pela atenção.

    abra~ços

    • andrealveslima disse:

      Olá Fernando!

      Caramba, hein.. Que demanda interessante.. Você precisa exibir esse relatório no viewer do Report Viewer ou pode ser direto um PDF com o resultado final? Se tiver que exibir no viewer, eu sinceramente não faço ideia de como você poderia resolver isso.. Se puder ser direto a geração de um PDF, aí você poderia gerar os dois relatórios separadamente e intercalar as páginas utilizando alguma biblioteca de manipulação de PDF (como o PDFSharp, por exemplo), gerando um PDF final com o resultado esperado..

      Entendeu a ideia?

      Abraço!
      André Lima

      • fernando pinto disse:

        Oi André boa tarde,

        Primeiramente muito obrigado por ter me respondido, eu precisava exibir no viewer, mas não está rolando…
        Eu vou tentar negociar com o usuário uma outra solução .

        abraços e muito obrigado

        • andrealveslima disse:

          Olá Fernando!

          Realmente no viewer fica complicado.. O ideal é convencer o usuário mesmo.. Pode até ser possível, mas com certeza vai dar um trabalho considerável..

          Abraço!
          André Lima

      • fernando pinto disse:

        Eu pensei em criar um pdf mas não rola o padrão da empresa é através do viewer …

        • andrealveslima disse:

          Olá novamente, Fernando.. Entendi.. Mas, talvez nesse caso eles tenham que aceitar algo fora do padrão, uma vez que um relatório desse tipo já é fora do padrão.. Me avisa depois qual foi o resultado das suas discussões aí..

          Abraço!
          André Lima

  • André Spilari disse:

    Olá André como vai? Como eu faço uma quebra de linha dentro de uma expressão.

    • andrealveslima disse:

      Olá André!

      Não sei se vai funcionar no seu caso específico, mas teoricamente, é só utilizar:

      System.Environment.NewLine
      

      Abraço!
      André Lima

  • claudio marques da silva disse:

    bom dia ,

    Gostaria de saber como eu faço para redimencionar o meu relatorio na hora da impressão , pois quando ele é exibido pelo reportview, fica normal , mas quando eu mando para a impressora ele quebra as colunas e acaba jogando para proxima pagina .

    Poderia me ajudar ?

    Obrigado !!

    • andrealveslima disse:

      Olá Claudio.

      Vi que você me mandou um e-mail com a mesma dúvida.. Vamos manter a discussão somente em um lugar (aqui ou por e-mail).. Como perguntei no e-mail, gostaria de entender se você está imprimindo pelo controle visualizador do Report Viewer ou se está imprimindo diretamente na impressora (sem passar pelo controle visualizador)..

      Abraço.
      André Lima

  • claudio marquesda silva disse:

    fiz como esta na sua video aula, porém eu exibo antes no reportView

    http://www.andrealveslima.com.br/blog/index.php/2017/08/02/imprimindo-direto-na-impressora-com-o-report-viewer/

    eu deixo o usuario visualizar e quando ele clica no botão para imprimir eu coloquei o codigo igual o da sua video aula

    • andrealveslima disse:

      Olá Claudio!

      É que aquele código não funciona muito bem com modo paisagem.. Você precisa ajustar o método “CriarDeviceInfo” para considerar a situação quando o relatório está configurado como paisagem.. A alteração em VB.NET fica assim:

          Private Function CriarDeviceInfo(Relatorio As Microsoft.Reporting.WinForms.LocalReport) As String
              Dim PageSettings = Relatorio.GetDefaultPageSettings()
              Dim PageWidth = PageSettings.PaperSize.Width
              Dim PageHeight = PageSettings.PaperSize.Height
              If (PageSettings.IsLandscape) Then
                  PageWidth = PageSettings.PaperSize.Height
                  PageHeight = PageSettings.PaperSize.Width
              End If
       
              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>",
                  PageWidth / 100D, PageHeight / 100D, PageSettings.Margins.Top / 100D, PageSettings.Margins.Left / 100D,
                  PageSettings.Margins.Right / 100D, PageSettings.Margins.Bottom / 100D)
          End Function
      

      Caso você esteja desenvolvendo em C#, a ideia é a mesma.. Só converte o código que deve funcionar também..

      Abraço!
      André Lima

  • Rodrigo Silveira Neto Malagodi disse:

    Boa tarde André.
    Tenho um relatório que é um certificado de treinamento, e em alguns casos, este treinamento possui mais que um aluno.
    O que preciso é que, na condição de ter mais que um aluno, haja uma quebra de página para cada aluno, mas eu não uso tablix, e sim texbox.
    Existe esta possibilidade?
    Fico no aguardo e já te agradeço pela atenção.

    • andrealveslima disse:

      Olá Rodrigo!

      Que eu saiba não.. Você terá que colocar os TextBoxes dentro de um Tablix, agrupar por aluno e colocar uma quebra de página entre as instâncias desse agrupamento..

      Abraço!
      André Lima

  • Rodrigo Silveira Neto Malagodi disse:

    Olá André, boa tarde.

    Eu tive que “individualizar” o report para que o usuário selecione o aluno e gere o certificado, pois com o Tablix ficaria fora do padrão do cliente.

    Mas mesmo assim lhe agradeço pelo retorno.

  • eluiz27 disse:

    Olá, consegui fazer certinho porém a cada página nova as informações descem um pouco, coisa de 1mm para menos, se forem muitas páginas irá quebrar o layout, poderia me ajudar ?

    • andrealveslima disse:

      Olá!

      Muito provavelmente você está com alguma configuração no seu layout entre as quebras de página que está fazendo esse 1mm de diferença.. Você já deu uma olhada para ver se você não encontra nenhum espaço em branco entre as quebras de página? Manda um screenshot do design do seu relatório (em tempo de desenvolvimento, não em tempo de execução) aí pra gente dar uma olhada..

      Abraço!
      André Lima

  • Lara disse:

    E se eu quiser fazer a quebra de página a partir de tabelas diferentes dentro de um mesmo DataSet??

  • Ian Pacheco disse:

    Fala Anrezao, blz??

    Gostaria de agradecer pelo suporte hahaha
    Preciso fazer uma quebra de linha por lista, ou seja passo um parametro (que é uma lista) e a cada indice, preciso que fique numa folha diferente, pois serão encaminhadas para locais diferentes… Por exemplo:
    Tenho um tabela escola, nela contem o nome de escola entao faço meu select, que contem tb outros campos de outras tabelas, porem o que me interessa é que a cada nova escola aconteça a quebra de linha… Escola A tantos regristros, Escola B (nova folha) tantos registros e isso continua ate terminarem minhas escolas…

    • andrealveslima disse:

      Olá Ian!

      Não entendi como você está passando esses dados para o relatório através de parâmetros.. Você está passando uma lista? Como assim? Você poderia explicar como você está fazendo exatamente? Como está o seu código?

      Abraço!
      André Lima

  • Jonathan Mendonça disse:

    Olá André,

    Muito bom o artigo e por aqui está funcionando tudo certo, criei o parametro de quebra de pagina ao setar eles vai ok caso nao coloque a condição no group,

    quando coloco =Not Parameters!Quebra_Pagina.Value ocorre esse erro abaixo:
    “The definition of the report ” is invalid”

    Sabe me dizer o possivel problema?

    Muito obrigado!

    • andrealveslima disse:

      Olá Jonathan!

      Esse tipo de mensagem costuma acontecer quando o designer do Report Viewer acaba atualizando a definição do relatório para uma versão mais recente do que você referenciou no projeto.. Qual versão do Visual Studio você está utilizando e como você referenciou as dlls do Report Viewer no seu projeto?

      Abraço!
      André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *