Ejemplo del uso del un recorset con xbrowse

Ejemplo del uso del un recorset con xbrowse

Postby leandro » Fri Feb 08, 2008 2:37 pm

Amigos del foro tengan buen dia, alguien me puede indicar de casualidad como se usa un recorset, directamente con un xbrowse.

De antemano gracias
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Postby alex_cyr » Sat Feb 16, 2008 2:10 am

pues mira yo use WBROWSE y para usar recordset tienes que definir el tipo de cursor correcto, definierle lo codigos de blocks de navegacion asi como definir una funcion skipper especial...

oLbx1:bLogicLen := { || oRecordSet:RecordCount }
oLbx1:bGoTop := { || oRecordSet:MoveFirst() }
oLbx1:bGoBottom := { || oRecordSet:MoveLast() }
oLbx1:bSkip := { | nSkip | Skipper( oRecordSet, nSkip ) }



STATIC 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


Debo aclararte que no lo he hecho funcionar al 100% ya que cuando me muevo hacia la derecha en el browse me hace un efecto "extraño"...

Ojala te sirva de algo.
Saludos.
Alex.
alex_cyr
 
Posts: 77
Joined: Wed Jun 28, 2006 6:38 pm
Location: Chihuahua

Postby Biel EA6DD » Sat Feb 16, 2008 6:02 pm

Code: Select all  Expand view  RUN
...
//oRs tiene el recordset ya creado.
oBrw := TXBrowse():New( oWnd )
oBrw:SetAdo(oRs)
oBrw:CreateFromCode()
oWnd:oClient:=oBrw
...

Tambien puedes consultar este otro hilo http://fivetechsoft.com/forums/viewtopic.php?t=8231
Saludos desde Mallorca
Biel Maimó
http://bielsys.blogspot.com/
User avatar
Biel EA6DD
 
Posts: 682
Joined: Tue Feb 14, 2006 9:48 am
Location: Mallorca

Postby MauroArevalo » Sat Feb 16, 2008 6:52 pm

Biel:

Se me ocurre una idea, te la voy a proponer a ver si te animas..

Porque no haces un manual como para niños de KINDER sobre como comenzar a utilizar ADO, yo leo tu BLOG y se que tu colaboras desinteresadamente a la comunidad de fivewineros.

Cuando yo aprendi clipper lo hice a punta de comprar libros y prácticar y repasar y practicar y repasar hasta que fui aprendiendo. Y creo que si tenemos un manual de KINDER y despues para PRIMARIA y asi sucesivamente iremos haciendo la transicion a ADO.

Lógico tu tiempo vale y por eso estaria dispuesto a pagar ($$ bueno Euros) por dicho manual. ¿Que te parece?; creo a que muchos nos serviria para dar ese salto.

Saludos
Edgar Mauricio Arévalo Mogollón.
Bogotá DC. Colombia
FWH FTDN, xHarbour 1.2.1, Pelles C, Fivedit, Visual Studio Code, Borland 7.30, Mysql, Dbfs
http://www.hymplus.com http://www.hymlyma.com
Tratando de retomar la programación....
User avatar
MauroArevalo
 
Posts: 107
Joined: Thu Jan 19, 2006 11:47 pm
Location: Bogota DC. Colombia

Postby Manuel Valdenebro » Sat Feb 16, 2008 7:13 pm

Mauricio,

El tema de ADO es bastante simple y realmente no es necesario un manual. En la red existe bastante información que es de donde (la mayoría) hemos ido aprendiendo.

http://www.w3schools.com/ado/default.asp

Pero si lo que se pretende es trabajar con una base de datos "seria" (cliente-servidor) tales como Oracle, MySql, SqlServer, etc. en mi opinión, habría que dividir el tema en tres pasos:

1) Lenguaje SQL (fundamental)
2) ADO
3) Temas específicos de cada base de datos (por ejemplo, Oracle tiene su propio lenguaje).
Un saludo

Manuel
User avatar
Manuel Valdenebro
 
Posts: 706
Joined: Thu Oct 06, 2005 9:57 pm
Location: Málaga-España

Postby MauroArevalo » Sat Feb 16, 2008 10:13 pm

Manuel:

Gracias

Y tienes toda la razón, es trabajar con base de datos cliente\servidor, lo que es no plantear bien la duda o pregunta.

Así como lo planteas es perfecto para iniciarse.

El primer punto no habriá necesidad porque hay bastante documentación, cursos, manuales, etc...de hecho ya hago pruebas con MYSQL desde la linea de comandos (crear, modificar, consultas, etc.)

El segundo ADO tambien pasa.

Entonces seria el tercer punto.

Temas específicos de cada base de datos (por ejemplo, Oracle tiene su propio lenguaje).

Dominando este tema podriamos tener nuestros sistemas en diferentes versiones atacando DBF, MYSQL, ORACLE, etc..


PD: ¿Manuel y al fín no viniste a Colombia el año pasado?, te teniamos una invitación a tomar puro cafecito colombiano.


