robinhocne Posted February 5, 2012 Report Share Posted February 5, 2012 (edited) Boa tarde a todos,Sempre tenho dificuldades em relatórios, aparentemente algo simples, mas não consigo:Estou tentando fazer um relatório com quebra por cliente e os detalhes das parcelas deles;Eu utilizo o Delphi 7, BD Firebird e para fazer relatório o Quick Report 4.05.No relatório eu preciso mostrar assim:------------------------------------------------------------- Relatório de Contas á Receber-------------------------------------------------------------Cliente : Robinho Telefone : 00-0000-0000E-mail : robinho@relatorio.comParcela Vencimento Valor-------------------------------------------------------------1ª Parcela 10/01/2012 150,362ª Parcela 10/02/2012 150,363ª Parcela 10/03/2012 150,364ª Parcela 10/04/2012 150,36Total de Parcelas : 4 Valor Total : 601,44-------------------------------------------------------------Cliente : Joao Telefone : 00-0000-0000E-mail : joao@relatorio.comParcela Vencimento Valor-------------------------------------------------------------3ª Parcela 15/01/2012 201,004ª Parcela 15/02/2012 201,005ª Parcela 15/03/2012 201,00Total de Parcelas : 3 Valor Total : 603,00-------------------------------------------------------------Cliente : Maria Telefone : 00-0000-0000E-mail : maria@relatorio.comParcela Vencimento Valor-------------------------------------------------------------1ª Parcela 17/02/2012 85,002ª Parcela 17/03/2012 85,003ª Parcela 17/04/2012 85,00Total de Parcelas : 3 Valor Total : 255,00-------------------------------------------------------------e assim vai pelo total de clientes que vier da pesquisa.....no final um totalizador...-------------------------------------------------------------Total de Parcelas : 10 Valor Total : 1.459,44Para ligar o BD com o sistema eu utilizo um IBTable, IBTransaction e IBQuery.para consultar o Relatório eu utilizo uma IBQuery1 que está ligado ao IBTable:Eu fiz assim:O DataSet do relatório está ligado ao IBQuery1 e os seus respectivos campos;------------------------------------------------------------- **rbTitle** Relatório de Contas á Receber-------------------------------------------------------------**rbDetail**Cliente : Robinho Telefone : 00-0000-0000E-mail : robinho@relatorio.comParcela Vencimento Valor-------------------------------------------------------------**rbSubDetail****FooterBand ligado com o rbGroupFooter**1ª Parcela 10/01/2012 150,362ª Parcela 10/02/2012 150,363ª Parcela 10/03/2012 150,364ª Parcela 10/04/2012 150,36-------------------------------------------------------------**rbGroupFooter**Total de Parcelas : 4 Valor Total : 601,44-------------------------------------------------------------e assim vai pelo total de clientes que vier da pesquisa.....no final um totalizador...-------------------------------------------------------------**rdSummary**Total de Parcelas : 10 Valor Total : 1.459,44mas ai sai só um clientee as parcelas dele não tem nada haver....já vi o Demo do Quick, tentei segui mas não consegui.....Uma ajuda ai...... Edited February 9, 2012 by robinhocne Quote Link to comment Share on other sites More sharing options...
0 Jhonas Posted February 6, 2012 Report Share Posted February 6, 2012 Vi algo a respeito relativo a sua dúvida no forum, mas não me lembro onde ... tente fazer uma pesquisa no forumabraço Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 6, 2012 Author Report Share Posted February 6, 2012 Sim , eu tinha verificado algo parecido, mas era para só ter 2 tipos de detalhes, esse teria que ser por quebra e detalhando e não estou conseguindo fazer. Quote Link to comment Share on other sites More sharing options...
0 Micheus Posted February 6, 2012 Report Share Posted February 6, 2012 Olá robinhocne.Montar relatórios no Quick Report é mesmo muito simples. Voce apenas tem que tentar captar a ideia de como as coisas se encadeiam lá - e é muito parecido com a estrutura do relacionamento de suas tabelas. Logo, se voce montar elas corretamente, montará seu relatório também.Olhe esta figura:Voce diz que está usando um IBTable e um IBQuery e que o DataSet do relatório está ligado ao IBQuery1.Isto me leva a pensar que você vinculou todos os campos do seu relatório aos campos existentes no IBQuery1. Não é que você não possa fazer tudo em uma única consulta, mas dai você tem que ter mais atenção a como isto deverá ser desmenbrado no relatório - se via usar subdetail ou group band.A forma mais simples de você montá-lo (e entendê-lo) é seguindo a estrutura do banco de dados. Isso implicar em usar mais datasets, mas facilitará a compreensão.Assim, o dataset principal (no seu caso, aquele que trará tantos clientes quanto você deseje) é aquele ligado ao QuickRep. Quando você adiciona uma Detail band, o quickreport irá imprimí-la para cada linha deste dataset.Seguindo a estrutura de dados do banco, as tabelas relacionadas à esta utilizada no dataset principal serão aquelas a serem colocadas nos agrupamentos abaixo da detail band.No seu caso, voce teria uma consulta que estaria buscando as informações da tabela parcelas utilizando como filtro a tabela principal. Voce pode fazer isto ustilizando a ligação via DataSource (acredito que você entanda do que estou falando). Estas informações seriam mostradas no seu relatório utilizando uma banda subdetail.Dê também uma lida neste post e veja se ele lhe ajuda um pouco mais a entender o que quero dizer. Depois que você pegar a filosofia da coisa, você não vai mais ter problemas com relatório. ;) Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 7, 2012 Author Report Share Posted February 7, 2012 Micheus, estou quase conseguindo de acordo com suas dicas.....Eu consulto o relatorio dessa maneira:procedure TFrmLisRelCtaReceber.ConsultaRelatorio; begin SQLCondicao := ''; SQLInstCli := 'Select A.CodCli, A.NomCli From Contas_Receber A'; SQLInstrucao := 'Select A.CodCli, A.Parcela, A.Vencimento, A.Receber, A.Recebido, A.Valor From Contas_Receber A'; {Faz o filtro de data de vencimento ...} if ((TxtDtVenIni.Text <> ' / / ') or (TxtDtVenFin.Text <> ' / / ')) then begin if SQLCondicao = '' then begin SQLCondicao := ' where A.Vencimento Between (' +#39+ FormatDateTime('dd.mm.yyyy', TxtDtVenIni.Date) + #39 + ') and ' + '(' +#39+ FormatDateTime('dd.mm.yyyy', TxtDtVenFin.Date) + #39 + ') '; end else begin SQLCondicao := ' and A.Vencimento Between (' +#39+ FormatDateTime('dd.mm.yyyy', TxtDtVenIni.Date) + #39 + ') and ' + '(' +#39+ FormatDateTime('dd.mm.yyyy', TxtDtVenFin.Date) + #39 + ') '; end; end; {... Faz o filtro de data de vencimento} {Busca os Clientes ...} SQLInstCli := SQLInstCli + SQLCondicao + ' and A.SituBaixado = '+#39+'N'+#39+' group by A.CodCli, A.NomCli'; with QryRec do begin close; sql.Clear; sql.Add(SQLInstCli); open; end; TblCli.Close; TblCli.Active := true; while not QryRec.Eof do begin with TblCli do begin insert; TblCliCliente.AsString := QryRec.FieldByName('CodCli').AsString; TblCliNome.AsString := QryRec.FieldByName('NomCli').AsString; post; end; QryRec.Next; end; Memo1.Text := SQLInstCli; TblCli.SortOnFields('Cliente', true, false); {... Busca os Clientes} {Busca as Parcelas ...} SQLInstrucao := SQLInstrucao + SQLCondicao + ' and A.SituBaixado = '+#39+'N'+#39; with QryRec do begin close; sql.Clear; sql.Add(SQLInstrucao); open; end; {... Busca as Parcelas} end;na tabela temporária TblCli eu coloquei o código do cliente e nome do cliente e na Query QryRec está as parcelas, mas ao listar no relatório está saindo misturando as parcelas dos clientes, na imagem abaixo veja que a parcela do Robson saiu para a Deise e vice versa.Coloquei assim:------------------ rbTitle-----------------rdDetail----------------rdSubDetailDataSet: QryRecFooterBand : GroupFooterBand1Master: QuickRep------------------rbGroupFooterLinkBand : QRSubDetail1------------------TOTAL GERAL ?Imagem? Quote Link to comment Share on other sites More sharing options...
0 Micheus Posted February 7, 2012 Report Share Posted February 7, 2012 robinhocne, antes de comentar qualquer coisa, vou lhe perguntar: este código é o que você está usando mesmo ou você removeu alguma parte dele (sem problemas - eu só preciso saber para dar mais ou menos pitacos ;))E uma pergunta que já precisarei de uma resposta: Observei que nas suas consultas, voce sempre usa a tabela Contas_Receber. É isto mesmo? Voce tem todas as informações na mesma tabela? Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 7, 2012 Author Report Share Posted February 7, 2012 robinhocne, antes de comentar qualquer coisa, vou lhe perguntar: este código é o que você está usando mesmo ou você removeu alguma parte dele (sem problemas - eu só preciso saber para dar mais ou menos pitacos ;))É esse código mesmo Micheus.E uma pergunta que já precisarei de uma resposta: Observei que nas suas consultas, voce sempre usa a tabela Contas_Receber. É isto mesmo? Voce tem todas as informações na mesma tabela?Sim, a minha tabela Contas_Receber tem o codigo do cliente e nome também, além das informações da parcela, valor, vencimento, recebido, receber...etc. Quote Link to comment Share on other sites More sharing options...
0 Micheus Posted February 7, 2012 Report Share Posted February 7, 2012 É esse código mesmo Micheus.Bom, neste caso...Observe que você inicializa -> SQLCondicao := '';e não muda ela antes de chegar no -> if SQLCondicao = '' thenlogo, este if será sempre validado.O if anterior -> if ((TxtDtVenIni.Text <> ' / / ') or (TxtDtVenFin.Text <> ' / / ')) thenestá permitindo que um dos valores seja nulo, porque você está usando um OR e não um AND. A menos que você possa realmente informar apenas uma data no período, isto deveria ser corrigido. Neste caso, a montagem da string (concatenação) deveria levar isto em conta, pois se uma das datas pode ser nula, então ela não deveria ser incluída no filtro.Voce provavelmente estaria filtrando um perído (between), ou datas maiores que a inicial (>=) ou as menores que a final (<=)Dê uma avaliada nisto.Sim, a minha tabela Contas_Receber tem o codigo do cliente e nome também, além das informações da parcela, valor, vencimento, recebido, receber...etc.Como voce tem todas as informações em uma única tabela, no meu entender, é desnecessário muito do que você está usando.Basicamente a sua consulta é apenas esta:Select A.CodCli, A.NomCli, A.Parcela, A.Vencimento, A.Receber, A.Recebido, A.Valor From Contas_Receber A where A.Vencimento Between <dd.mm.yyyy> and <dd.mm.yyyy> order by A.NomCliEm uma modelagem de dados usual, as informações do cliente estariam em outra tabela e você faria a ligação entre elas utilizando CodCli.Esta consulta estará trazendo repetidamente o CodCli e NomCli, enquanto que os outros campos (pela lógica) devem ser diferentes. Assim, para montar este relatório utilizando o QuickReport, voce irá precisar apenas de uma group band e uma detail.O dataset (que nesta configuração seria apenas 1) seria vinculado ao QuickRep; Na group band, voce deverá indicar o campo de quebra que neste caso será o CodCli e nela voce adiciona o CodCli e NomCli a serem impressos.Na banda detalhe voce coloca os demais campos referentes às parcelas.Qual é a lógica:- o quick irá varrer o dataset a ele associado;- a banda detail será impressa para cada item no dataset;- como adicionamos uma group band, ela será impressa a cada vez que o campo a ela associado sofrer alteração. Como ordenamos a consulta pelo nome do cliente, automaticamente o código também ficou repetido e agrupado. Assim, a group band irá observer o momento em que este campo é alterado e "se" imprime. Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 8, 2012 Author Report Share Posted February 8, 2012 (edited) Bom, neste caso...Observe que você inicializa -> SQLCondicao := '';e não muda ela antes de chegar no -> if SQLCondicao = '' thenlogo, este if será sempre validado.O if anterior -> if ((TxtDtVenIni.Text <> ' / / ') or (TxtDtVenFin.Text <> ' / / ')) thenestá permitindo que um dos valores seja nulo, porque você está usando um OR e não um AND. A menos que você possa realmente informar apenas uma data no período, isto deveria ser corrigido. Neste caso, a montagem da string (concatenação) deveria levar isto em conta, pois se uma das datas pode ser nula, então ela não deveria ser incluída no filtro.Voce provavelmente estaria filtrando um perído (between), ou datas maiores que a inicial (>=) ou as menores que a final (<=)Dê uma avaliada nisto.Micheus, realmente vocês está certo sobre o or o correto é and, sobre o "if SQLCondicao" eu já deixei preparado o código pois vou incluir mais tipo de filtro.Sobre o agrupamento do relatório ficou show de bola, do jeito que eu queria, agora só não estou conseguindo fazer que para cada agrupador(cliente) apareça um "subtotal", pois um "total" eu já coloquei em um rbSummary e deu certo, para o subtotal eu havia colocado uma child, mas para cada registro foi somando um resultado (legal), mas não o que quero...testei entre outras BandType e não consegui, você poderia me ajudar ?Obrigado. Edited February 8, 2012 by robinhocne Quote Link to comment Share on other sites More sharing options...
0 Micheus Posted February 8, 2012 Report Share Posted February 8, 2012 Sobre o agrupamento do relatório ficou show de bola, do jeito que eu queria, agora só não estou conseguindo fazer que para cada agrupador(cliente) apareça um "subtotal", pois um "total" eu já coloquei em um rbSummary e deu certo, para o subtotal eu havia colocado uma child, mas para cada registro foi somando um resultado (legal), mas não o que quero...testei entre outras BandType e não consegui, você poderia me ajudar ?A banda sumário, é como diz o nome: sumariza/totaliza tudo! Ou seja, soma todos os registros que ele mostrar na banda detalhe.Isto que voce quer está claramente relacionado à quebra do cabeçalho, não é mesmo. Vinculada à uma GroupBand voce terá uma GroupFooter (ou apenas footerband - já não lembro, mas você a achará). Esta banda deverá ser vinculada à group em questão. Isso é necessário porque o QuickReport tem que saber a quem ela "pertence" para imprimí-la na hora certa. Lembre-se que voce poderia ter vários destes conjuntos em um relatório mais compléxo.Observe ainda, que há uma propriedade nos componente de totalização (TQrExpr) que voce usará onde você diz que ele deve ser zerado após impresso (acho que é algo como ResetAfterPrint). Do contrário, ele poderá funcionar como um sumario.Abraços Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 8, 2012 Author Report Share Posted February 8, 2012 (edited) um outro detalhe é que informei:order by A.NomCli, A.Parcelae não está ordenando por parcela, sai tudo mistura, o cliente sai na ordenação.... Edited February 8, 2012 by robinhocne Quote Link to comment Share on other sites More sharing options...
0 Micheus Posted February 8, 2012 Report Share Posted February 8, 2012 um outro detalhe é que informei: order by A.NomCli, A.ParcelaPela imagem daquele relelatório inicial, parece que este campo é string e não numérico. Sendo string, dependendo como está o texto isto poderia acontecer. Vai ficar de eu avaliar isto daqui.Eventualmente, voce não poderia utilizar a data? Em teoria, a ordem de vencimento é a orde das parcelas - crescente Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 8, 2012 Author Report Share Posted February 8, 2012 Coloquei uma QRBand e mudei o BandType para rbGroupFooter, liguei o LinkBand com a QRGroup1, nele eu coloquei os QrExpr :sum(valor), sum(recebido) e sum(receber).mesmo assim não trouxe nada, testei como rbGroupHeader, mas também não deu, o que posso estar fazendo de errado ?um outro detalhe é que informei: order by A.NomCli, A.Parcela Pela imagem daquele relelatório inicial, parece que este campo é string e não numérico. Sendo string, dependendo como está o texto isto poderia acontecer. Vai ficar de eu avaliar isto daqui. Eventualmente, voce não poderia utilizar a data? Em teoria, a ordem de vencimento é a orde das parcelas - crescente Nesse caso eu tenho o campo A.NumParc que traz o numero da parcela, é um campo numeric, coloquei ele e o CodCli como order by também, ai deu certo. Ficou então order by A.CodCli, A.NomCli, A.NumParc Quote Link to comment Share on other sites More sharing options...
0 Micheus Posted February 8, 2012 Report Share Posted February 8, 2012 Coloquei uma QRBand e mudei o BandType para rbGroupFooter, liguei o LinkBand com a QRGroup1, nele eu coloquei os QrExpr :sum(valor), sum(recebido) e sum(receber).mesmo assim não trouxe nada, testei como rbGroupHeader, mas também não deu, o que posso estar fazendo de errado ?só para confirmar, o QRGroup1 deve ter as propriedades Expression contendo o campo de quebra do dataset (CodCli) e a propriedade FooterBand apontando para a QRBand que você definiu para rbGroupFooter.No QRExp além de configurar a Expression e setar ResetAfterPrint = True.Estamos chegando naquele ponto em que eu não vendo o seu código, não consigo depurá-lo. A lógica é esta ai que discutimos aqui.Nesse caso eu tenho o campo A.NumParc que traz o numero da parcela, é um campo numeric, coloquei ele e o CodCli como order by também, ai deu certo.Ficou entãoorder by A.CodCli, A.NomCli, A.NumParcSe voce quer que a listagem seja ordenada pelo nome do cliente, então aquele CodCli não deve ser colocado. No caso de voce querer ordenar pelo CodCli mesmo, então retire NomCli porque ele torna-se redundante e também, pelo fato de que se a sua tabela tiver um índice contendo os campos CodCli + NunParc, este índice será utilizado na ordenação agilizando-a. Quote Link to comment Share on other sites More sharing options...
0 robinhocne Posted February 9, 2012 Author Report Share Posted February 9, 2012 só para confirmar, o QRGroup1 deve ter as propriedades Expression contendo o campo de quebra do dataset (CodCli) e a propriedade FooterBand apontando para a QRBand que você definiu para rbGroupFooter.faltava setar a propriedade FooterBand......Agora está ordenando na quebra e campos de detalhes, está somando cada quebra (SubTotal) e retornando um total geral...por fim....completo :D Nossa Micheus, cara muito obrigado mesmo pela ajuda, paciência, me ajudou muito e entendi várias coisas com suas explicações.....obrigado mais uma vez..... :lol: :D ^_^ Quote Link to comment Share on other sites More sharing options...
Question
robinhocne
Boa tarde a todos,
Sempre tenho dificuldades em relatórios, aparentemente algo simples, mas não consigo:
Estou tentando fazer um relatório com quebra por cliente e os detalhes das parcelas deles;
Eu utilizo o Delphi 7, BD Firebird e para fazer relatório o Quick Report 4.05.
No relatório eu preciso mostrar assim:
Para ligar o BD com o sistema eu utilizo um IBTable, IBTransaction e IBQuery.para consultar o Relatório eu utilizo uma IBQuery1 que está ligado ao IBTable:
Eu fiz assim:
O DataSet do relatório está ligado ao IBQuery1 e os seus respectivos campos;
mas ai sai só um cliente
e as parcelas dele não tem nada haver....já vi o Demo do Quick, tentei segui mas não consegui.....
Uma ajuda ai......
Edited by robinhocneLink to comment
Share on other sites
14 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.