Jump to content

Filtar dois valores ao mesmo tempo


InfoMan
 Share

Recommended Posts

Boa Noite pessoal!

Estou usando um componente TDBF para acessar os dados no meu programa. Acontece que preciso filtrar dois valores ao mesmo tempo. Para que os resultados sejam corretos, preciso que sejam exibidos todos os registros com data posterior a 01/01/2007 e que pertençam a um determinado grupo, por exemplo B019. O campo de data chama "DT_DATA" e o campo de grupo chama "ID_CODIGO". Como faço isso via código?

Tem horas que estou quase desanimando de usar o Lazarus (por ser gratuito) em lugar do Delphi. No Delphi conseguiria fazer as coisas muito mais facilmente com certeza.

Muito obrigado a todos que responderem.

Link to comment
Share on other sites

Podes usar os operadores lógicos para isso...

Por exemplo:

TForm1.Tabela1OnFilterEvent(Sender : TObject; var Accept : Boolean)
begin
     Accept := (Copy(Trim(Tabela1ID_AGRAVO.AsString),1,4) = 'B019') or (StrToDate(Tabela1DT_ENCERRA.AsString) > StrToDate('2007-01-01'));
end;

Assim, o registo será aceito (Accept = True) se o ID_AGRAVO for B019 ou o DT_ENCERRA estiver vazio.

Convém só notar se as datas estão no formato aceite pelo comando StrToDate. Se não estiverem (se te der erro a converter), fazes uma função que converta a data to formato certo.

PS: Embora o Delphi seja de longe melhor que o Lazarus, neste caso específico até ia ser igual, já que o componente TDBF é o mesmo em ambos. Pessoalmente prefiro usar SQL, mas pelo que percebi, aqui estás limitado ao uso deste componente, certo?

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

obrigado por responder.

Infelizmente estou realmente limitado ao componente, já que tenho que trabalhar com dados exportados pelo outro programa que só exporta neste formato.

Tentei fazer como me mostrou, mas infelizmente não deu certo. A mensagem de erro foi essa: "unit1.pas(110,79) Error: Operation "or" not supported for types "Constant String" and "Boolean"

Preciso que as duas condições que sejam atendidas ao mesmo tempo. Provavelmente usando o "And" no lugar do "Or" também vai dar erro.

Como resolvo isso?  Muito obrigado a todos que responderem.

Link to comment
Share on other sites

Diz-me ao certo qual a linha que estás a usar, e diz-me um exemplo de um registo que queiras que apareça, especialmente o formato da data.

O OR por acaso está mal, porque tu queres só os que sejam desse grupo E de uma data posterior à tal. Por isso neste caso tem de ser o AND. O OR serial se quisesses uns e outros.

Para estar a dar esse erro, é possível que seja algum parentessis fora do sitio, por o OR, assim como o AND, o XOR e o NOT, são operadores booleanos. Têm mesmo de dar! 👍

Quanto ao TDBF, podias ainda criar um pequeno programa que simplesmente importasse do DBF para SQL (isso é simples, é só ler de um lado e gravar do outro, sem "calculos"), e depois trabalhar tudo em SQL... 🙂

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Muito obrigado pela atenção.

A linha que estou usando é a seguinte:

Accept := (Copy(Trim(dadosab.FieldByName('ID_CODIGO').AsString),1,4) = 'P371' or 
          (StrToDate(dadosab.FieldByName('DT_DATA').AsString) > StrToDate('20070101')));

O formato que uso aqui é Dia/Mês/Ano.

Poderia me dizer, qual a melhor forma de fazer essa conversão de DBF para SQL no Lazarus?

Mais uma vez, muito obrigado.

EDIT (by nunopicado): Inseridas tags GeShi na linha de código

Link to comment
Share on other sites

Falta-te um parenteses depois do 'P371' e um antes do Copy. Habitua-te a contar os parenteses numa expressão; conta para cima a cada parenteses de abertura '(' e para baixo a cada ')'; no fim tem de dar zero. E se tiveres expressões ao lado dum operador lógico, mete parenteses à volta dessa expressão, para não teres este problema. E o operador lógico deve ser o 'and', como disse o nunopicado.

Link to comment
Share on other sites

Exactamente isso, é o parentesis que falta. E no fim tens um a mais...

Ficaria assim:

Accept := (Copy(Trim(dadosab.FieldByName('ID_CODIGO').AsString),1,4) = 'P371') and 
          (StrToDate(dadosab.FieldByName('DT_DATA').AsString) > StrToDate('20070101'));

Para converter, não te consigo dizer um passo a passo, porque nunca usei o TDBF, mas o conceito é:

1. Crias uma base de dados em MySql, MSSql ou outro do género que queiras trabalhar. Essa DB deverá ter os mesmos campos que tem  a tua DBF.

2. Colocas um componente de acesso ao SQL no teu programa (por exemplo SqlDB que vem com o Lazarus, embora eu pessoalmente prefiro o ZeosLib, que também podes instalar).

3. Estabeleces conexão ao teu DBF (como já fazes agora) e ao SQL.

4. Fazes um ciclo FOR que percorra todos os registos do DBF (tabela a tabela).

Dentro do ciclo, fazes a inserção dos valores lidos do DBF para o SQL:

Ex.:

for i:=0 to dadosab.recordcount-1 do
  begin
    dadosab.RecNo:=i;
    dbSQL.Insert;
    dbSQL.FieldValues['ID_CODIGO']:=dadosab.FieldByName('ID_CODIGO').AsString;
    dbSQL.FieldValues['DT_DATA']:=dadosab.FieldByName('DT_DATA').AsString;
.
.
.
    dbSQL.Post;
  end;

No final de fazeres isto para todas as tabelas, terás todos os teus dados em SQL. Depois é só fazer uma query SQL para teres à mostra apenas os dados desejados...

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

A nível das datas, se estás a usar o / como separador, terás problemas, pois a função StrToDate não reconhece esse separador.

Terás de substituir todas as / por - para poderes fazer a comparação.

Podes fazer assim:

Accept := (Copy(Trim(dadosab.FieldByName('ID_CODIGO').AsString),1,4) = 'P371') and
          (StrToDate(StringReplace(dadosab.FieldByName('DT_DATA').AsString, '/', '-',[rfReplaceAll, rfIgnoreCase])) > StrToDate('01-01-2007'));

A função StringReplace irá substituir todas as / por - antes da comparação

Já agora, devo dizer que, se as datas estivessem no formato aaaa-mm-dd (maior grandeza do lado esquerdo, menor do direito), a comparação seria tão simples como isto:

Accept := (Copy(Trim(dadosab.FieldByName('ID_CODIGO').AsString),1,4) = 'P371') and
          (dadosab.FieldByName('DT_DATA').AsString > '2007-01-01');

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Muito obrigado pelas respostas.

Tentei com o primeiro exemplo e não funcionou. Aí resolvi tentar o segundo com a data no formato AA-MM-DD e deu certo. Consegui fazer a comparação também com datas em branco.

Mais uma vez, muitíssimo obrigado a todos pela valiosíssima ajuda de vocês.

Link to comment
Share on other sites

Mais uma vez, muitíssimo obrigado a todos pela valiosíssima ajuda de vocês.

Às ordens...  👍

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.