Jump to content
Fórum Script Brasil
  • 0

[resolvido] Duplica Registros Quickreport


Eder
 Share

Question

Ola..pessoal..novamente estou com problemas com duplicação de registros.

Eu fiz esta instrução sql:

SELECT PAGADOR_NOME,

REMET_CIDADE,

VALOR_FRETE

FROM CTRC WHERE (REMET_CIDADE = "BLUMENAU")

ORDER BY PAGADOR_NOME

Ela deveria selecionar todos os clientes pagadores da cidade de Blumenau e ordenar o rel. por cliente pagador

Montei o relatorio no quick assim Bandas:

pageheader

title

rbColumnHeader

QrGroup=expression=QUERY1.PAGADOR_NOME o a footerband dela = BandaGroupFooter

rbDetail

rbGroupFooter

rbSummary

Funciona certinho.....exceto a duplicação de registros....

ai fiz o famoso testezinho num dbgrid pra testar meu codigo sql..e ai notei que também duplicad então ficou claro que é o código..

Então pederia aos colegas..me explicarem porque acontece esta duplicação...pois trabalho apenas com uma tabela.

muito Grato

Link to comment
Share on other sites

23 answers to this question

Recommended Posts

  • 0

Eder, se você tem 3 campos no seu select (PAGADOR_NOME, REMET_CIDADE, VALOR_FRETE), está agrupando por PAGADOR_NOME (GroupBand) e tem uma banda detalhe onde supostamente tem algo nela (suponho: REMET_CIDADE, VALOR_FRETE), parece lógico que se um pagador tiver mais que um registro haja a impressão das respectivas bandas detalhes.

- Que informações você tem nas bandas Group, Detail, Footer?

- Como deveria ser o lay-out de saída do seu relatório?

Link to comment
Share on other sites

  • 0
- Que informações você tem nas bandas Group, Detail, Footer?
R.: Na Group tenho o Pagador_nome

na detail tenho somente o campo VALOR_FRETE

na footer o totalizar ou seja um Qrexp somando o valor_frete

- Como deveria ser o lay-out de saída do seu relatório?

R.: é simples é o nome_pagador na Group e na detail a relação dos valores e na groupFooter totaliza a cada Pagador_nome e na Sumary o total geral....

Micheus....mas você notou que coloquei que numa dbgrid também duplica...acho que é no meu select o problema....você Não acha???

Este negócio de duplicar regitros de vez em quando me empata!!!..vichiiiii

Grato

Link to comment
Share on other sites

  • 0
- Que informações você tem nas bandas Group, Detail, Footer?
R.: Na Group tenho o Pagador_nome

na detail tenho somente o campo VALOR_FRETE

na footer o totalizar ou seja um Qrexp somando o valor_frete

- Como deveria ser o lay-out de saída do seu relatório?
R.: é simples é o nome_pagador na Group e na detail a relação dos valores e na groupFooter totaliza a cada Pagador_nome e na Sumary o total geral....
isto então confirma o que eu imaginava que você estivesse fazendo no seu relatório.

Micheus....mas você notou que coloquei que numa dbgrid também duplica...acho que é no meu select o problema....você Não acha???
Pelo seu SQL, a única coisa que deve estar duplicada é PAGADOR_NOME E REMET_CIDADE. O VALOR_FRETE deve ser diferente para cada linha listada - exceto, se por algum problema você tem realmente estes dados duplicados na base:
PAGADOR_NOME | REMET_CIDADE | VALOR_FRETE
Eder         | BLUMENAU     |  45,00
Eder         | BLUMENAU     |  35,00
Eder         | BLUMENAU     |  53,00
Micheus      | BLUMENAU     |  45,00
Micheus      | BLUMENAU     |  15,00
Micheus      | BLUMENAU     |  23,50

A cidade sempre vai repetir, já que você à utiliza no filtro e o nome repetirá para cada registro de valor frete que existir.

Não era este tipo de resultado que você esperava?

Link to comment
Share on other sites

  • 0

Carinha...perdão comi bola de novo.....lembra dos testes do Gauge???pois é nestes testes...acabei duplicando a base várias vezes...e não havia percebido..e pra fazer o relatorio acabei pegando esta base teste...foi mal.

é o que você havia suspeitado na resposta que li agora.

agora o relatório sai certinho...teria que sair mesmo. ;)

Agora mudei a minha select assim:

SELECT DATA_EMISSAO, SIGLA_CTRC, NUMERO_CTRC, PAGADOR_NOME,
REMET_CIDADE,
VALOR_FRETE
FROM CTRC WHERE (REMET_CIDADE = "BLUMENAU") 
ORDER BY PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC
Só que eu queria colocar a ordem do relatorio pra que sair o VALOR_FRETE(groopFooter) na ordem Descrescente....ou seja em ordem de Rankin, ou melhor colocar o o cliente analizando o seu valor_frete em ordem de ranking, mas não to achando o codigo certo....pois já existe ali um order by. Tentei usar assim o order by:
Order by Valor_frete Desc, sigla_ctrc, numero_ctrc

