FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Aporte. Nueva clase TQRecord. Para el 谩rbol de Navidad
Posts: 1515
Joined: Thu Oct 30, 2008 02:37 PM
Aporte. Nueva clase TQRecord. Para el 谩rbol de Navidad
Posted: Thu Dec 13, 2018 08:58 PM
Hola a todos,

Siguiendo la estela de una pregunta de Jos茅 Luis, os dejo una clase Record, orientada a la versatilidad y la rapidez.

Espero vuestros comentarios. Saludos

Code (fw): Select all Collapse
///////////////
// TQRecord.prg  -  Quick Record
//
/////////////////////////////////////////////////

#include "hbclass.ch"
#Include "\prg\genlib\debug.ch"


//-------------------------------------------------------------------------//
function PruebaTQRecord()
Local oRec
Local cAlias:= "JAlgo", xRegistro

SELECT 0
USE \Algo ALIAS (cAlias)
IF Select(cAlias) == 0
聽 聽MERROR_("no se pudo abrir !!", cAlias)
ENDIF
*
*
xRegistro:= 2
*
oRec:= TQRecord(cAlias):New(cAlias, xRegistro, .t.)
*
SELECT (cAlias)
GO xRegistro
*
FLOGMSG_("1", oRec, oRec:cAlias, oRec:AlmCod, AlmCod)
*
oRec:AlmCod:= "24"
FLOGMSG_("2", oRec, oRec:cAlias, oRec:AlmCod, AlmCod)
*
oRec:Graba()
FLOGMSG_("3", oRec, oRec:cAlias, oRec:AlmCod, AlmCod)
*
CLOSE (cAlias)
return nil
*
*
//-------------------------------------------------------------------------//
CLASS TQRecord

聽 DATA cAlias
聽 DATA nFCount 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽HIDDEN


聽 DATA 聽 aBuffer 聽 聽 聽INIT {=>} 聽 聽 HIDDEN

聽 METHOD New() 聽 聽 聽 聽CONSTRUCTOR
聽 METHOD AddField() 聽 聽 聽 聽 聽 聽 聽 聽 HIDDEN

聽 DATA nRecNumber 聽 聽 聽 聽 聽 聽 聽 聽 聽 HIDDEN
聽 DATA aCampos 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽HIDDEN

聽 METHOD DondeCargar() 聽 聽 聽 聽 聽 聽 聽HIDDEN

聽 METHOD Llena()
聽 METHOD Graba()

聽 DATA lValueNil 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽HIDDEN

ENDCLASS

