Page 1 of 1

Uso de DBSETFILTER y SET FILTER con variables.

Posted: Wed Sep 26, 2007 11:46 am
by new_indika
Intentando sustituir un filtro construido por SET FILTER por uno hecho con DBSETFILTER, me he encontrado con un error que no soy capaz de solventar. Os adjunto un codigo de "ejemplo".

Code: Select all

LOCAL cCadena:="MANUEL"

SET FILTER TO AT(cCadena, _FIELD->NOMBRE) > 0
//Este filtro, funciona perfectamente.
Ahora supongamos, que en vez de usar este código, usamos este otro:

Code: Select all

LOCAL cCadena:="MANUEL"
LOCAL cFiltro, bFiltro

cFiltro:="AT(cCadena, _FIELD->NOMBRE) > 0"
bFiltro:="{||"+cFiltro+"}"
DBSETFILTER(&bFiltro, cFiltro)
Si lo hago así, recibo un error en tiempo de ejecución que me señala que DBSETFILTER no reconoce la variable cCadena, pero en cambio el SET FILTER si.

He intentado mandarla como 'parametro' al codeblock:

Code: Select all

bFiltro:="{|cCadena|"+cFiltro+"}"
. Tampoco funciona así.

¿Como puedo hacer para que DBSETFILTER me reconozca la variable local? Curioso es que este trozo de código tampoco funciona.

Code: Select all

SET FILTER TO AT(cCadena, _FIELD->NOMBRE) > 0 //Establezco el filtro
cFiltro:=DBFILTER() //Lo envio a una cadena de caracteres
DBCLEARFILTER() //Elimino filtros activos
bFiltro:="{||"+cFiltro+"}" 
DBSETFILTER(&bFiltro, cFiltro) //Lo asigno...
Provoca el mismo error en tiempo de ejecución. ¿Alguna sugerencia? Gracias de antemano.

Posted: Wed Sep 26, 2007 12:35 pm
by QAZWSX2K
HAS PROBADO

cFiltro:="AT(&cCadena, _FIELD->NOMBRE) > 0"

Posted: Wed Sep 26, 2007 12:47 pm
by new_indika
Si. De hecho fue lo primero que probe. Provoca el mismo error en tiempo de ejecución. DBSETFILTER no es capaz de reconocer la variable local si se le manda via & como si se le envia via @.

He encontrado una solución drástica para este problema, que me he ha dado mas de tres o cuatro horas de quebraderos de cabeza hasta que por fin, he encontrado el como, pero estoy seguro de que hay alguna manera de que el codeblock reconozca una variable pasandosela como parametro... He aqui el codigo:

Code: Select all

LOCAL cCadena:="Manuel"
LOCAL cFiltro, bFiltro

cFiltro:="(AT("+CHR(34)+cCadena+CHR(34)+",UPPER(_FIELD->NOMBRE)) > 0"
bFiltro:="{||"+cFiltro+"}"
DBSETFILTER(&bFiltro,cFiltro)
Ojo al dato. Consiste en hacerle pasar a DBSETFILTER los datos 'digeridos'. Lo tedioso del asunto es que hay que pasarle las comillas via CHR (caracter 34) cerrando y abriendo la cadena. Con esto se consigue sustituir la variable por su valor real. No es lo mas optimo, y si alguno de ustedes sabe como hacer para que el codeblock de DBSETFILTER me reconozca la variable, me haría un gran favor.

Posted: Wed Sep 26, 2007 1:20 pm
by Patricio Avalos Aguirre

Code: Select all

dbSetFilter( {|| AT(cCadena, _FIELD->NOMBRE) > 0}, "AT(cCadena, _FIELD->NOMBRE) > 0" )
nota:

Lo puedes hacer tambien utilizando la opcion del compilador /p

este te va generar un archivo.ppo

o sea si colocas SET FILTER TO AT(cCadena, _FIELD->NOMBRE) > 0
el archivo .ppo te lo va traducir
dbSetFilter( {|| AT(cCadena, _FIELD->NOMBRE) > 0}, "AT(cCadena, _FIELD->NOMBRE) > 0" )

saludos

Posted: Wed Sep 26, 2007 2:04 pm
by Carlos Mora
new_indika wrote:Si. De hecho fue lo primero que probe. Provoca el mismo error en tiempo de ejecución. DBSETFILTER no es capaz de reconocer la variable local si se le manda via & como si se le envia via @.

He encontrado una solución drástica para este problema, que me he ha dado mas de tres o cuatro horas de quebraderos de cabeza hasta que por fin, he encontrado el como, pero estoy seguro de que hay alguna manera de que el codeblock reconozca una variable pasandosela como parametro... He aqui el codigo:

Code: Select all

LOCAL cCadena:="Manuel"
LOCAL cFiltro, bFiltro

cFiltro:="(AT("+CHR(34)+cCadena+CHR(34)+",UPPER(_FIELD->NOMBRE)) > 0"
bFiltro:="{||"+cFiltro+"}"
DBSETFILTER(&bFiltro,cFiltro)
Ojo al dato. Consiste en hacerle pasar a DBSETFILTER los datos 'digeridos'. Lo tedioso del asunto es que hay que pasarle las comillas via CHR (caracter 34) cerrando y abriendo la cadena. Con esto se consigue sustituir la variable por su valor real. No es lo mas optimo, y si alguno de ustedes sabe como hacer para que el codeblock de DBSETFILTER me reconozca la variable, me haría un gran favor.
El problema es que las variables locales no pueden ser usadas en expresiones dinámicas, digamos de manera simplificada que el compilador no guarda el nombre.

Si cambias Local cCadena por Private cCadena te funcionará bien, porque las privates se crean en runtime por lo tanto se las puede invocar por nombre. Obviamente son mucho mas lentas.

Yo preferiría usar la opción de armar la expresión entre comillas, la evaluación es más rápida porque no tiene que resolver el nombre de ninguna variable.
Y para optimizar un poquito más, en lugar de usar la función AT() puedes usar el operador $ como en:
cFiltro:= CHR(34)+cCadena+CHR(34)+" $ UPPER(_FIELD->NOMBRE)"
o Bien :

Set Filter to "Manuel"$Upper( _Field->Nombre)

Saludos,

Carlos

Posted: Wed Sep 26, 2007 2:10 pm
by FiveWiDi
QAZWSX2K wrote:HAS PROBADO

cFiltro:="AT(&cCadena, _FIELD->NOMBRE) > 0"
Mejor aún,

cFiltro:="AT(" + cCadena + ", _FIELD->NOMBRE) > 0"

Saludos
Carlos G.