Page 1 of 1

RECORDSET AND REPORT

Posted: Sat Jan 19, 2008 10:52 am
by Manuel Valdenebro
En una aplicacion Oracle + Ado, capturo un RecordSet con varios registros que muestro en un Browse con tres columnas:


..........

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

oLbx:aJustify ={.F.,.F.,.t.}
oLbx:bLogicLen = { || oRs:RecordCount }
oLbx:bGoTop = { || oRs:MoveFirst() }
oLbx:bGoBottom = { || oRs:MoveLast() }
oLbx:bSkip = { | nSkip | Skipper( oRs, nSkip ) }
oLbx:cAlias = "ARRAY"

Desearía imprimir el browse (todos los registros) con la clase Report, pero solo consigo que me salga, varias veces, el primer registro. He intentado poniendo un bucle FOR/NEXT ó de la manera usual con un array (bSkip), pero no resulta. ¿Alguna ayudita por favor?

----------------------------------------------------------
STATIC FUNCTION I_LISTA( oRs )
LOCAL oReport, oFont1, oFont2, oFont3, oPen1, oPen2

DEFINE FONT oFont1 NAME "ARIAL" SIZE 0,-8
DEFINE FONT oFont2 NAME "ARIAL" SIZE 0,-12 BOLD
DEFINE FONT oFont3 NAME "ARIAL" SIZE 0,-16 BOLD

REPORT oReport ;
CAPTION " Mi libro de Cocinas" ;
TITLE "*** Listado de Recetas ***" ;
HEADER DTOC(DATE()) , " " FONT oFont1, ;
oFont2, ;
oFont3 ;
FOOTER "Página Número: " + STR (oReport:nPage, 3) CENTER ;
PREVIEW
COLUMN TITLE "Clas" DATA oRs:Fields("clase"):value
COLUMN TITLE "Nombre" DATA oRs:Fields("nombre"):value
COLUMN TITLE "Refª" DATA oRs:Fields("control"):value

END REPORT

oReport:oTitle:aFont[1] := {|| 3 }
oReport:oHeader:aFont[1] := {|| 2 }
oReport:oDevice:SetPortrait()
oReport:oDevice:lPrvModal := .T. // preview modal

ACTIVATE REPORT oReport

oFont1:End()
oFont2:End()
oFont3:End()
oRs:MoveFirst()

RETURN NIL

------------------------------------------

Posted: Sat Jan 19, 2008 3:03 pm
by Moisoft
Posiblemente usando el metodo bSkip del Report:

END REPORT

....
....
oReport:bSkip = { | nSkip | Skipper( oRs, nSkip ) }

ACTIVATE REPORT oReport

Posted: Sat Jan 19, 2008 6:01 pm
by Armando
Manuel:

Yo lo hago así con MySql, espero que te funcione con Oracle:

Dentro de la función para la impresión tengo

FUNCTION Imprime()

LOCAL nLinea := 1
LOCAL nHasta := oRsPro:RecordCount()

oRsPro:MoveFirst()

Aquí van los DEFINE de fonts y REPORT

// Creo que aqui esta el truco
IF oReporte:lCreated
oReporte:bSkip := { || (nLinea++, oRsPro:MoveNext())}
ENDIF

Y finalmente al activar el reporte:

ACTIVATE REPORT oReporte ;
WHILE nLinea <= nHasta


Espero esto te ayude, Saludos

Posted: Sat Jan 19, 2008 7:12 pm
by Manuel Valdenebro
Moisoft wrote:Posiblemente usando el metodo bSkip del Report:
END REPORT
....
....
oReport:bSkip = { | nSkip | Skipper( oRs, nSkip ) }

ACTIVATE REPORT oReport
Moisés, muchas gracias por tu ayuda. Ahora lista perfectamente el Recordset, pero repite "infinitamente" el último registro. Me imagino que es la función Skipper, que al encontrar oRs:EOF ejecuta MoveLast().-
He intentado solucionándolo añadiendo:

ACTIVATE REPORT oReport WHILE (oRs:AbsolutePosition < oRs:RecordCount)

pero no sale el ultimo registro y si le pongo:
(oRs:AbsolutePosition <= oRs:RecordCount), estamos igual que antes, es decir, repite el ultimo registro infinitamente.

En Listbox, tenemos oLbx:bLogicLen = { || oRs:RecordCount }, pero no he encontrado su sustituto en la clase Report.

Esta es mi funcion Skipper:

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

Me imagino que la cosa ahora no es complicada, pero a mi no se me ocurre ninguna solución.

Posted: Sun Jan 20, 2008 8:20 pm
by Moisoft
Prueba a dejar la funcion skipper más sencilla:

FUNCTION SKIPPER( oRs, nSkip )
LOCAL nRec := oRs:AbsolutePosition
oRs:Move( nSkip )
RETURN oRs:AbsolutePosition - nRec

ya que cuando sea eof el Reporte Termine.

Posted: Sun Jan 20, 2008 10:33 pm
by mmercado
Hola Manuel:

1.- Ya probaste el Method Report del Browser que estás usando?
2.- Ya probaste usando la Cláusula FOR en lugar de la cláusula WHILE en ACTIVATE REPORT?