//-------------------------------------------------------------------------//
// cAlias, Obligatorio
// xDondeCargar, posibles valores son: NIL, nRegistro, "EOF"
// lValueNil, indica si se cargaran las datas-field con NIL
METHOD New(cAlias, xDondeCargar, lValueNil) CLASS TQRecord
聽 Local nArea:= Select()
聽 Local nSitio
聽 Local cName
聽 Local nPos
聽 *
聽 ::cAlias:= cAlias
聽 IF lValueNil == NIL
聽 聽 聽lValueNil:= .f.
聽 ENDIF
聽 ::lValueNil:= lValueNil
聽 *
聽 SELECT (cAlias)
聽 ::nFCount:= FCount()
聽 nSitio:= Recno()
聽 *
聽 *
聽 ::aCampos:= Array(::nFCount)
聽 *
聽 ::DondeCargar(xDondeCargar, lValueNil)
聽 *
聽 IF lValueNil
聽 聽 聽// Carga datas con NIL. Interesante para luego solo grabar los que no son NIL y asi
聽 聽 聽// permitir grabaciones parciales utiles por ejemplo en registros que tienen campos
聽 聽 聽// que se deben actualizar de forma separada, por ejemplo campos contador.
聽 聽 聽FOR nPos:= 1 TO ::nFCount
聽 聽 聽 聽 cName:= FieldName(nPos)
聽 聽 聽 聽 *
聽 聽 聽 聽 ::aCampos[nPos] := cName
聽 聽 聽 聽 *
聽 聽 聽 聽 ::AddField(cName, NIL)
聽 聽 聽NEXT
聽 聽 聽*
聽 ELSE
聽 聽 聽FOR nPos:= 1 TO ::nFCount
聽 聽 聽 聽 cName:= FieldName(nPos)
聽 聽 聽 聽 *
聽 聽 聽 聽 ::aCampos[nPos] := cName
聽 聽 聽 聽 *
聽 聽 聽 聽 ::AddField(cName, FieldGet(nPos))
聽 聽 聽NEXT
聽 聽 聽*
聽 ENDIF
聽 GO nSitio
聽 SELECT (nArea)
聽 *
RETURN Self
*
//-------------------------------------------------------------------------//
METHOD DondeCargar(xDondeCargar)
聽 *
聽 DO CASE
聽 聽 聽CASE xDondeCargar == NIL .OR. ValType(xDondeCargar) == "N"
聽 聽 聽 聽 IF xDondeCargar == NIL
聽 聽 聽 聽 聽 聽xDondeCargar:= Recno()
聽 聽 聽 聽 ENDIF
聽 聽 聽 聽 IF !::lValueNil 聽 聽 聽 聽 聽 聽 聽// No necesario pq para lValueNil = .T. no se cargan datos
聽 聽 聽 聽 聽 聽GO xDondeCargar
聽 聽 聽 聽 ENDIF
聽 聽 聽 聽 ::nRecNumber:= xDondeCargar
聽 聽 聽 聽 *
聽 聽 聽CASE ValType(xDondeCargar) == "C" .AND. xDondeCargar == "EOF"
聽 聽 聽 聽 IF !::lValueNil
聽 聽 聽 聽 聽 聽GO BOTTOM
聽 聽 聽 聽 聽 聽SKIP 聽 聽 聽 聽 聽// Eof(), para datas vacias, y nuevo
聽 聽 聽 聽 ENDIF
聽 聽 聽 聽 ::nRecNumber:= 0
聽 聽 聽 聽 *
聽 聽 聽 聽 *
聽 聽 聽CASE .T.
聽 聽 聽 聽 MERROR_("Opcion no contemplada !!", cAlias, xDondeCargar)
聽 聽 聽 聽 *
聽 ENDCASE
聽 *
RETURN NIL
*
//-------------------------------------------------------------------------//
METHOD AddField(cName, uValue)
聽 *
聽 ::aBuffer[cName] := uValue
聽 *
聽 __clsAddMsg( ::ClassH, cName,;
聽 聽 聽 聽 聽 聽 聽 聽{|Self 聽 聽 聽 聽| Self:aBuffer[cName] 聽 聽 聽 聽 聽 }, HB_OO_MSG_INLINE )
聽 *
聽 __clsAddMsg( ::ClassH, "_" + cName,;
聽 聽 聽 聽 聽 聽 聽 聽{|Self, uValue| Self:aBuffer[cName] := uValue }, HB_OO_MSG_INLINE )
聽 *
return Self

//-------------------------------------------------------------------------//
STATIC FUNCTION Vacia()
聽 聽::Llena(xDondeCargar)
RETURN NIL
*
//-------------------------------------------------------------------------//
METHOD Llena(xDondeCargar)
聽 Local nArea:= Select()
聽 Local nSitio
聽 Local nPos
聽 Local cName
聽 *
聽 SELECT (cAlias)
聽 nSitio:= Record()
聽 *
聽 ::DondeCargar(xDondeCargar)
聽 *
聽 IF ::lValueNil
聽 聽 聽// Carga datas con NIL. Interesante para luego solo grabar los que no son NIL
聽 聽 聽FOR nPos:= 1 TO ::nFCount
聽 聽 聽 聽 cName:= FieldName(nPos)
聽 聽 聽 聽 *
聽 聽 聽 聽 ::Buffer[cName]:= NIL
聽 聽 聽 聽 *
聽 聽 聽NEXT
聽 聽 聽*
聽 ELSE
聽 聽 聽FOR nPos:= 1 TO ::nFCount
聽 聽 聽 聽 cName:= FieldName(nPos)
聽 聽 聽 聽 *
聽 聽 聽 聽 ::Buffer[cName]:= FieldGet(nPos)
聽 聽 聽 聽 *
聽 聽 聽NEXT
聽 聽 聽*
聽 ENDIF
聽 *
聽 GO nSitio
聽 SELECT (nArea)
RETURN NIL