mas ai....não agrupa os dados e sai o relatorio picado.

você teria alguma idéia??

Grato e perdão pela falha quanto a duplicação de registros. :(

Link to comment
Share on other sites

  • 0

Se não me engano, você havia dito que na groopFooter estaria o valor total de fretes daquele cliente, não é? Supondo quea resposta seja sim, então a query naquele formato não vai resultar no que você quer.

Eu só vejo uma saída para esta situação - utilizar duas consultas:

- uma agrupa os valores pelo nome;

- a outra baseada no nome, busca os itens (fretes individuais)

Vejamos se consigo exemplificar:

SELECT PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL
FROM CTRC 
WHERE REMET_CIDADE = "BLUMENAU"
GROUP BY PAGADOR_NOME
ORDER BY 2 DESC
Esta query agrupará (somará) os fretes de cada pagador e ao final ordenará pela 2ª coluna (o resultado do SUM). Se alguma das outras colunas que eu suprimi aqui, se repetirem para cada linha de registro do pagador, você pode a acrescentá-la aqui, do contrário, terá que trazê-la na outra consulta. Você já deve entender como funciona uma consulta com GROUP BY, não?! Nesta condição (hanking) acho que você poderia colocar o valor total, na mesma banda que o nome do pagador. Isso simplificaria bastante as coisas. Você teria uma banda Detail com o PAGADOR_NOME o valor total VALOR_FRETE_TOTAL. Para detalhar estes pagamentos, você utilizaria a seguinte consulta:
SELECT DATA_EMISSAO, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE
FROM CTRC 
WHERE REMET_CIDADE = "BLUMENAU" 
   AND PAGADOR_NOME = :PAGADOR_NOME
ORDER BY SIGLA_CTRC, NUMERO_CTRC

Veja que nesta consulta é esperado um parâmetro, que não por acaso tem o mesmo nome do campo que iremos buscar na query principal.

Esta query deve ser ligada, via propriedade MasterSource, ao datasource da 1ª query.

Você então adiciona uma banda SubDetail para mostrar os dados obtidos nesta query e define em sua propriedade Dataset esta segunda query.

Como vai funcionar:

- ao mostrar seu relatório, você abre as duas queries;

- para cada linha na 1ª query (impressa na banda detalhe), a 2ª query obterá o parâmetro da primeira (automaticamente, por isso o nome do parâmetro ser igual ao campo lá obtido)

- havendo resultados na 2ª query, seus dados serão mostrados através da banda subdetail.

Será que me fiz entender?!

Link to comment
Share on other sites

  • 0

Carinha achei...muito Complicado :(

Achei que era mais simples, derepende um order by resolveria.

Na verdade eu apenas queria criar este relatorio a mais no programa...mais vou deixar como esta....e mostrar desta maneira anterior.

No momento estou meio atarefado..e eu iria perder um pouco de tempo..

Vou deixar este tópico anotado pra hora que tiver um tempo maior...dar uma estudada e monta-lo

Uma vez eu vi um relatorio assim:

Listava os clientes como estou fazendo mais ou menos...e no final do relatorio abria um resumo sintetico em ordem de ranking.(mas só no final) e listava somente os 10 maiores clientes...achei muito legal....mas deve ser muito complicado mexer num relatorio destes...imagina!!..se este...você já escreveu um monte...

Mas...beleza..o que eu pretendia inicialmente era um relatorio analítico por ordem de cliente...já resolve...no momento.

valeu

Grato

Link to comment
Share on other sites

  • 0
Carinha achei...muito Complicado :(
Só parece complicado - é muito simples!

Achei que era mais simples, derepende um order by resolveria.
como fazer um order by por um campo (total) que você não tem na sua consulta? Com a sua consulta inicial, no máximo, você conseguiria ordenar os valores para uma mesmo nome.

Mas tudo bem. Se eu tiver um tempinho, faço um para você ver que não tem nada de complicado. ;)

Link to comment
Share on other sites

  • 0

Ola..Micheus....Carinha...meti a cara hoje de manhã..e ttrabalhei em cima do seu exemplo e CONSEGUI montar exatamente como queria....funcionar 100%....mostrou os totais em ordem de Ranking e totalizei na sumary o relatorio, coloquei também mais um campo o cnpj dos clientes e também coloquei um QrsysData=que mostra a colocação do clientes....ficou show. :D

ficou assim as duas queryes

query1:

SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL
FROM CTRC WHERE (SITUACAO_CTRC <> "C")
GROUP BY PAG_CNPJ, PAGADOR_NOME
ORDER BY 3 DESC
Query2:
SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE
FROM CTRC 
WHERE (SITUACAO_CTRC <> "C")  AND (PAG_CNPJ = :PAG_CNPJ)
ORDER BY SIGLA_CTRC, NUMERO_CTRC
Segui exatamente seus passos, e claro que ai eu mudei algumas coisinhas no codigo, tipo mais campos e filtros etc...mas a sua ideia deu certo. Carinha seguinte: me surgiu duas duvidas agora, só por curiosidade. Uma delas é que se eu quizer consultar por data. Eu fiz assim mas da erro:
procedure TFormRanking.XiButton2Click(Sender: TObject);
var Qry1, Qry2 : String;
begin
 If DateTimePicker2.Date < DateTimePicker1.Date Then
    begin
      ShowMessage('Intervalo de datas Inválido, a data Inicial é maior que a data Final!');
      DateTimePicker2.Date := DateTimePicker1.Date;
    exit;
    end;

    {QUERY1}
    Qry1 :='SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL '+
    'FROM CTRC WHERE (SITUACAO_CTRC <> "C") '+
    'AND between :datai and :dataf '+
    'GROUP BY PAG_CNPJ, PAGADOR_NOME ORDER BY 3 DESC';
    Query1.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query1.SQL.Text := Qry1; //a instrucao sql recebe o texto acima
    Query1.ParamByName('datai').AsDate := DateTimePicker1.Date; // você ta passando as datas iniciais para o parametro
    Query1.ParamByName('dataf').AsDate := DateTimePicker2.Date; // você ta passando as datas finais para o parametro
    Query1.Open;

    {QUERY2}
    Qry2 :='SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, '+
    'NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE '+
    'FROM WHERE (SITUACAO_CTRC <> "C")  AND (PAG_CNPJ = :PAG_CNPJ) '+
    'AND between :datai and :dataf '+
    'ORDER BY SIGLA_CTRC, NUMERO_CTRC';
    Query2.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query2.SQL.Text := Qry2; //a instrucao sql recebe o texto acima
    Query2.ParamByName('datai').AsDate := DateTimePicker1.Date; // você ta passando as datas iniciais para o parametro
    Query2.ParamByName('dataf').AsDate := DateTimePicker2.Date; // você ta passando as datas finais para o parametro
    Query2.Open;
    If query1.IsEmpty Then
   begin
    ShowMessage('Nenhum Registro Encontrado!');
    exit;
   end;
    quickrep1.Preview;
    END;

e a outra dúvida....bom...esta deixa pra depois...

Bom é isto ai....valeu a ajuda..agradecido.

Abraços

:D

Link to comment
Share on other sites

  • 0
Ola..Micheus....Carinha...meti a cara hoje de manhã..e ttrabalhei em cima do seu exemplo e CONSEGUI montar exatamente como queria....funcionar 100%....mostrou os totais em ordem de Ranking e totalizei na sumary o relatorio, coloquei também mais um campo o cnpj dos clientes e também coloquei um QrsysData=que mostra a colocação do clientes....ficou show. :D

Segui exatamente seus passos, e claro que ai eu mudei algumas coisinhas no codigo, tipo mais campos e filtros etc...

beleza, parabéns :D

Carinha seguinte:

me surgiu duas duvidas agora, só por curiosidade.

Uma delas é que se eu quizer consultar por data. Eu fiz assim mas da erro:

dá uma olhada nesta linha:

'AND between :datai and :dataf '+

você não está sentindo falta de nada não? :unsure:

AND ??? between :datai and :dataf

Percebeu?! o que é mesmo que tem que estar entre datai e dataf? Não seria DATA_EMISSAO? ;)

e a outra dúvida....bom...esta deixa pra depois...
manda logo esta encrenca... :D

Abraços

Link to comment
Share on other sites

  • 0
dá uma olhada nesta linha:

'AND between :datai and :dataf '+

você não está sentindo falta de nada não?

AND ??? between :datai and :dataf

Percebeu?! o que é mesmo que tem que estar entre datai e dataf? Não seria DATA_EMISSAO?

R.: Opa.....cheguei....foi mal... na correria nem me toquei do nome do campo.... :)