Saludos,
Edgar Mauricio Arévalo Mogollón.
Bogotá DC. Colombia
FWH FTDN, xHarbour 1.2.1, Pelles C, Fivedit, Visual Studio Code, Borland 7.30, Mysql, Dbfs
http://www.hymplus.com http://www.hymlyma.com
Tratando de retomar la programación....
User avatar
MauroArevalo
 
Posts: 107
Joined: Thu Jan 19, 2006 11:47 pm
Location: Bogota DC. Colombia

Postby horacio » Sun Feb 17, 2008 1:36 am

El problema de las BBDD cliente - servidor no es como atacarlas desde nuestros programas mediante Ado ( en el foro hay bastante documentación con respecto a este tema ). El mayor problema es cambiar la visión que nosotros tenemos con respecto de las bases de datos que hemos venido manejando ( dbf ). Hasta ahora la lógica la manejabamos nosotros, desde nuestras aplicaciones pero cuando trabajamos sobre esta tecnología la lógica es manejada por el servidor mediante store procedures ( procedimientos almacenados ) y triggers ( disparadores ). y para trabajar con estas herramientas es necesario aprender el lenguaje de la BBDD. Creer que solamente con una cadena de conexión y el comando SELECT tenemos todo resuelto es una ingenuidad. Si realmente queremos que nuestros sistemas sean eficientes debemos cambiar la mentalidad ( y estudiar bastante ). Yo he hecho pruebas con 200 o 300 registros y el rendimiento no ha variado significativamene con respecto a una base distribuida ( dbf ) pero hablar de más de 3.000.000 de registros y conectarnos en forma remota es otra cosa. Los index no son iguales tal cual los conocemos. Es el servidor el que elige que index va a utilizar en las consultas y para eso nosotros debemos decidir que index crear. No quiero extenderme demasiado sobre este tema ( tampoco soy un entendido ) pero me parece que si decidimos trabajar en forma seria sobre esta tecnología hará falta mucho estudio y ver el manejo de datos de manera diferente . Espero que esto sirva.
saludos
horacio
 
Posts: 1363
Joined: Wed Jun 21, 2006 12:39 am
Location: Capital Federal Argentina

Postby Manuel Valdenebro » Sun Feb 17, 2008 10:05 am

Horacio,

Podriamos clasificar la mayoria de las aplicaciones que venimos desarrollando los clipperos en dos grupos:

1) Programas domésticos.
2) Programas para pequeñas/medianas empresas (multipuesto o multilugares)

En el segundo grupo es muy conveniente, por cuestiones de seguridad interna (pérdida de datos, reindexados, etc) y externa (encriptación de los datos, copias de seguridad, etc) el usar una base de datos cliente/servidor. Incluso a nivel comercial, no vende igual una aplicación que trabaje con Oracle/MySql que con dbf. Recuerdo que Oracle Express es gratuito.

En este caso, no es obligatorio un conocimiento profundo de la BD y con unos pequeños cambios (sobre todo, si nos preparamos algunas funciones generales de apoyo), podemos poner a trabajar nuestra aplicación con una BD de garantía. En velocidad practicamente igual que con dbf.

Esta claro que si se tienen esos conocimientos y planteamos nuestra aplicación de otra forma (huir de los browse) la cosa mejora, pero lo que quiero decir es que no es OBLIGATORIO.

Otro tema muy importante (en mi opinión) sería trabajar con una BD en un servidor externo (internet). Y quizás con esta opción, si podriamos organizar, entre los foreros que estuvieran interesados, unas prácticas, contratando un servidor compartido y atacando, cada uno desde su ordenador como usuario, la misma BD.

Tambien sería interesante, para no duplicar los comentarios y conseguir mas colaboradores, que el tema lo desarrollaramos exclusivamente en el foro INGLES, aunque se permitieran utilizar españo/inglés.
Un saludo

Manuel
User avatar
Manuel Valdenebro
 
Posts: 706
Joined: Thu Oct 06, 2005 9:57 pm
Location: Málaga-España

Amigo...

Postby leandro » Sun Feb 17, 2008 5:39 pm

Alex amigo:

Es posible que sea el tipo de cursor, lo estoy definiendo de la siguiente manera:

Code: Select all  Expand view  RUN
oRsPro:CursorLocation := adUseClient
oRsPro:LockType := adLockOptimistic
oRsPro:CursorType := adOpenDynamic
oRsPro:Source := "SELECT * FROM clientes ORDER BY clie_nom"
oRsPro:ActiveConnection(oCnx)

Es correcto o debo hacerlo de otra forma?

Te hago otra pregunta, como hago para refrescar el recorset en tiempo de ejecucción?
Last edited by leandro on Sun Feb 17, 2008 5:44 pm, edited 1 time in total.
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Con ....

Postby leandro » Sun Feb 17, 2008 5:43 pm

