Page 1 of 1

ayuda para seek o search

Posted: Sun Jul 30, 2006 2:59 pm
by sildata
Amigos Saludos a todos:
Debido a la necesidad personal y de otros colegas del foro y aun mas a la
sugerencia del Sr. Antonio, me atrevi a intentar crear una funcion para hacer
unas busquedas rapidas en todos _ de una base de datos o tablas lo
cual creo haberlo conseguido, mas lo que me ha resultado imposible es poder
calcular exactamente el numero de registro donde ocurre la coincidencia.
Dejo ha los demas colegas el reto a colaborar en terminar lo que yo no pude.
Pruebenla con tablas muy grandes y se sorprenderan al igual que yo, de la
rapidez de la busqueda; al encontrar la solucion por favor envienmela.
La idea de esta rutina es complementar un "SEEK", al no encontrar resultados
pues simple y rapidamente traer registros parecidos que contengan esta palabra
motivo del fallido "SEEK".

Atentatamente RODOLFO SILVA
sildata@cantv.net

* ---------------------
FUNCTION MAIN(nmbbd,cBuscar)
* nmbbd= es el nombre de la tabla *.dbf donde se efectuara la busqueda
* cBuscar= es la palaba o strind a buscar en todos _ de la *.dbf
* ---------------------
LOCAL nfpos := 0, nDpos := 0
LOCAL g_recsize, g_header, g_lastrec, g_cdata, g_offset, G_CTDOR := 0
LOCAL a_data := {}
LOCAL g_handle, nheader, dbfheader, cfilename :=nmbbd
g_handle := FOPEN( cfilename )
g_recsize := BIN2I( FILESTR( cFileName, 8, 10 ) ) //tama¤o del registro de la DBF
g_header := BIN2I( FILESTR( cFileName, 2, 8 ) ) //tama¤o del header de la DBF
g_lastrec := BIN2L( FILESTR( cFileName, 2, 4 ) ) // numero de registros en la DBF
* lee todo el header con el tama¤o calculado
DBFHeader := FILESTR( cFileName, g_header, 10 ) //contenido del header de la DBF
DO WHILE .NOT. feof( g_handle )
g_cdata := FREADSTR( g_handle, g_recsize * 10 )
nfpos := g_ftell( g_handle ) // posicion del pointer en el archivo
g_offset := AT(cBuscar, g_cdata )
IF g_offset > 0
* aqui deberia calcular el numero de registro RECNO() Y agruparlos
* en una matriz para al final devolver la matriz al programa llamante
* aadd(a_data, int((g_lastrec - (g_offset-g_header)) / g_offset)+1)
ENDIF
ENDDO
FCLOSE( g_handle )
RETURN(a_data)
* ---------------------
FUNCTION fEOF( nHandle )
* ---------------------
LOCAL nCurrentPos, nEOF
nCurrentPos := FSEEK( nHandle, 0, 1 ) //busca desde la posicion actual
nEOF := FSEEK( nHandle, 0, 2 ) //busca desde el fin de archivo
FSEEK( nHandle, nCurrentPos, 0 ) // busca desde el inicio de archivo
RETURN nEOF <= nCurrentPos
* ---------------------
FUNCTION G_FTell( nFileHandle )
* ---------------------
RETURN ( FSEEK( nFileHandle, 0, 1 ) ) // devuelve la posicion actual
* ---------------------
* EOF: PRUEBA.PRG

Posted: Sun Jul 30, 2006 9:22 pm
by joseluisysturiz
Hola SILDATA, espero me recuerdes, JOSE LUIS, voy probar esto a ver si te ayudo, pero creo que si usas 1 contador cada ves que hay concidencia y el recno(), podrias saber en que registro se realizo la concidencia, no se si es lo que quieres, escribe a mi privado...saludos desde Caracas-Venezuela.estemos en contacto, te perdistes...

Posted: Mon Jul 31, 2006 11:30 am
by manuramos
No se muy bien si me he enterado. ¿Deseas saber un valor similar a un RecNo()?

Por lo que veo, no estoy muy acostumbrado a los ficheros de bajo nivel, lees los registros de 10 en 10, y dentro de ese grupo haces un AT. Con lo cual, conoces la posición dentro del grupo ( g_offset ). También sabes cuanto mide cada registro. ( g_recsize ) y donde está el puntero ( nfpos ).

NUMREG := INT(g_offset / g_recsize)+1 debe de decirte en qué registro, dentro del grupo, está la coincidencia. Eso si el primer elemento del grupo es un 0. Si es un 1 sería: INT(g_offset-1) / g_recsize)+1. Es cuestión de porbar.

NUMGROUP := INT((nfpos-g_header) / (g_recsize*10))+1 tendría que decirte en qué grupo se realizó la búsqueda AT. Como antes Si nfpos no empieza por 0, sino por 1 sería: INT((nfpos-g_header-1) / (g_recsize*10))+1. Claro que lo que interesa es que el primer grupo sea conocido como el número 0, para que al sumarle NUMREG nos dé el RecNo() correcto. Por lo que hay que quitar el '+1' final:

NUMGROUP := INT((nfpos-g_header) / (g_recsize*10)) o NUMGROUP= := INT((nfpos-g_header-1) / (g_recsize*10))

Finalmente RECNO := (NUMGROUP*10)+NUMREG.

Una coincidencia en grupo 0, tramo 3 dará RECNO = 3. (tramo 3º del primer grupo = 3º registro).
Una coincidencia en grupo 1, tramo 5 dará RECNO = 15 (tramo 5º del segundo grupo = 15º registro).
...
Una coincidencia en grupo 14, tramo 6 dará RECNO = 146 (tramo 6º del 15avo grupo = 146º registro).
...
Etc.

Debería funcionar. Es cuestión de probar.

Un saludo a todos.