Mas..Micheus...mesmo assim...o relatorio saiu loco....duplicando

cliente........cnpj.......valor
=================
xxxxx.......99999.......10,00
xxxxx.......99999.......10,00
xxxxx.......99999.......10,00 repete um monte de vezes...ai depois muda pra outro cliente
yyyyy.......99999.......15,00
yyyyy.......99999.......15,00
e vai repetindo.....não sei porque...ai só pra testar tirei o codigo de DATA_EMISSÃO para ficar igual ao codigo sql que esta na PROPRIA query1 e query2 no quickreport ficando assim:
procedure TFormRanking.XiButton2Click(Sender: TObject);
var Qry1, Qry2 : String;
begin
    {QUERY1}
    Qry1 := 'SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") '+
'GROUP BY PAG_CNPJ, PAGADOR_NOME ORDER BY 3 DESC';
    Query1.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query1.SQL.Text := Qry1; //a instrucao sql recebe o texto acima
    Query1.Open;

    {QUERY2}
    Qry2 := 'SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") AND (PAG_CNPJ = :PAG_CNPJ) ORDER BY SIGLA_CTRC, NUMERO_CTRC';
    Query2.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query2.SQL.Text := Qry2; //a instrucao sql recebe o texto acima
    Query2.Open;
    quickrep1.Preview;
    END;

