Page 1 of 1
Mysql & Busqueda Incremental xBrowse
Posted: Sat Dec 05, 2009 2:28 am
by Mauricio
Hola
estoy intentando hacerme una busqueda incremental con TMySql y xBrowse, capturo la tecla con bKeydown, pero no encuentro como refrescar el browse que origino la busqueda, despues de hacerle un filtro a la tabla con los datos que estaba buscando.
Code: Select all
#include "fiveWin.ch"
#include "xbrowse.ch"
static oBrw, cBuscador
/*******************************************************************/
function Departamentos()
local oCol, cQuery, oDatos, oDlg
LOCAL aBtn := array( 8 )
local oBoton1, oBoton2
local oDeptos, oFont1
local oEsperar := Esperar("Cargando departamentos ..... espere por favor ...")
cBuscador := ''
IF oMysql:netErr()
MSGINFO( cMensajeSql, cProgram )
RETURN NIL
ENDIF
DEFINE FONT oFont1 NAME 'MS Sans Serif' SIZE 0,-10 BOLD
oDeptos := oMysql:Query( "SELECT * FROM departamentos ORDER BY nombre ")
IF oDeptos:netErr()
MSGINFO( cMensajeSql + ' [departamentos]', cProgram )
RETURN NIL
ENDIF
oEsperar:end()
DEFINE DIALOG oDlg RESOURCE "DEPTO0" TITLE "Catalogo de Departamentos"
oDlg:lHelpIcon := (.f.)
oBrw := TxBrowse():New(oDlg)
SetMyBrwSql( oBrw, oDeptos )
oCol := oBrw:AddCol()
oCol:bStrData := { || strzero(MyCampo(oDeptos,"codigo"),3) }
oCol:cHeader := "Código"
oCol := oBrw:AddCol()
oCol:bStrData := { || MyCampo(oDeptos,"nombre") }
oCol:cHeader := "Descripción"
oCol := oBrw:AddCol()
oCol:bStrData := { || transform(MyCampo(oDeptos,"descuento"),'999%') }
oCol:cHeader := "% descuento"
oCol:nDataStrAlign := AL_RIGHT
oCol:oDataFont := oFont1
oBrw:CreateFromResource(101)
oBrw:bKeyDown := { | nKey | MisTeclas( nKey, oBrw, oDeptos ) }
oBrw:aCols[ 03 ]:bClrStd := {|| { iif( oDeptos:fieldGet('descuento') > 0, CLR_RED, CLR_WHITE), CLR_WHITE } } // nombre
oBrw:bClrHeader := { || {CLR_MAGENTA,CLR_WHITE }}
oBrw:bClrFooter := { || {CLR_GREEN,CLR_WHITE } }
oBrw:bClrSel := { || {CLR_CYAN,CLR_WHITE } }
ACTIVATE DIALOG oDlg CENTER ON INIT CreaBarra(oDlg, oDeptos)
oDeptos:end()
oDeptos := NIL
oFont1:end()
RETURN NIL
static function CreaBarra(oDlg, oDeptos)
return nil
/*******************************************************************/
static function MisTeclas( cSeek, oBrw, oDeptos )
local cTecla := chr(cSeek)
local cChar := upper(cTecla)
local oDlg, oFont, oGet1
cBuscador := cBuscador + cChar
local oBuscar := oMysql:Query( "SELECT * FROM departamentos ORDER BY nombre WHERE nombre LIKE '" + cBuscador + "'%'")
oBrw:Refresh()
oDeptos:refresh()
// en esta parte de aqui, es donde deberia asignarle la nueva data al browse, pero no doy con bola
return nil
Saludos,
Mauricio
Re: Mysql & Busqueda Incremental xBrowse
Posted: Sat Dec 05, 2009 3:15 am
by wmormar
Mau,
contestado desde el messenger...
Re: Mysql & Busqueda Incremental xBrowse
Posted: Sat Dec 05, 2009 6:52 am
by Mauricio
Don Willians gracias.
lo anoto para que los demas vean la solucion, si pasan por lo mismo.
Code: Select all
static function MisTeclas( cSeek, oBrw, oTabla, oSay )
local cTecla := chr(cSeek)
local cChar := upper(cTecla)
IF cSeek == VK_BACK .OR. cSeek == VK_ESCAPE
cBuscador := ''
oSay:setText(cBuscador)
oTabla:cQuery := "SELECT * FROM vendedores ORDER BY nombre"
oTabla:refresh()
oBrw:refresh(.t.)
return nil
ENDIF
IF cSeek == VK_RETURN // Edicion del vendedor
cBuscador := ''
oSay:setText(cBuscador)
AddDeptos(.f., oTabla)
oTabla:refresh()
oBrw:refresh()
ENDIF
IF cSeek == VK_INSERT // agregar vendedor
cBuscador := ''
oSay:setText(cBuscador)
AddDeptos(.t., oTabla)
ENDIF
IF cSeek == VK_DELETE // borrar vendedor
cBuscador := ''
oSay:setText(cBuscador)
deleteVendedor(oTabla)
ENDIF
if cSeek >= 30 .AND. cSeek <= 132
cBuscador := cBuscador + cChar
else
return nil
endif
oSay:setText(cBuscador)
// aqui esta el truco =====, pueden usar LIKE con % al inicio y final, si lo ponemos al inicio y final es como
// contenido en $ de Clipper, si lo ponemos solo al inicio ira tomando _ al inicio
// tambien se puede usar LEFT( nChar)
oTabla:cQuery := "SELECT * FROM vendedores WHERE nombre LIKE '%" + cBuscador + "%'"
oTabla:gotop()
oTabla:refresh()
oBrw:refresh(.t.)
return nil
Saludos
Mauricio
Re: Mysql & Busqueda Incremental xBrowse
Posted: Wed Dec 09, 2009 10:08 am
by Biel EA6DD
Hola Mauricio, un poco tarde llega mi respuesta porque veo que ya lo tienes solucionado. De todas formas si quieres darle un vistazo, aqui tienes una alternativa, usando el metodo Find del recordset (evita el trafico al servidor que genera las sentencias Select), y usando los metodos própios de la clase xBrowse para busquedas incrmentales.
http://bielsys.blogspot.com/2008/04/usa ... o-y-2.html
Code: Select all
...
oBrw:bSeek := { | c | Busca(c,oRs) }
oBrw:oSeek := oSay
oBrw:SetAdo(oRs)
...
//---------------------------------
STATIC FUNCTION Busca(cBuscar,oRs)
LOCAL nLen:=Len(cBuscar)
STATIC nLenAnt
DEFAULT nLenAnt:=0
IF Len(cBuscar)>1
IF(nLenAnt>nLen,oRs:MoveFirst(),)
oRs:Find( "CliDes LIKE '"+cBuscar+"*'",,1)
ELSE
oRs:MoveFirst()
IF !Empty(cBuscar)
oRs:Find( "CliDes LIKE '"+cBuscar+"*'",,1)
ENDIF
ENDIF
nLenAnt:=nLen
RETURN !(oRs:Eof.OR.oRs:Bof)
Re: Mysql & Busqueda Incremental xBrowse
Posted: Wed Dec 09, 2009 2:32 pm
by Armando
Biel:
Excelente solución !, solo hay que tomar en cuenta un detalle, la busqueda que se hace con la solución de Mauricio se hace a la Tabla que hay en el servidor, de ahí tu acertado comentario sobre la sobre carga al servidor, mientras que la busqueda que se hace con tu solución se hace sobre el objeto RecordSet que es una copia de la tabla del lado del cliente.
Sentado lo anterior es bueno aclarar que si por alguna razón la tabla en el servidor fue actualizada con nuevos registros estos no van a estar en el RecordSet a menos de que se haga un Refresh, lo que podría provocar algunos errores.
Supongamos que estamos dando Altas de nuevos clientes pero no somos los unicos que podemos hacerlo algunas otras terminales tambien tiene esa autorización, lo lógico es que antes de realizar el alta del nuevo cliente primero revisemos que no este registrado, esta revisión debe ser a través de una busqueda que en el caso de la solución de Mauricio, aunque más lenta, sería más eficiente en cuento a resultado, mientras que la solución que ofrece Biel, aunque remota, podría caber la posibilidad de duplicar algunos clientes.
Solo mis dos centavos.
Saludos al foro
Re: Mysql & Busqueda Incremental xBrowse
Posted: Wed Dec 09, 2009 6:10 pm
by Mauricio
Biel,
gracias por tu sugererencia.
el problema para mi es este.
tengo un catalogo de productos de cerca de 38mil, el cual se comparte con 8 tiendas remotas,
si cargo la tabla completa al inicio se hace una pesadilla cargar los 38mil registros, con los cuales ya podria hacer la busqueda como sugieres.
lo que hago es cargar solo 250 registros al inicio o 100, de ahi el usuario ya puede empezar a teclear lo que busca y le va apareciendo, lo que me importa del catalogo es ver en caso de que uno de los almacenes no tenga el producto, saber en ese momento quien lo tiene.
por eso debo estar revisandolo en cada momento, porque todos estan vendiendo al mismo tiempo, es un punto de venta que a lo mejor en 2 minutos ya me vendio los productos y yo sigo pensando que los tiene porque la tabla la cargue al inicio.
es como lo comenta perfecto don Armando, la informacion debe estar actualizada en ese instante no me sirve de hace 3 o 5 minutos.
con la solucion que se esta haciendo es bastante rapido, solo le puse que empezara a buscar cuando el usuario escribiera mas de 2 letras.
saludos cordiales,
Mauricio
Re: Mysql & Busqueda Incremental xBrowse
Posted: Wed Dec 09, 2009 9:31 pm
by Adolfo
Mauricio....
La solucion es tener una funcion que se gatille con el OnChange del Browse, que pregunte en el momento por el stock y lo muestre donde tu quieras dentro del dialogo.
Esa funcion seria sencilla...
.....
oBrw:bChange:={ || RefrescaStock(oDbProd:CODIGO) }
.....
Function RefrescaStock(codigobusca)
Local nStock:=0
Local oCmd
Local oRsCmd
oCmd:=TOleAuto():New("ADODB.Command")
oCmd:CommandText := "select STOCK from productos where CODIGO ='" + codigoBusca + "' limit 1"
oCmd:CommandType := adCmdText
oCmd:ActiveConnection:=oCn
oRsCmd:=oCmd:Execute()
nStock:=oRsCmd:Fields( 0 ):value
oRsCmd:Close()
If nStock <> Nil
oSayStock:SetText(Str(nStock))
oSayStock:Refresh()
Endif
Return Nil
Esa funcion deberia demorarse milisegundos...y le puedes poenr lo parametros que quieras para controar cuando llamar al recordset o no...
Con eso liberas el trafico y obtienes VELOCIDAD....
Saludos
DEsde Chile
Adolfo
Re: Mysql & Busqueda Incremental xBrowse
Posted: Wed Dec 09, 2009 9:56 pm
by Mauricio
Adolfo,
estas usando ADO?
Saludos,
Mauricio
Re: Mysql & Busqueda Incremental xBrowse
Posted: Wed Dec 09, 2009 10:38 pm
by Mauricio
Adolfo,
en ese supuesto se me complica un poco ir haciendo registro por registro
porque por ejemplo en este caso es una farmacia, le teclean AMOX , de deberia traer todo lo que contenga AMOXCILINA en todas las presentanciones, para saber cual tienes y cual le puedes ofrecer el cliente y si no la tienes en ese puesto, en cual la tienen para hacer la orden que te la traigan o se la reserven al cliente.
pueden ser que coincidan 10-20-60
y seria tardadon que el usuario vaya uno por uno,
Saludos,
Mauricio
Re: Mysql & Busqueda Incremental xBrowse
Posted: Thu Dec 10, 2009 4:45 am
by wmormar
Mauricio,
Creo lo que comenta Adolfo es bueno, solo que no en todas las necesidades se aplica.
También creo que es cuestión de mentalidad, a veces tratamos de "estirar" mucho SQL para simular DBF.
Vuelvo a repetir es por necesidades.
Re: Mysql & Busqueda Incremental xBrowse
Posted: Thu Dec 10, 2009 6:14 am
by Mauricio
Don William,
estoy totalmente de acuerdo con Don Adolfo, por eso le puse "en este supuesto", se me complicaria,
respecto a estirar SQL desgraciadamente los clientes vienen de sistemas hechos en Clipper/FWH y DBF que se acostumbraron tanto que no hacerles casi lo mismo que hacian los sistemas viejos, para ellos es ir para atras.
saludos,
Mauricio
Re: Mysql & Busqueda Incremental xBrowse
Posted: Thu Dec 10, 2009 1:45 pm
by Adolfo
Mauricio...
Conversar con el cliente de las ventajas y desventajas de una tecnologia y la otra es el primer paso para no prometer cosas que no podras hacer.
Segundo, el cambio de la interfaz es necesario si quieres pasar a SQL, los Browses de DBF deben ser modificados y ajustados a la nueva realidad ( SQL, Recordset etc ) y vas a tener que programar updates o refresh mas seguido de lo que crees, esos botones van a estar presentes en la mayoria de los gestores de ABM. o en su defecto programar timers que te refresquen automaticamente los browses o pantallas.
Para tu problema.. un GEt donde tipees lo que buscas, aunque solo sea parte del nombre (amox... por ej ) y al presionar enter, mostrar en el browse lo pertinente. Es proceso debe ser acotado ( es decir ... rapido, sin muchas confirmaciones, 1 o 2 botones, que controle solo los errores, que valide salir con escape, que enter seleccione sin mas confirmaciones etc etc... lo que por el momento se me ocurre ) de tal forma que en unos pocos dias de uso ya sea algo mecanico para el usuario.
De la misma manera, debes tener ese MISMO y EXACTO procedimiento para todas las funciones donde el usuario deba buscar en alguna tabla. asi logras standarizacion dentro del sistema y todos saben que hacer independientemente del modulo donde se encuentren.
Saludos
Desde Chile
Adolfo
Re: Mysql & Busqueda Incremental xBrowse
Posted: Thu Dec 10, 2009 3:08 pm
by wmormar
Mauricio,
Muy de acuerdo contigo.
Adolfo,
Cuando la aplicación es para un solo cliente el proceso aplica en su totalidad, pero cuando son muchos clientes ahi es donde (como decimos por acá) la mula tuerce el rabo, jjejjejjejje
Lo que tenemos muy claro es que no siempre ponemos las reglas los desarrolladores, el usuario final (el que paga) es muy quisquilloso y hay cosas que no debemos hacer, pero las tenemos que hacer.