Saludos.

Manuel Mercado

Posted: Mon Jan 21, 2008 12:18 am
by Manuel Valdenebro
Moises, Armando y D. Manuel, muchas gracias por contestar.

Al final la solución la he encontrado haciendo un popurrí con todo lo dicho por Vdes.

1) He utilizado:
local nHasta := oRs:RECORDCOUNT(), nLinea := 1
.....
oReport:bWhile := { || nLinea <= nHasta }
IF oReport:lCreated
oReport:bSkip := { | | nLinea++, Ors:MOVENEXT() }
ENDI

2) He modificado la funcion Skipper quedando:

FUNCTION SKIPPER( oRs, nSkip )
LOCAL nRec := oRs:AbsolutePosition

IF oRs:EOF
oRs:MoveLast()
ELSE
oRs:Move( nSkip )
ENDIF

IF oRs:BOF; oRs:MoveFirst(); ENDIF

RETURN oRs:AbsolutePosition - nRec


Ya está funcionando estupendamente. De nuevo, muchas gracias a los tres.

Posted: Mon Jan 21, 2008 1:23 am
by Armando
Manuel:

Me alegra saber que todo funciona bien ahora, sin embargo creo que puedes reducir tu código, en realidad pienso que no necesitas la función Skipper().

Es solo una sugerencia.

Saludos

Posted: Mon Jan 21, 2008 3:48 pm
by Manuel Valdenebro
Armando wrote:... no necesitas la función Skipper().
Armando,

En un principio lo hice como me dices. Sale perfecto el "preview" de Treport, pero al pulsar Imprimir/Salir marcaba un error de ADO/ors, al volver al Browse. Por eso incluí el Skipper que creo sincroniza el Ors:Fields con el registro del browse.

Yo utilizo tWbrowse.- ¿Que browse estás tu utilizando con Mysql?

Posted: Mon Jan 21, 2008 4:00 pm
by Armando
Manuel:

En principio te dire lo que dicen los gurus, "Si funciona bien no le muevas" :D perooo solo por no dejar.

1.- Yo uso TXBrowse, no se si eso tengo algo que ver

2.- Me olvide de indicarte estas dos línea de código, tal vez por ahí esta el problema

LOCAL nLinea := 1
LOCAL nHasta := oRsPro:RecordCount()
LOCAL nBookMark := oRsPro:BookMark

....
....
....


ACTIVATE REPORT oReporte ;
ON STARTPAGE Alinea(oReporte,1,2);
ON END oRsPro:BookMark := nBookMark;
WHILE nLinea <= nHasta

Creo que el RecordSet es muy quisquilloso en cuanto al apuntador.

Saludos, Armando

Posted: Mon Jan 21, 2008 9:35 pm
by Manuel Valdenebro
Armando wrote: Me olvide de indicarte estas dos línea de código, tal vez por ahí esta el problema
Armando,

Llevabas mucha razón. Aunque funcionaba al imprimir cuando cambie la función Skipper, al moverme normalmente en el browse, cuando llegaba al final daba error. He modificado la función de la siguiente forma:

STATIC FUNCTION I_LISTA( oRs )
local nLinea := 1, nHasta := oRs:RECORDCOUNT(), ;
nBookMark := oRs:BookMark

oRs:MoveFirst()

REPORT oReport ;
CAPTION .....
...................
END REPORT

oReport:bWhile := { || nLinea <= nHasta }
oReport:oTitle:aFont[1] := {|| 3 }
oReport:oHeader:aFont[1] := {|| 2 }
oReport:oDevice:SetPortrait()
oReport:oDevice:lPrvModal := .T. // preview modal
IF oReport:lCreated
oReport:bSkip := { | | nLinea++, Ors:MOVENEXT() }
ENDI

ACTIVATE REPORT oReport ;
ON END oRs:BookMark := nBookMark

oRs:MoveFirst()
RETURN NIL

--------------------------------

¿ Para que pones ON STARTPAGE Alinea (oReport,1,2) ?

Posted: Mon Jan 21, 2008 11:55 pm
by Armando
Manuel:

Me algera que funcione bien.


La función ALINEA() es porque a mi me gustan los encabezados así

Fecha: 22/Ene/2008 Página No. 1
=========================================
COLUMNA COLUMNA COLUMNA COLUMNA
=========================================

Así defino los encabezados

TITLE "Fecha: "+Date2Txt(DATE()),;
"Hoja No:"+STR(oReporte:nPage,3)

Al ser dos elementos del arreglo TITLE me los pone uno en una línea y el otro en la línea siguiente

Fecha: 22/Ene/2008
Página No. 1

Entonces la función ALINEA() me sirve para cambiarle la línea al segundo elemento dandole la misma línea que el primer elemento y me quedan en una misma línea.

Esepero haberme explicado.

Saludos, Armando

Posted: Tue Jan 22, 2008 2:52 pm
by Manuel Valdenebro
Armando wrote: Esepero haberme explicado.
Armando,

Te has explicado magnificamente. Gracias por todo.