Leandro,
No sé si esto es lo que necesitas:
Ejemplo para trabajar con ADO + RecordSet + Browse:
======================================
En una aplicación cliente servidor, debemos tener UNA SOLA
conexión a la Base de Datos (BD). En cambio, tendremos
múltiples RecordSet. Por tanto es conveniente disponer de una
función para facilitar la creación de estos RecordSet de una
forma sencilla. Tambien podemos tener en nuestra librería,
las funciones SKIPPER() y ADOERROR().
En resumen, una vez creado el objeto RecordSet, la actuación
en el Browse es muy parecido a cuando usamos el objeto
Database de FiveWin.
/////////////////////////////////////////////////
Suponemos que ya tenemos en nuestra libreria la función
F_RecordSet y que en la aplicación que estamos programando,
ya existe una Conexión a la BD que llamaremos oCon.
Ahora vamos a crear un objeto RecordSet y mostrarlo
en un Browse.
En nuestro ejemplo, se trata de un programa de recetas
de cocina,
/////////////////////////////////////////////////
FUNCTION BrwCocina(oCon)
Local lSalvar := .f., oDlg, oLbx, oBtn:= ARRAY(9)
// orden SQL
LOCAL cSql := 'SELECT * FROM RECETAS ORDER BY NOMBRE'
// crea recordset
Local oRs := F_RECORDSET ( oCon, cSql, .t. ) // ver al final
// F_recordset devuelve "nil" si hay error
IF oRs == nil
RETURN nil
ENDI
// Caja de Diálogo -----------------------------------------------------
DEFINE DIALOG oDlg RESOURCE "RECETAS" ;
TITLE " Mi libro de recetas con ORACLE"
**
** campos del browse
**
REDEFINE LISTBOX oLbx ;
FIELDS oRs:Fields("CLASE"):value, ;
oRs:Fields("NOMBRE"):value, ;
NUM2STR(oRs:Fields("CONTROL"):value, 10, 0) ;
HEADERS PADC ( "Clase", 18 ) , ;
PADC("Nombre",80), ;
PADC("Ref.",10) ;
FIELDSIZES 90, 290, 20 ;
ID 101 ;
OF oDlg ;
ON DBLCLICK F_ALTA(oRs, .F., oLbx )
oLbx:bLogicLen = { || oRs:RecordCount }
oLbx:bGoTop = { || oRs:MoveFirst() }
oLbx:bGoBottom = { || oRs:MoveLast() }
oLbx:bSkip = { | nSkip | Skipper( oRs, nSkip ) }
oLbx:cAlias = "ARRAY"
** si pulsa <intro>
oLbx:bKeyDown := {|nK| if( nK != VK_RETURN, , F_ALTA(oRs,.F.,aCbx, oLbx) ) }
** para que el browse salga a dos colores
oLbx:nClrPane:={|| IIF(oRs:AbsolutePosition % 2==0,CLR_LGREEN,CLR_LGRAY)}
REDEFINE BUTTONBMP oBtn[1] ID 104 OF oDlg ;
ACTION F_ALTA( oRs, .T., oLbx) ;
MESSAGE "Alta de una nueva receta." ;
PROMPT SPACE(6)+ "&Alta" TEXTRIGHT ;
BITMAP "Alta3"
**
** Baja receta
**
REDEFINE BUTTONBMP oBtn[2] ID 105 OF oDlg ;
ACTION( O_SUPRIMIR ( oRs, "NOMBRE" ), ;
oLbx:Refresh(), ;
oLbx:SetFocus() ) ;
MESSAGE " Eliminar receta activa." ;
PROMPT SPACE(6)+ "&Baja" TEXTRIGHT ;
BITMAP "Cancelar"
// modificar receta
REDEFINE BUTTONBMP oBtn[3] ID 106 OF oDlg ;
ACTION F_ALTA( oRs, .F., oLbx ) ;
MESSAGE " Editar receta activa." ;
PROMPT SPACE(10) + "&Editar" ;
BITMAP "lapiz" TEXTRIGHT
// filtrar
REDEFINE BUTTONBMP oBtn[4] ID 107 OF oDlg ;
ACTION ( FILTRAR ( oRs ), ;
oLbx:Refresh(), ;
oLbx:SetFocus() ) ;
MESSAGE " Filtrar recetas." ;
PROMPT SPACE(10) + "&Filtrar" ;
BITMAP "buscar" TEXTRIGHT
// Imprimir
REDEFINE BUTTONBMP oBtn[5] ID 108 OF oDlg ;
ACTION ( I_LISTA( oRs ), ;
oLbx:REFRESH(), ;
oLbx:SETFOCUS()) ;
MESSAGE " Imprimir la receta activa." ;
PROMPT SPACE( 8 ) + "&Imprimir" ;
BITMAP "imprimir1" TEXTRIGHT
// boton salir
REDEFINE BUTTONBMP oBtn[6] ID 109 OF oDlg ;
ACTION oDlg:End() ;
MESSAGE " Salir del programa." ;
PROMPT SPACE(4)+ "&Salir" TEXTRIGHT ;
BITMAP "salir1"
oDlg:lHelpIcon:=.f.
ACTIVATE DIALOG oDlg CENTERED ;
ON INIT oLbx:SetFocus()
oRs:CLOSE()
oRS:=Nil
RETURN NIL
////////////////////////////////////////
/// funcion que crea un recordset
/// oCon = Objeto conexión a la BD
/// cSql = Orden SQL
/// lVacio = .T./.F. avisar que Ors está vacio
///////////////////////////////////////
FUNCTION F_RECORDSET (oCon, cSql, lVacio)
local oError
local oRs := CreateObject( "ADODB.Recordset" )
oRs:CursorLocation := 3 // adUseClient
oRs:LockType := 3 // adLockOptimistic
oRs:CursorType := 1 // adOpenKeyset
oRs:Source := cSql
oRs:ActiveConnection(oCon)
TRY
oRs:Open( )
CATCH oError
AdoError(oCon, oError)
RETURN nil
END
IF lVacio
IF oRs:EOF .and. oRs:BOF
msgstop ("Fichero vacio")
oRs:CLOSE()
oRs:=Nil
RETURN nil
ENDI
oRs:MoveFirst()
ENDI
RETURN oRs
//////////////////////////////////
/// skipper se usa para saltar en el oRs
/// cuando salta en el browse
////////////////////////////////////////////////////////
FUNCTION SKIPPER( oRs, nSkip )
LOCAL nRec := oRs:AbsolutePosition
oRs:Move( nSkip )
IF oRs:EOF; oRs:MoveLast(); ENDIF
IF oRs:BOF; oRs:MoveFirst(); ENDIF
RETURN oRs:AbsolutePosition - nRec
/////////////////////////////////////////
/// Para informar de un error ADO
////////////////////////////////////////
FUNCTION AdoError(oCon, oError)
LOCAL oTmp
FOR EACH oTmp IN oCon:Errors // oAdoErrors
IF oError == nil
oError := ErrorNew()
oError:Description := "Error desconocido ADO"
ELSE
oError:SubCode := oTmp:NativeError //¡¡¡num. error nativo
oError:Description := oTmp:Description
ENDIF
NEXT
MSGSTOP ( (oError:Description + CRLF ) , ;
" Error " + oError:Operation + ' ' + oError:SubSystem )
RETURN (oError:SubCode) // Código num. del error
///////////////////////////////////////
Para agregar o editar un registro, puedes ver este mensaje:
http://fivetechsoft.com/forums/viewtopi ... ght=#47676