e ai continua repetindo......estranho não deveria pois..estou passando atraves do Qry1 e Qry2 variaveis Texto...a instrução sql igualzinho que ta la nas querys no proprio form do quick.

O que você acha??

Grato

Edited by Eder
Link to comment
Share on other sites

  • 0
e vai repetindo.....não sei porque...ai só pra testar tirei o codigo de DATA_EMISSÃO para ficar igual ao codigo sql que esta na PROPRIA query1 e query2 no quickreport

ficando assim:

procedure TFormRanking.XiButton2Click(Sender: TObject);
var Qry1, Qry2 : String;
begin
    {QUERY1}
    Qry1 := 'SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") '+
'GROUP BY PAG_CNPJ, PAGADOR_NOME ORDER BY 3 DESC';
    Query1.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query1.SQL.Text := Qry1; //a instrucao sql recebe o texto acima
    Query1.Open;

    {QUERY2}
    Qry2 := 'SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") AND (PAG_CNPJ = :PAG_CNPJ) ORDER BY SIGLA_CTRC, NUMERO_CTRC';
    Query2.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query2.SQL.Text := Qry2; //a instrucao sql recebe o texto acima
    Query2.Open;
    quickrep1.Preview;
    END;

Eder, está deste jeito mesmo? Onde está a inicialização dos parâmetros?

Link to comment
Share on other sites

  • 0
Eder, está deste jeito mesmo? Onde está a inicialização dos parâmetros?

R.: Oba....Micheus...ta deixa ver se entendi.. a inicialização que você diz é o parametro da query?

se for ....acrescentei esta linha no codigo:

Query2.ParamByName('pag_cnpj').asString := QUERY1pag_cnpj.AsString;
codigo abaixo completo
var Qry1, Qry2 : String;
    Begin
    Qry1 := 'SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") '+
'GROUP BY PAG_CNPJ, PAGADOR_NOME ORDER BY 3 DESC';
    Query1.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query1.SQL.Text := Qry1;
    Query1.Open;

    {QUERY2}
    Qry2 := 'SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") AND (PAG_CNPJ = :PAG_CNPJ) ORDER BY SIGLA_CTRC, NUMERO_CTRC';
    Query2.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query2.SQL.Text := Qry2; //a instrucao sql recebe o texto acima
    Query2.ParamByName('pag_cnpj').asString := QUERY1pag_cnpj.AsString; 
    Query2.Open;
    quickrep1.Preview;

Mesmo assim ta duplicando como mencionei acima...

Estou fazendo errado??

Antes eu tava fazendo na propria query..e funcionava.

Link to comment
Share on other sites

  • 0

Eder, a questão do parâmetro pode ter sido viagem minha. É que as coisas já ficaram confusas. Voce começou sem parâmetros na query principal, depois colocou parâmetros para filtrar período, daí no último post você retirou esta cláusula where com os parâmetros da data e eu ainda estava com elas na cabeça e não percebi que você as tinha retirado.

Repassando:

- Qry1 é a principal (resumo), conterá como resultado uma lista de nomes de pagadores, em ordem decrescente de vl total de frete;

- Qry2 é a secundária (detalhe), conterá os detalhes que resultaram no agrupamento total feito na Qry1;

- Seu quickreport tem uma banda Detail, onde estão os campos da Qry1 ou eles estão em um GroupHeader - certo?!

- Seu quickreport tem uma banda Sub-detail, onde estão os campos da Qry2 - certo?!

- Qry1 está vinculada a propriedade Dataset do seu QuickReport - certo?!

- Qry2 está vinculada a propriedade Dataset da sua banda SubDetail - certo?!

- Qry1 está vinculada a um DataSource;

- Qry2 está vinculada ao Datasource da Qry1, via sua propriedade Datasource. Este procedimento tem por objetivo, direcionar a obtenção do parâmetro pag_cnpj a partir da linha atual de Qry1. Assim, não deve ser colocado no código a linha:

