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