Estimado Jorge,
Es más fácil de lo que parece: la búsqueda incremental de TXBrowse se ejecuta a través del codeblock bSeek, que es un DATA
público y reemplazable (está declarado en source/classes/xbrowse.prg:169 con el comentario "block expression for autoincremental
search"). Cada datasource solo le pone un default (SetAdo asigna {|c| ::AdoIncrSeek(c)} en la línea 7044), así que basta con
asignar el tuyo después de cargar los datos.
Tenés dos caminos, según cómo estés trayendo los datos:
Opción 1 (recomendada si usás ADO): lIncrFilter + bFilterExp
En modo lIncrFilter := .t., AdoIncrSeek (xbrowse.prg:8213) evalúa bFilterExp con el texto tipeado y aplica lo que devuelvas como
oRs:Filter. O sea, no reconsultás al servidor: ADO filtra el recordset local, y tu bloque arma la condición multi-palabra.
Code: Select all | Expand
oBrw:lIncrFilter := .t.
oBrw:bFilterExp := { | cSeek | FiltroStock( cSeek ) }
Code: Select all | Expand
function FiltroStock( cSeek )
local cExpr := ""
local cWord
for each cWord in hb_ATokens( AllTrim( cSeek ), " " )
if ! Empty( cWord )
cExpr += If( Empty( cExpr ), "", " AND " ) + ;
"Descri LIKE '*" + StrTran( cWord, "'", "''" ) + "*'"
endif
next
// Ojo: con cSeek vacío hay que devolver algo siempre-verdadero,
// porque AdoIncrSeek solo toca oRs:Filter si cExpr no está vacío
return If( Empty( cExpr ), "1=1", cExpr )
Detalle importante: la propiedad Filter de ADO usa * (también acepta %) como comodín, no la sintaxis de SQL Server. El resultado
equivale a tu LIKE '%APLI%' AND LIKE '%350%' AND LIKE '%ZIO%'.
Opción 2 (cualquier datasource): reemplazar bSeek y reconsultar
Si preferís ir al servidor con tu SELECT exacto, asigná bSeek con tu función, que recibe el string tipeado y debe devolver .T.
si encontró algo (el método Seek() en xbrowse.prg:9798 evalúa ese bloque y hace el Refresh solo si devolvés verdadero):
Code: Select all | Expand
oBrw:bSeek := { | cSeek | BuscarStock( oBrw, oCn, cSeek ) }
Code: Select all | Expand
function BuscarStock( oBrw, oCn, cSeek )
local cWhere := ""
local cWord, oRs
for each cWord in hb_ATokens( AllTrim( cSeek ), " " )
if ! Empty( cWord )
cWhere += If( Empty( cWhere ), "", " AND " ) + ;
"s.Descri LIKE '%" + StrTran( cWord, "'", "''" ) + "%'"
endif
next
oRs := oCn:Execute( "SELECT * FROM dbo.Stock AS s " + ;
If( Empty( cWhere ), "", "WHERE " + cWhere ) + " ORDER BY s.Descri" )
if oRs:RecordCount > 0
oBrw:SetAdo( oRs ) // re-carga el browse con el nuevo recordset
return .t.
endif
return .f.
La opción 2 tiene sentido si la tabla es grande y no querés bajar todo el stock al recordset; para un ABM típico, la opción 1
filtrando local es más fluida (una sola consulta al abrir).
Un par de notas:
• Asigná bSeek/bFilterExp después del SetAdo() (o del NewFrom... que uses), porque esos métodos pisan el default.
• Si tu fuente no es ADO (por ejemplo Dolphin/MySQL), bFilterExp no aplica — ahí usá la opción 2, o fijate que lSeekWild := .t.
ya te da LIKE '%texto%' pero solo con una palabra.
¿Con qué datasource estás trabajando en ese ABM (ADO recordset, conexión directa SQL Server, otra)? Si me pasás el fragmento
donde creás el xBrowse te lo dejo ajustado.