Query2.ParamByName('pag_cnpj').asString := QUERY1pag_cnpj.AsString;

Por favor repasse o check-list e dê um retorno.

Link to comment
Share on other sites

  • 0
Eder, a questão do parâmetro pode ter sido viagem minha. É que as coisas já ficaram confusas. Voce começou sem parâmetros na query principal, depois colocou parâmetros para filtrar período, daí no último post você retirou esta cláusula where com os parâmetros da data e eu ainda estava com elas na cabeça e não percebi que você as tinha retirado.
R.: fiz isto e abandonei por enquando o periodo ...pois deu erro...resolvi fazer um testezinho sem o periodo...pois antes quando tinha dito que tinha dado tudo certo, eu fazia os codigos sql nas proprias querys...no SQL-Tstrings....mas como eu queria testa-los também com o codigo a instrução sql no botão....exemplo:

Qry2 := 'SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE '+
'FROM CTRC WHERE (SITUACAO_CTRC <> "C") AND (PAG_CNPJ = :PAG_CNPJ) ORDER BY SIGLA_CTRC, NUMERO_CTRC';
Repassando: - Qry1 é a principal (resumo), conterá como resultado uma lista de nomes de pagadores, em ordem decrescente de vl total de frete; - Qry2 é a secundária (detalhe), conterá os detalhes que resultaram no agrupamento total feito na Qry1; - Seu quickreport tem uma banda Detail, onde estão os campos da Qry1 ou eles estão em um GroupHeader - certo?! - Seu quickreport tem uma banda Sub-detail, onde estão os campos da Qry2 - certo?! - Qry1 está vinculada a propriedade Dataset do seu QuickReport - certo?! - Qry2 está vinculada a propriedade Dataset da sua banda SubDetail - certo?! - Qry1 está vinculada a um DataSource; - Qry2 está vinculada ao Datasource da Qry1, via sua propriedade Datasource. Este procedimento tem por objetivo, direcionar a obtenção do parâmetro pag_cnpj a partir da linha atual de Qry1. Assim, não deve ser colocado no código a linha: Query2.ParamByName('pag_cnpj').asString := QUERY1pag_cnpj.AsString; Por favor repasse o check-list e dê um retorno.
R.: bom....ta tudo certo como acima, exceto as bandas....tenho somente as bandas:
rbPageHeader rbTitle rbColumnHeader (TQRSubDetailGroupBands) nesta aqui foi sugestão sua colocar o nome do cliente, cnpj e o valor. rbSummary nesta aqui eu totalizo o valor...e finalizo.
Micheus....só pra você entender...o relatorio funciona 100% se eu colocar este codigo na query1 SQL TStrings:
SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS [quote]VALOR_FRETE_TOTAL
FROM CTRC WHERE (SITUACAO_CTRC <> "C")
GROUP BY PAG_CNPJ, PAGADOR_NOME
ORDER BY 3 DESC
e na Query2 SQL TStrings:
SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE
FROM CTRC 
WHERE (SITUACAO_CTRC <> "C")  AND (PAG_CNPJ = :PAG_CNPJ)
ORDER BY SIGLA_CTRC, NUMERO_CTRC
entendeu?? funciona certinho.. Agora que vem a pepa....eu não queria usar mais o codigo direto nas querys SQL TStrings, pois como vou ter que deixar o usuario selecionar a data (periodo desejado)...então gostaria de deixar estes codigo na query num BOTÃO. pra isto tenho que trabalhar estes codigos pro botão....e coloca-los em string´s..como coloquei logo acima.....mas eles não funcionam ...duplicam.... não sei porque...pois estou usando o mesmo critério....apenas mudando a forma de processar...que antes tava nos TString direto nas queryes...e agora coloquei no botão...exatamente igual. Valeu..Grato opa deu certo era este codigo abaixo que dava o problema e duplicava:
query2.open;
ai retirei ele e ficou assim:
procedure TFormRanking.XiButton2Click(Sender: TObject);
var Qry1, Qry2 : String;
begin
    If DateTimePicker2.Date < DateTimePicker1.Date Then
    begin
      ShowMessage('Intervalo de datas Inválido, a data Inicial é maior que a data Final!');
      DateTimePicker2.Date := DateTimePicker1.Date;
    exit;
    end;
    {QUERY1}
    Qry1 :='SELECT PAG_CNPJ, PAGADOR_NOME, SUM(VALOR_FRETE) AS VALOR_FRETE_TOTAL '+
    'FROM CTRC WHERE (SITUACAO_CTRC <> "C") '+
    'AND DATA_EMISSAO between :datai and :dataf '+
    'GROUP BY PAG_CNPJ, PAGADOR_NOME ORDER BY 3 DESC';

    Query1.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query1.SQL.Text := Qry1; //a instrucao sql recebe o texto acima//Query1.ParamByName('datai').AsDate := DateTimePicker1.Date; // você ta passando as datas iniciais para o parametro
    Query1.ParamByName('datai').AsDate := DateTimePicker1.Date;
    Query1.ParamByName('dataf').AsDate := DateTimePicker2.Date; // você ta passando as datas finais para o parametro
    Query1.Open;
    {QUERY2}
    Qry2 :='SELECT DATA_EMISSAO, PAG_CNPJ, PAGADOR_NOME, SIGLA_CTRC, '+
    'NUMERO_CTRC, REMET_CIDADE, VALOR_FRETE '+
    'FROM WHERE (SITUACAO_CTRC <> "C")  AND (PAG_CNPJ = :PAG_CNPJ) '+
    'AND DATA_EMISSAO between :datai and :dataf '+
    'ORDER BY SIGLA_CTRC, NUMERO_CTRC';
    Query2.Close; //fecha para limpar qualquer instrução que esteje na memoria....
    Query2.SQL.Text := Qry2; //a instrucao sql recebe o texto acima
    Query2.ParamByName('datai').AsDate := DateTimePicker1.Date;
    Query2.ParamByName('dataf').AsDate := DateTimePicker2.Date; // você ta passando as datas finais para o parametro
         //
    If query1.IsEmpty Then
   begin
    ShowMessage('Nenhum Registro Encontrado!');
    exit;
   end;
    FormRAbast1.qrlabel20.Caption:=DateToStr(DateTimePicker1.Date);
    FormRAbast1.qrlabel22.Caption:=DateToStr(DateTimePicker2.Date);
    quickrep1.Preview;
    End;