//-------------------------------------------------------------------------//
METHOD Graba()
聽 Local nArea:= Select()
聽 Local nSitio
聽 Local nI, nPos
聽 Local lValueNil:= ::lValueNil
聽 *
聽 SELECT (::cAlias)
聽 nSitio:= Recno()
聽 *
聽 IF ::nRecNumber == 0
聽 聽 聽Add_Rec(0)
聽 ELSE
聽 聽 聽GO ::nRecNumber
聽 聽 聽Rec_Lock(0)
聽 ENDIF
聽 *
聽 FOR nI:= 1 TO ::nFCount
聽 聽 聽// Grabacion segura (cambio de orden de campos entre tabla de origen y
聽 聽 聽// tabla de destino o bien no existe el campo en destino.)
聽 聽 聽nPos:= FieldPos(::aCampos[nI])
聽 聽 聽IF nPos > 0
聽 聽 聽 聽 IF If(lValueNil , ::aBuffer[::aCampos[nI]] != NIL, .t.) 聽 聽 聽 聽 聽
聽 聽 聽 聽 聽 聽FieldPut(nPos, ::aBuffer[::aCampos[nI]])
聽 聽 聽 聽 ENDIF
聽 聽 聽ENDIF
聽 NEXT
聽 *
聽 UNLOCK
聽 *
聽 GO nSitio
聽 *
聽 SELECT (nArea)
RETURN NIL
*
*
Posts: 564
Joined: Thu Oct 13, 2005 09:23 AM
Re: Aporte. Nueva clase TQRecord. Para el 谩rbol de Navidad
Posted: Sat Dec 15, 2018 07:30 AM
Hola,
Pues me alegro de que la idea te sirviera la idea, a veces las cosas sencillas son las que m谩s utilizamos. Yo ahora estoy utilizando una modificaci贸n de la clase original que me envi贸 Biel Maim贸 y que dejo por si alguien m谩s est谩 interesado.

Hay varias diferencias con la clase original. El alias lo defines en el momento de crear el objeto, en vez de arrays esta nueva clase usa tablas hash, y la creaci贸n de una data no existente en la dbf original debe hacerse mediante el m茅tido adddata('data').

Saludos,

Code (fw): Select all Collapse
// C贸digo basado en una aportaci贸n de Marcelo Via Giglio y modificada por Biel Maim贸.
#include "hbclass.ch"

CLASS tRecord

聽 聽DATA 聽 aFld 聽 聽 聽 聽 聽 聽 聽 聽INIT {=>} HIDDEN
聽 聽DATA 聽 cAlias AS CHARACTER INIT "" 聽 HIDDEN
聽 聽METHOD New(cAlias) CONSTRUCTOR
聽 聽METHOD FieldGet( cName)
聽 聽METHOD FieldPut( cName, uVal )
聽 聽METHOD AddData( cName )
聽 聽METHOD AddDataFromAlias()
聽 聽METHOD LoadFromAlias()
聽 聽METHOD saveToAlias()
聽 聽METHOD blankFromAlias()
聽 聽METHOD SetAlias( cAlias )
聽 聽METHOD GetAlias( ) INLINE ::cAlias

ENDCLASS

//------------------------------------------------------------------------------
METHOD New( cAlias ) CLASS tRecord
聽 聽IF cAlias!=NIL .AND. Select(cAlias)!=0
聽 聽 聽 ::cAlias:=cAlias
聽 聽 聽 ::AddDataFromAlias()
聽 聽 聽 //::loadFromAlias()
聽 聽ENDIF
RETURN SELF

//------------------------------------------------------------------------------
METHOD FieldGet( cName ) CLASS tRecord ; RETURN ::aFld[ cName ]

//-----------------------------------------------------------------------------
METHOD FieldPut( cName, uVal ) CLASS tRecord
聽 聽::aFld[ cName ]:=uVal
RETURN NIL