Con la respecto a la documentacion de ado creo que es suficiente para iniciar y poder hacer andar tu aplicación por lo menos a un 80%. El mayor problema para mi ha sido hacer funcionar el recorset en un browse. Es en donde me he topado con mas complicaciones, me gustaria que existiera un manual en donde se explicara el manejo del recorset sobre un browse, cualquiera que este sea.
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Ejemplo con ADO + RecordSet + Browse

Postby Manuel Valdenebro » Mon Feb 18, 2008 9:30 am

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
Un saludo

Manuel
User avatar
Manuel Valdenebro
 
Posts: 706
Joined: Thu Oct 06, 2005 9:57 pm
Location: Málaga-España

Postby leandro » Mon Feb 18, 2008 3:00 pm

Gracias Manuel

Muchas gracias por las respuesta voy a probar y cualquier cosa te comento.

Amigo, cuando estoy trabajando con entorno MDI, debo hacer algo especial para que funcione bien el xbrowse?
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Postby Biel EA6DD » Mon Feb 18, 2008 5:21 pm

Bueno este hilo parece que genera bastante interes, me alegro pues cada dia somos mas los que podemos ir aportando conocimientos sobre ADO.

Mauro, a mi no me importaria realizar un manual de ADO, pero como tu bien comentas el tiempo vale dinero, y muchas veces no dispongo de todo el tiempo que quisiera. De momento en el blog voy escribiendo cada cuando puedo, habra epocas con mas articulos, y otras de larga sequia. En cuaquier caso, el tema formacion es algo que me interesa, y puedo llegar a plantearmelo, siempre y cuando me compense la retribución a recibir a cambio.

Al tema, como bien han comentado otros por la red hay bastante información del tema ADO, y en este foro cada vez mas, recuperar un recordset y visualizarlo en un browse con ventanas MDI no tien que llevar ningún problema.
He escrito en mi blog una nueva entrada, con un ejemplo muy básico de ADO para visualizar una tabla en un xBroswe.
http://bielsys.blogspot.com/2008/02/usando-origenes-de-datos-ado-1.html
Espero que os pueda ser de utilidad.
Saludos desde Mallorca
Biel Maimó
http://bielsys.blogspot.com/
User avatar
Biel EA6DD
 
Posts: 682
Joined: Tue Feb 14, 2006 9:48 am
Location: Mallorca

Postby leandro » Tue Feb 19, 2008 5:15 pm

Biel y Manuel muchas gracias por la ayuda. Funciona de maravilla.

Pero tengo otra preguntica?

Como hago para actualizar el recorset. por ejemplo que quiera cambiar el orden en que se estan mostrando la consulta.

El recorset inicial es:

Code: Select all  Expand view  RUN
oVar   := "SELECT * from colores order by CODIGO"
TRY
  oLamcla:oRsColore:=tOleAuto():New("ADODB.RecordSet")
CATCH oError
  MsgStop( "No se ha podido crear el RECORDSET !","Error de Datos" )
END

oLamcla:oRsColore:CursorLocation  := adUseClient //adUseServer
oLamcla:oRsColore:LockType        := adLockOptimistic
oLamcla:oRsColore:CursorType      := adOpenKeyset
oLamcla:oRsColore:Source          := oVar
oLamcla:oRsColore:ActiveConnection( oLamcla:oServer )


Pero quiero actualizar el recorset con la siguiente consulta:

Code: Select all  Expand view  RUN
oVar   := "SELECT * from colores order by NOMBRE"


Como lo hago?

De antemano gracias por las respuesta.
Saludos
LEANDRO AREVALO
Bogotá (Colombia)
https://hymlyma.com
https://hymplus.com/
leandroalfonso111@gmail.com
leandroalfonso111@hotmail.com

[ Embarcadero C++ 7.60 for Win32 ] [ FiveWin 23.07 ] [ xHarbour 1.3.0 Intl. (SimpLex) (Build 20230914) ]
User avatar
leandro
 
Posts: 1676
Joined: Wed Oct 26, 2005 2:49 pm
Location: Colombia

Postby Biel EA6DD » Wed Feb 20, 2008 8:30 am

Si lo único que quieres cambiar es el orden de los registros que ya tienes seleccionados, la mejor opción es utilizar el metodo Sort del recordset.
Code: Select all  Expand view  RUN
oRs:Sort:="NOMBRE ASC"

Esta es la manera más rapida y obtima, ya que no implica trafico de red ni carga en el servidor.

En el supuesto que quieras cambiar la sentencia SELECT, el mecanismo seria el siguiente:
Code: Select all  Expand view  RUN
      ::oRs:Close()
      ::oRs:Source:="SELECT * from colores order by NOMBRE"
      ::oRs:Open()
      ::oRs:Refresh()
Saludos desde Mallorca
Biel Maimó
http://bielsys.blogspot.com/
User avatar
Biel EA6DD
 
Posts: 682
Joined: Tue Feb 14, 2006 9:48 am
Location: Mallorca

Next

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 57 guests