Agora fechou tudo certinho....até por periodo.. :D O que é um codigo colocado incorretamente né :D Carinha sem querer abusar ...lembra da outra dúvida?? acho que esta é facil pra você.. Eu gostaria de saber se da pra listar apenas os 10 maiores clientes..... É facil?? li uns artigos que diz que tem usar um comando chamado:
top 10

tentei usar mas não deu certo...não sei se coloquei certo.

Grato ;)

Edited by Micheus
Link to comment
Share on other sites

  • 0
Agora fechou tudo certinho....até por periodo..

:D O que é um codigo colocado incorretamente né :D

Até que enfim.... :D

Eu gostaria de saber se da pra listar apenas os 10 maiores clientes.....

É facil?? li uns artigos que diz que tem usar um comando chamado:

top 10

depende de que banco você utiliza:

- Se for Paradox, não há suporte a este tipo de "seleção";

- Se for Interbase ou SQLServer (se não me engano, este também), então você teria a opção de TOP no SELECT;

- Se for FireBird, então não existe TOP, mas sim FIRST;

Resumindo, se não for Paradox é fácil.

Caso contrário, o único jeito que conheço é você controlar na mão. Teria duas maneiras:

- Controlar o evento OnNeedData do relatório;

- Evitar a impressão da banda após impressos os "n" itens, através do parâmetro PrintBand recebido no evento BeforePrint da banda Detail, SubDetail ou Group (o que você estiver imprindo).

A vantagem da 1ª opção é que seu relatório só vai processar os "n" itens, enquanto a 2ª processará todos, mas imprimirá apenas os itens limitados.

Dúvidas sobre OnNeedData? Se tiver, veja se você lembra deste post ;)

Link to comment
Share on other sites

  • 0

Micheus.....achei que era mais simples....é muito complicado...deixa quieto.... ;)

Do Jeito que ta já ta bom pra caramba....hehehe

A hora que tiver mais inspirado...vou dar um estudada.

Por enquanto meu muito obrigado pelo esforço e paciência.

O que eu queria realmente você me ajudou...e ficou muito bom...t+ :D

Abraço

Oba...eu de novo....tive uma ideia....eu tinha colocado um QrSysData que mostrava a colocação do cliente no ranking...

então eu pensei não daria pra fazer o controle em cima deste componente??

eu fiz assim:

procedure TFormRanking.QRSysData3Print(sender: TObject; var Value: String);
begin
If value = '4' then
begin
Abort;
end
else
begin
VALUE := formatfloat('000',StrToFloat(VALUE))+'º';
end;
end;
até funcionou em parte...ele mostrou os 4 clientes maiores.....só não terminou o relatorio corretamente...derepente você saberia como fazer para o relatório em cima deste componente e encerra-lo corretamente... O que acha??? é só uma ideia..aqui deu certo como te falei apenas não encerrou corretamente: o layout ficou assim>
c===cliente======valor
1.......XXXX.............10,00
2.......YYYY..............15,00
3.......ZZZZ.............18,00
  .......mmm.............12,00

