Página 1 de 3
erro no set filter
Enviado: 20 Fev 2013 01:09
por cjp
Pessoal,
Estou tendo um erro estranho no meu programa compilado no Harbour: o set filter não está funcionando direito.
Estou usando assim:
No Xharbour funcionava perfeitamente.
Mas agora, no Harbour, ele só está filtrando o primeiro registro da base que corresponde ao filtro, embora haja vários.
Isso acontece também em outros pontos do programa onde uso o set filter.
Alguém sabe me dizer por que? Estou fazendo algum errado?
erro no set filter
Enviado: 20 Fev 2013 01:47
por rochinha
Amiguinho,
Meu exemplo:
Código: Selecionar todos
function FiltraNome( cArea,cOrdem,cQueNome )
cBRFiltro := "!DELETED()"
dbSelectArea( cArea ) // Seleciona area requerida
OrdSetFocus( cOrdem ) // Sleciona ordem requerida
dbSetFilter( {|| .t.}, "" ) // Libera filtros na area
cBRFiltro := cBRFiltro + " .and. clientes->nome=" + cQueNome
dbSetFilter( {|| &cBRFiltro. }, &cBRFiltro. )
dbGoTop()
erro no set filter
Enviado: 20 Fev 2013 02:16
por alxsts
Olá!
Não consegue usar OrdScope()?
erro no set filter
Enviado: 20 Fev 2013 12:33
por cjp
Não conheço a OrdScope() nem a Dbsetfilter(). Não achei essas funções no NG do velho Clipper.
Poderiam, por favor, me dar melhor descrição dos seus argumentos e forma de uso exato?
Mas existe algum problema em usar set filter?
Agradeço.
erro no set filter
Enviado: 20 Fev 2013 12:51
por alxsts
Olá!
Você postou na seção Harbour. Está usando Clipper?
OrdScope() só funciona em Clipper 5.3, Harbour e xHarbour. Alem disso, você tem que estar usando o RDD DBFCDX.
Segue um exemplo. No Ord.ch as constantes TOPSCOPE e BOTTOMSCOPE tem os valores 1 e 2, respectivamente Top e Bottom Scope definem uma faixa de chaves de índice que serão consideradas. No exemplo abaixo, somente pessoas com sobrenomes iniciados com as letras entre "E" e "K", incluindo estas,serão mostrados no Browse():
Código: Selecionar todos
// The example demonstrates evaluation of scope code blocks while a
// database is browsed. Although the code blocks return constant values,
// they could return the result of a function call as well.
#include "Ord.ch"
PROCEDURE Main
USE Customer
INDEX ON Upper(LastName+Firstname) TO Cust01
OrdScope( TOPSCOPE , {|| Tone(1000), "E" } )
OrdScope( BOTTOMSCOPE, {|| Tone(500), "K" } )
Browse()
RETURN
Segue um exemplo de DbSetFilter(), embora eu não a recomende:
Código: Selecionar todos
// The example demonstrates the effect of a filter condition
PROCEDURE Main
USE Customer
INDEX ON Upper(LastName) TO Cust01
GO TOP
? Recno(), Lastname // result: 28 Abbey
DbSetFilter( {|| Upper(LastName) > "L" }, ;
'Upper(LastName) > "L"' )
GO TOP
? Recno(), Lastname // result: 182 MacDonald
? DbFilter() // result: Upper(LastName) > "L"
CLOSE Customer
RETURN
erro no set filter
Enviado: 20 Fev 2013 17:10
por cjp
Eu estou usando o Harbour.
Só mencionei o Clipper porque procurei essas funções no NG do Clipper, mas não achei. Como não tenho um NG (ou algo semelhante) do Harbour, quando se trata de função que já tinha no Clipper, tento consultar o NG do Clipper.
Não entendi bem como funciona a OrdScope(). Parece que ela não faz filtro, estou correto? Tentei fazer assim:
Código: Selecionar todos
#include "Ord.ch"
INDEX ON acao TO Cust01
OrdScope( TOPSCOPE , {|| Tone(1000), ac1$acao } )
OrdScope( BOTTOMSCOPE, {|| Tone(500), ac1$acao } )
Browse()
Mas não filtrou.
Quanto à DbSetfilter(), está dando o mesmo problema que dava no set filter, ou seja, só aparece a primeira ocorrência do filtro. E dbfilter() não está retornando nada. Estou fazendo assim:
Código: Selecionar todos
DbSetFilter( {|| ac1$acao })
GO TOP
cls
? DbFilter() // result: Upper(LastName) > "L"
Será que estou fazendo algo errado?
erro no set filter
Enviado: 20 Fev 2013 19:08
por alxsts
Olá!
Qual o conteúdo de ac1$acao? Tem que ser um valor do mesmo tipo da chave de índice e que possa existir no índice.
erro no set filter
Enviado: 20 Fev 2013 19:53
por rochinha
Amiguinho,
O
dbSetFilter precisa de
dois parametros:
Teste:
DbSetFilter( )
Código: Selecionar todos
? cSetFilter := ac1$acao
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
Agora mostre-nos trecho do código que cria sua variável
ac1$acao. Já estamos tendo de adivinhar pra dar resposta.
Coloque o trecho acima no seu programa e nos diga qual foi o conteudo mostrado na linha
? cSetFilter := ac1$acao.
Se a filtragem não esta resultado em registros é porque nada que valha a filtragem está sendo passado para o comando.
E também já estou velho, nem lembro o porque do uso que voce faz de
$, em
{|| ac1$acao }.
Pelo que entendi:
Voce tem uma variável chamada
ACL e está criticando o conteúdo do campo
acao.
Pois bem:
Voce não terá filtragem nenhuma porque, se a variável
acl retornar
falso caso não seja encontrada no campo
acao.
Para usar o operador
$ voce estará perguntando:
procure ACL dentro de ACAO
O que esta ocorrendo é que o comando de filtragem está recebendo somente,
.T. ou
.F. puros, ou seja:
ou:
Isto não irá fazer nenhum efeito.
Voce deve passar uma expressão que valha a pena, exemplo:
Voce que pesquisar por um código dentro de um campo e filtrar tudo relativo:
Código: Selecionar todos
nNumero := "123"
cSetFilter := "TABELA->CODIGO = " + strZero( nNumero, 5 )
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
Ou:
Código: Selecionar todos
cNome := "ROCHA"
cSetFilter := "upper(TABELA->NOME) = " + upper( cNome )
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
erro no set filter
Enviado: 21 Fev 2013 01:31
por cjp
Cara, agradeço muito tua tentativa em ajudar, mas eu ainda não consegui entender como usar essa dbsetfilter().
Minha função original, com set filter, estava assim:
Código: Selecionar todos
index on substr(acao,1,4) to inddt for !empty(acao) unique
go bottom
go top
clear
@ 3,1 say "Escolha as ações:"
private v1[1]
v1[1]="Acao"
do while .t.
dbedit(5,1,22,20,v1)
if lastkey()=27
exit
endif
if deleted()
flock()
recall
else
flock()
dele
endif
enddo
unlock
ac1=space(20)
ac2=space(20)
ac3=space(20)
ac4=space(20)
ac5=space(20)
go top
locate for deleted()
if found()
ac1=substr(acao,1,4)
if "Adia"$ac1
ac1="Adia"
endif
continue
if found()
ac2=substr(acao,1,4)
continue
if found()
ac3=substr(acao,1,4)
continue
if found()
ac4=substr(acao,1,4)
continue
if found()
ac5=substr(acao,1,4)
continue
if found()
tone(261.7,3)
@ maxrow(),5 say "Erro: pesquisa máxima de 5 ações ultrapassada"
inkey(5)
endif
endif
endif
endif
endif
if usebase(athor)=.t.
flbs()
recall all
unlock
endif
do case
case !empty(ac5)
set filter to ac1$acao .or. ac2$acao .or. ac3$acao .or. ac4$acao .or. ac5$acao //.or. empty(hora)
case !empty(ac4)
set filter to ac1$acao .or. ac2$acao .or. ac3$acao .or. ac4$acao //.or. empty(hora)
case !empty(ac3)
set filter to ac1$acao .or. ac2$acao .or. ac3$acao //.or. empty(hora)
case !empty(ac2)
set filter to ac1$acao .or. ac2$acao //.or. empty(hora)
otherwise
set filter to ac1$acao //.or. empty(hora)
endcase
else
use
return
endif
Portanto, as variáveis ac1, ac2, ac3, ac4 e ac5 são variáveis texto que correspondem ao campo acao, da base.
O objetivo é listar os registros da base cujo campo acao correspondem às variáveis escolhidas pelo usuário.
Com set filter sempre funcionou perfeitamente, até eu mudar do xHarbour para o Harbour. Ainda não entendi porque não funciona mais. O set filter não funciona no Harbour? E não tem nada simples que lhe equivalha?
Testei os teus exemplos, mas não funcionou. Embora eu não saiba se fiz corretamente. Testei assim:
Código: Selecionar todos
cSetFilter := acao + ac1
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
Agradeço a ajuda.
erro no set filter
Enviado: 21 Fev 2013 03:20
por rochinha
Amiguinho,
Se me clareou as idéias tenho pra mim que voce esta tentando simular o CTRL+Click do mouse que damos quando queremos marcar itens aleatórios em um browse.
Pelo que vi voce deleta os registros que deseja depois filtrar, mas se o seu aplicativo contivar a diretiva
SET DELETE OFF os registros se tornarão invisiveis e quando voce tentar filtrar nada será mostrado.
Uma saida para isto possa ser um campo extra, tipo um flag, que se marcado poderá permitir a filtragem por ele.
Mas se voce deseja filtrar a tabela pelo campo desejado e que contenha até 5 parametros voce pode passar o conteudo das variáveis assim:
Código: Selecionar todos
Set Delete Off
cSetFilter := [!deleted()]
cSetFilter := cSetFilter + iif( !empty( AC1, [ .OR. TABELA->ACAO $ "] + alltrim( AC1 ) + ["], [] )
cSetFilter := cSetFilter + iif( !empty( AC2, [ .OR. TABELA->ACAO $ "] + alltrim( AC2 ) + ["], [] )
cSetFilter := cSetFilter + iif( !empty( AC3, [ .OR. TABELA->ACAO $ "] + alltrim( AC3 ) + ["], [] )
cSetFilter := cSetFilter + iif( !empty( AC4, [ .OR. TABELA->ACAO $ "] + alltrim( AC4 ) + ["], [] )
cSetFilter := cSetFilter + iif( !empty( AC5, [ .OR. TABELA->ACAO $ "] + alltrim( AC5 ) + ["], [] )
? "Filtro: ", cSetFilter
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
Compile este trecho passando aleatóriamente parametros para AC1, AC2,..., AC5 e veja como a string de filtragem é montada.
erro no set filter
Enviado: 21 Fev 2013 11:22
por cjp
Ainda não funcionou, meu amigo.
Na verdade, na primeira parte, eu uso sim o deleted para marcar na base os campos que eu quero filtrar, tomando-os para as variáveis ac1, ac2...ac5.
Mas depois eu dou um recall all. Portanto, daí em diante, o deleted não é mais usado.
A partir daí, a questão é apenas filtrar os campos da base que contenham os conteúdos das variáveis ac1... ac5.
Se eu entendi o que vc fez, o teu filtro estaria considerando o deleted, o que não é o caso. E também está invertido, filtrando pelo campo incluído na variável ([ .OR. TABELA->ACAO $ "] + alltrim( AC1 )), quando deveria ser a variável incluída no campo (ac1 $ TABELA->ACAO). Por isso não filtrou corretamente.
Tentei inverter, mas não funcionou. Na verdade eu ainda não entendi bem a lógica de funcionamento dessa função, por isso não estou conseguindo fazer como deveria.
Por favor, preciso novamente da sua ajuda.
erro no set filter
Enviado: 21 Fev 2013 13:00
por rochinha
Amiguinho
Realmente eu inverti as bolas o correto esta abaixo:
Código: Selecionar todos
AC1 := "scuba"
AC2 := "blue"
AC3 := ""
AC4 := ""
AC5 := ""
use CUSTOMER shared
Set Delete Off
cSetFilter := [!deleted()]
cSetFilter := cSetFilter + iif( !empty( AC1), [ .AND. ("] + alltrim( upper(AC1) ) + [" $ upper(CUSTOMER->company)], [] )
cSetFilter := cSetFilter + iif( !empty( AC2), [ .OR. "] + alltrim( upper(AC2) ) + [" $ upper(CUSTOMER->company)], [] )
cSetFilter := cSetFilter + iif( !empty( AC3), [ .OR. "] + alltrim( upper(AC3) ) + [" $ upper(CUSTOMER->company)], [] )
cSetFilter := cSetFilter + iif( !empty( AC4), [ .OR. "] + alltrim( upper(AC4) ) + [" $ upper(CUSTOMER->company)], [] )
cSetFilter := cSetFilter + iif( !empty( AC5), [ .OR. "] + alltrim( upper(AC5) ) + [" $ upper(CUSTOMER->company)], [] )
cSetFilter := cSetFilter + [)]
? "Filtro: ", cSetFilter
dbSelectArea( "CUSTOMER" )
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
dbGoTop()
Browse()
Neste caso o
Set Delete Off mostra até os deletados.
Faça o download do arquivo
customer.dbf.zip(elimine o .ZIP), compile o trecho acima e rode. Ou teste com
custtest.exe.
erro no set filter
Enviado: 21 Fev 2013 23:04
por cjp
Testando com o .exe e o .dbf que vc mandou, funcionou perfeitamente.
Mas, quando transformo para usar no programa, dá o seguinte erro:
A linha onde está dando o erro é esta:
Estou colocando assim no meu programa:
Código: Selecionar todos
Set Delete Off
cSetFilter := [!deleted()]
cSetFilter := cSetFilter + iif( !empty( AC1), [ .AND. ("] + alltrim( upper(AC1) ) + [" $ upper(acao)], [] )
cls
? "Filtro: ", cSetFilter
wait ""
dbSetFilter( {|| &cSetFilter. }, &cSetFilter. )
Ainda estou fazendo errado?
erro no set filter
Enviado: 22 Fev 2013 02:55
por rochinha
Amiguinho,
Nem precisarei testar para saber que voce deixou de fora um parentesis. Como prova valendo 10, deixo voce descobrir.
Testes só dão resultados por prova e erro, ou, prova e acerto.
erro no set filter
Enviado: 22 Fev 2013 09:48
por asimoes
Nesse caso eu trabalharia com indices temporários e com ordscope que é bem mais rápido que set filter ou dbsetfilter