//------------------------------------------------------------------------------
METHOD AddData( cName ) CLASS tRecord

聽 __clsAddMsg( ::ClassH, cName,;
聽 聽 聽 聽 聽 聽 聽 聽{|Self| Self:FieldGet( cName ) }, HB_OO_MSG_INLINE )

聽 __clsAddMsg( ::ClassH, "_" + cName,;
聽 聽 聽 聽 聽 聽 聽 聽{|Self,Value| Self:FieldPut( cName, Value ) }, HB_OO_MSG_INLINE )

RETURN Self

//------------------------------------------------------------------------------
METHOD AddDataFromAlias() CLASS tRecord
聽 聽LOCAL nFld,i
聽 聽nFld:=(::cAlias)->(FCount())
聽 聽FOR i:=1 TO nFld
聽 聽 聽 ::AddData( (::cAlias)->(FieldName( i )) )
聽 聽NEXT
RETURN NIL

//------------------------------------------------------------------------------
METHOD LoadFromAlias( ) CLASS tRecord
聽 聽LOCAL nFld,i
聽 聽nFld:=(::cAlias)->(FCount())
聽 聽FOR i:=1 TO nFld
聽 聽 聽 ::aFld[ ( (::cAlias)->(FieldName( i )) )]:= (::cAlias)->(FieldGet(i) )
聽 聽NEXT
RETURN NIL

//-----------------------------------------------------------------------------
METHOD SetAlias( cAlias ) CLASS tRecord
聽 聽LOCAL lVal
聽 聽IF cAlias!=NIL .AND. Empty(::cAlias) .AND. Select(cAlias)!=0
聽 聽 聽 ::cAlias:=cAlias
聽 聽 聽 
聽 聽 聽 ::AddDataFromAlias()
聽 聽 聽 //::loadFromAlias()
聽 聽 聽 lVal:=.T.
聽 聽ELSE
聽 聽 聽 lVal:=.F.
聽 聽 聽 //En este caso deberia borrar los mensajes del objeto, y de momento no se como hacerlo.
聽 聽ENDIF
RETURN lVal

//-----------------------------------------------------------------------------
METHOD blankFromAlias() CLASS tRecord
聽 聽LOCAL i, cInit
聽 聽FOR i := 1 TO ( ::cAlias ) ->( FCount() )
聽 聽 聽 DO CASE
聽 聽 聽 CASE ( ::cAlias )->( FieldName( i ) ) == "C"
聽 聽 聽 聽 聽cinit := Space( Len( ( ::cAlias )->( FieldName( i ) ) ) )
聽 聽 聽 CASE ( ::cAlias )->( FieldName( i ) ) == "N"
聽 聽 聽 聽 聽cinit := 0
聽 聽 聽 CASE ( ::cAlias )->( FieldName( i ) ) == "D"
聽 聽 聽 聽 聽cinit := Date()
聽 聽 聽 CASE ( ::cAlias )->( FieldName( i ) ) == "M"
聽 聽 聽 聽 聽cInit := Space( 255 )
聽 聽 聽 CASE ( ::cAlias )->( FieldName( i ) ) == "L"
聽 聽 聽 聽 聽cinit := .F.
聽 聽 聽 ENDCASE
聽 聽 聽 ::aFld[ ( (::cAlias)->(FieldName( i )) )]:= cInit
聽 聽NEXT
RETURN NIL

// ------------------------------------------------------------------------------
METHOD saveToAlias() CLASS tRecord
聽 聽LOCAL i, key, pos
聽 聽FOR i := 1 TO Len( ::aFld ) // (::cAlias) -> ( FCOUNT() )
聽 聽 聽 key := hb_hKeyAt( ::aFld, i )
聽 聽 聽 pos := (::cAlias)->(FieldPos( key ))
聽 聽 聽 IF pos != 0
聽 聽 聽 聽 (::cAlias)->(FieldPut( pos, ::aFld[ key ] )) // FIELDPUT de Harbour
聽 聽 聽 ENDIF
聽 聽NEXT
RETURN NIL

// ------------------------------------------------------------------------------

Continue the discussion