pode notar que ele não mostrou o nr 4 e não mostrou a banda sumary e o somatorio, é claro eu abortei....

mas será que teria jeito? se não der beleza...foi uma ideia...

abraço

Link to comment
Share on other sites

  • 0
Oba...eu de novo....tive uma ideia....eu tinha colocado um QrSysData que mostrava a colocação do cliente no ranking...

então eu pensei não daria pra fazer o controle em cima deste componente??

eu fiz assim:

procedure TFormRanking.QRSysData3Print(sender: TObject; var Value: String);
begin
  If value = '4' then
  begin
    Abort;
  end
  else
  begin
    VALUE := formatfloat('000',StrToFloat(VALUE))+'º';
  end;
end;
até funcionou em parte...ele mostrou os 4 clientes maiores.....só não terminou o relatorio corretamente...derepente você saberia como fazer para o relatório em cima deste componente e encerra-lo corretamente...
se você Aborta a execução, não tem como terminar corretamente. Mas, a sua idéia é basicamente o que eu propús, apenas que da forma que não é correta. Faz o seguinte, veja se consegue implementar o lance do OnNeedData. Primeiro, retire a sua consulta principal (Qry1, se não me engano) da propriedade DataSet do QuickRep (deixe esta propriedade em branco)
TFormRanking = class(TForm)
...
private
  ContaHanking :integer;
end;
...

procedure TFormRanking.QuickRep1BeforePrint(sender ....);
begin
  ...
  Qry1.First;  // posicionamos no início antes da impressão ou visualização
  ContaHanking := 0; // inicializa contador
end;

procedure TFormRanking.QuickRep1OnNeedData(sender :TObject; var MoreData :boolean);
begin
  ...
  MoreData := (ContaHanking < 20) and (not Qry1.EOF);  // vai listar os 20 primeiros registros
 // MoreData indica se há dados a serem impressos, é chamado após a impressão de cada "linha"
  if MoreData then
  begin
    Qry1.Next;  // avançamos na mão para o próximo registro
    Inc(ContaHanking); // incrementamos item impresso
  end;
end;

Tenta aí e vê se sai...

Link to comment
Share on other sites

  • 0
Tenta aí e vê se sai...

R.: Bingo....tu é o cara....deu certo....na pinta. :D

Carinha...uma coisa que queria perguntar a algum tempo...Q

Qual a dirença da Variavel abaixo do private p/ a variavel abaixo do Var??

private
  ContaHanking :integer;
para
var
  FormRanking: TFormRanking;
  TOTALGFRETE:REAL; //VARIVEL QUE PEGA O VALOR TOTAL GERAL DO FRETE

Valeu...Grato ;)

Link to comment
Share on other sites

  • 0
Tenta aí e vê se sai...

R.: Bingo....tu é o cara....deu certo....na pinta. :D

Viu, não tinha nada de complicado ;)

Qual a dirença da Variavel abaixo do private p/ a variavel abaixo do Var??
Bom, vamos ver se consigo explicar isto descentemente...

Declarar dentro da cláusula private de uma classe, resulta em que esta variável será acessível (visível) apenas na unit (ou módulo) onde a classe está declarada.

Por ex., supondo que a unit que você colocou seu form em questão chame-se uFormHanking, esta seria a unit na qual as variáveis private da(s) classe(s) estarão visíveis. Qualquer código que você coloque nesta unit, até mesmo de uma outra classe, poderá referenciar a variável (devidamente precedida pela classe) sem problemas. Assim, se você tivesse qualquer outro código, nesta unit, que fizesse a seguinte referencia:

if FormRanking.ContaHanking then

não haveria qualquer problema na compilação.

Mas se, por exemplo, no form principal (outra unit) onde você cria seu relatório, você tentar fazer a mesma referência terá como resultado um erro de compilação, pois a variável neste ponto não "existirá".

Com relação a classes, há ainda outras "diretivas" de visibilidade: Public (visíveis por todos os módulos), Protected (visíveis apenas dentro da classe), Published (aplicados a propriedades, é similar a Public, exceto que o a informação pode ser gerada em run-time)

Já declarar uma variável fora de uma classe, há duas possibilidades:

- se declarada antes da sessão Implementation, torna-se "global". Voce pode referenciá-la de qualquer lugar desde que faça referência à unit onde a mesma está definida.

- se declarada após a sessão Implementation, torna-se "loca" à unit (modulo) onde está definida.

Não sei se ficou claro, uma coisa é eu entendê-las, outra é conseguir explicar. :D

Talvez algum outro colega possa corrigir ou incrementar mais alguma informação.

Abraços.

Link to comment
Share on other sites

  • 0

Entendi ...sim...muito boa explicação....peguei o esquema....realmente eu só sabia sobre a variavel global...as demais não sabia mesmo..

valeu..Grato

Micheus...tava testando com dados reais...o exemplo que você me passou:

Faz o seguinte, veja se consegue implementar o lance do OnNeedData.

Primeiro, retire a sua consulta principal (Qry1, se não me engano) da propriedade DataSet do QuickRep (deixe esta propriedade em branco)

CODE

TFormRanking = class(TForm)

...

private

ContaHanking :integer;

end;

...

procedure TFormRanking.QuickRep1BeforePrint(sender ....);

begin

...

Qry1.First; // posicionamos no início antes da impressão ou visualização

ContaHanking := 0; // inicializa contador

end;

procedure TFormRanking.QuickRep1OnNeedData(sender :TObject; var MoreData :boolean);

begin

...

MoreData := (ContaHanking < 20) and (not Qry1.EOF); // vai listar os 20 primeiros registros

// MoreData indica se há dados a serem impressos, é chamado após a impressão de cada "linha"

if MoreData then

begin

Qry1.Next; // avançamos na mão para o próximo registro

Inc(ContaHanking); // incrementamos item impresso

end;

end;

Testando como disse acima com dados reais..notei agora..que tem uma falhilha.....sempre o CLIENTE em primeiro lugar não aparece...eu sei porque como fiz varios tipos de relatorio de ranking...então comparei e notei que sempre o primeio não aparece...ou seja..aparece pra mim assim:

aparece como primeiro ....o segundo na real.

depois o segundo .....é o terceiro na real

depois o terceiro....é o querto na real..e assim por diante...

e

o verdadeiro cliente em primeiro lugar não aparece...em colocação alguma...é como ele passasse por cima..e desconsiderasse ele...

Tens ideia do problema???

Grato

Link to comment
Share on other sites

  • 0
Testando como disse acima com dados reais..notei agora..que tem uma falhilha.....sempre o CLIENTE em primeiro lugar não aparece...eu sei porque como fiz varios tipos de relatorio de ranking...então comparei e notei que sempre o primeio não aparece...ou seja..aparece pra mim assim:

aparece como primeiro ....o segundo na real.

depois o segundo .....é o terceiro na real

depois o terceiro....é o querto na real..e assim por diante...

e

o verdadeiro cliente em primeiro lugar não aparece...em colocação alguma...é como ele passasse por cima..e desconsiderasse ele...

Tens ideia do problema???

é eu até estava esperando por um questionamento como este. Na verdade estava achando que não seria impresso o último, mas foi o contrário....

Apesar de saber que funciona, as vezes não lembro de alguns detalhes que acabo ajustando durante durante os testes.

Parece, que ao contrário do que mencionei ontem, OnNeedData ocorre antes da impressão do registro e não depois - captou?!

Então, altere para:

procedure TFormRanking.QuickRep1OnNeedData(sender :TObject; var MoreData :boolean);
begin
...
  MoreData := (ContaHanking < 20) and (not Qry1.EOF); // vai listar os 20 primeiros registros
end;
e acrescente no AfterPrint da GroupFooter (se não existir, coloque uma com altura mínima):
procedure TFormRanking. ... AfterPrint(sender ....);
begin
  if not Qry1.EOF then
  begin
    Qry1.Next; // avançamos na mão para o próximo registro
    Inc(ContaHanking); // incrementamos item impresso
  end;
end;

o objetivo desta banda é garantir o avanço da Qry1, apenas, após que todos os registros da Qry2 (que está vinculada a Qry1) tenham sido impressos.

Acho que agora vai. :)

Link to comment
Share on other sites

  • 0

Oba...Micheus..agora fechou...testado e aprovado...deu certo..coloquei no:

procedure TFormRanking.QRSubDetail1AfterPrint(Sender: TQRCustomBand;
  BandPrinted: Boolean);
begin
 if not Query1.EOF then
  begin
    Query1.Next; // avançamos na mão para o próximo registro
    Inc(ContaHanking); // incrementamos item impresso
  end;
end;

e deu certo...pois só tinha a banda columaHeader e SubDetail e Sumary...então coloquei na SubDetail..e deu certo.

Comparei com outros dois relatorio de ranking e deu tudo certo.

Bom é isto ai...chega de encher a tua paciência :) ....vamos encerrar este tópico :D ...foi muito proveitoso esta discussão deste tópico com certeza vai ajudar mais usuários..pois foi sanado mtas dúvidas.

Um Grande Abraço e muito grato pela ajuda.

t+

:D

Edited by Eder
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share



  • Forum Statistics

    • Total Topics
      151k
    • Total Posts
      649.1k
×
×
  • Create New...