Page 1 of 1

filter database using tdata class

Posted: Tue Jan 22, 2008 1:32 pm
by Ehab Samir Aziz
I am trying to use James class tdata to filter a database using the below code :

Code: Select all


//--- meter class
class Tmeter from TData
   method new
   method browser
   method add
   method edit
   method filterreads
   message delete method _delete
 Hidden:
   data lAdd as logical
endclass

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

method new()
   super:new(,"mete",,.f.)
   if ::use()
      ::addIndex("mete")
      ::addIndex("mete2")
      ::setOrder(1)
      ::gotop()
      msgInfo( ::reccount(),"reccount()")
      msgInfo( ::fcount(),"fcount()")
      
   endif
   ::lAdd:=.f.
return self
method browser()

   local oDlg,oBrw,oMeter,oFont,oCol,nFor,oChild

   ::setOrder(2)
   ::gotop()


   define font oFont name "Ms Sans Serif" size 0,-14 BOLD

   DEFINE DIALOG oDlg FROM 0,0 TO 45,128 TITLE "meter reads browse "

   oBrw := TXBrowse():New( oDlg )
   oBrw:nMarqueeStyle       := MARQSTYLE_HIGHLCELL
   oBrw:nColDividerStyle    := LINESTYLE_BLACK
   oBrw:nRowDividerStyle    := LINESTYLE_BLACK
   oBrw:lColDividerComplete := .t.
   oBrw:nHeaderLines        := 1
   oBrw:nFooterLines        := 1
   oBrw:nDataLines          := 1
   oBrw:lFooter             := .t.
   oBrw:CreateFromCode()
   oBrw:nTop = 0
   oBrw:nLeft = 0
   oBrw:nWidth = 1000
   oBrw:nHeight =600
   oBrw:SetRDD()
   


      for nFor := 1 to ::Fcount()
      	oBrw:aCols[ nFor ]:oDataFont := oFont
      next
    
   // Setup for using database class
   oBrw:cAlias:= ::cAlias
   oBrw:bSkip:= {|nRecs| ::skipper( nRecs ) }
   oBrw:bGotop:= {|| ::gotop() }
   oBrw:bGoBottom:= {|| ::goBottom() }
   oBrw:bBookMark := {| n | iif( n == nil, ::RecNo() , ::Goto( n ) ) }
   

oMeter:= self

ACTIVATE DIALOG oDlg ON INIT (oBrw:SetSize( 1000, 600 ), BuildButtons( oMeter,oBrw,oDlg),oBrw:Refresh(.t.), oDlg:Refresh(.t.)) 
RETURN nil
//---------------------------------------------------------------------------//

function BuildButtons(oMeter, oBrw, oDlg)
*--------------------------------------------------
    @ 34,   1 BUTTON "&New"    OF oDlg SIZE 60, 20 ACTION ( oMeter:add(oBrw),oBrw:refresh(),oDlg:update())

    @ 34,  15 BUTTON "&Modify" OF oDlg SIZE 60, 20 ACTION ( oMeter:edit(oBrw),oBrw:refresh(),oDlg:update())

    @ 34, 30 BUTTON "&Delete" OF oDlg  SIZE 60, 20 ACTION ( oMeter:delete(oBrw,oMeter))

    @ 34,45 BUTTON "&Search" OF oDlg SIZE 60, 20 //ACTION addmete( oBrw , oDlg )

    @ 34,60 BUTTON "&Print" OF oDlg SIZE 60, 20 //ACTION oDlg:Report ( "meter reads Report", .t. )

    @ 36,  1 BUTTON "&Order"    OF oDlg SIZE 60, 20//ACTION ordercust(oLbx) SIZE 40, 12

    @ 36, 5 BUTTON "&Filter"    OF oDlg SIZE 60, 20 ACTION ( oMeter:filterreads(oBrw),oBrw:refresh(),oDlg:update())

    @ 36,  30 BUTTON "&Unfilter" OF oDlg SIZE 60, 20//ACTION Nonfiltercust(oLbx) SIZE 40, 12

    @ 36, 45 BUTTON "&Exit"   OF oDlg SIZE 60, 20 //ACTION oDlg:End() SIZE 40, 12


return nil



method add(oBrw)
*---------------
   ::lAdd:=.t.
   ::edit(oBrw)
   ::load()   // in case they cancel
   ::lAdd:=.f.
   ::GOTOP()
return self

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

method edit(oBrw)
*---------------
   local oDlg,oBtnNew
   local ometer:= TRecord():new( self )
   if ::lAdd
      ometer:blank()
   endif


   DEFINE DIALOG oDlg FROM 8, 2 TO 600, 700 PIXEL ;
      TITLE if(::lAdd,"Untitled","Update")


   @ 1,2 SAY "&Serial" OF oDlg PIXEL
   @ 1,50 SAY ":" OF oDlg PIXEL
   @ 1,60 GET ometer:me_mc_serl OF oDlg PIXEL UPDATE

   @ 15,1 SAY "&Meter date" OF oDlg PIXEL
   @ 15,50 SAY ":" OF oDlg PIXEL
   @ 15,60 GET ometer:me_date pict ("99/99/9999") OF oDlg PIXEL UPDATE


   @ 280, 10 BUTTON oBtnNew PROMPT "&Save" OF oDlg PIXEL SIZE 30, 12 ;
      ACTION  ( ometer:save(), oDlg:end() )

   ACTIVATE DIALOG oDlg CENTERED ;
         ON INIT ( oBrw:Refresh(), oDlg:Update() )

ometer:end()
oDlg:update()

return self



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

method _delete(oBrw,oMeter) 
*------------------------
   if msgYesNo("Delete this record?") 
      super:delete() 
      oMeter:blank()
      oMeter:save()
   endif 
   ::skip(1)    
   ::skip(0)    
if oBrw:eof()
   ::skip(-1)    
   ::skip(0)    
endif
oBrw:refresh()    
   

return self

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

CLASS TXData from TData
   METHOD Append()
   METHOD filterreads()
   MESSAGE Delete METHOD _Delete()
endclass

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

METHOD _Delete()
   ::blank()
   ::save()
return super:delete()

//---------------------------------------------------------------------------//
method filterreads(oBrw)
*----------------------
   local oDlg,oBtnNew
   local ometer:= TRecord():new( self )
   local V_me_mc_serl,y,cfilter,bfilter:=""

   if MsgGet( "Serial Machine", "Enter Serial Machine", @V_me_mc_serl,;
              "" )
      select 3
      use mach
      set index to mach5
      if ! DbSeek( (V_me_mc_serl ))
         MsgAlert( "I don't find that serial" )
      endif
   endif

y := "'"+padr(V_me_mc_serl,7)+"'" 
cFilter := "me_mc_serl = "+ y
bFilter = "{||"+cFilter+"}"

select mete
use mete
set index to mete1
DBSETFILTER(&bFilter,cFilter)
mete->(DBGOTOP())
ometer:end()
oDlg:update()

return self



Posted: Tue Jan 22, 2008 7:40 pm
by James Bott
Ehab,

I see a few things wrong with just a quick look. I have mentioned this before--you MUST use the CLASS clause with methods when defining more than one class in a single PRG. You cannot do:

method new()

You MUST do:

method new() CLASS TMeter

Otherwise the compiler doesn't know which class each method belongs to. You need to do this for EVERY method in your PRG.

Also, you are not understanding that TMeter is a database object. You don't want to open another copy of the same database to do the fiiltering, you filter the one you already have open. So change this code:

select mete
use mete
set index to mete1
DBSETFILTER(&bFilter,cFilter)
mete->(DBGOTOP())

To this:

(::cAlias)->(dbsetfilter(&bFilter,cFilter))
::gotop()

There are other problems too. You have a TXData class defined but you are not inheriting from it to make the TMeter class. Was that your intent?

Let me explain my concept of TXData. This is just the name I picked for a class that exists between TData and any database classes that you create. Start it as an empty class.

class TXData from TData
endclass

That is all you need. Then create your other classes from it.

class TMeter from TXData
...
endclass

OK, what is the point you ask? Later when you wish to make some change in behavior that you want all your database to inherit, you an add it to the TXData class. For example, lets say you want to reuse deleted records. You can add the code to do that in TXData, then TMeter and any other database class that you have created will automatically inherit the ability to reuse deleted records.

You also have an append() method defined in the TXData class that does not exist. I suggest removing the append method, and moving the FilterReads() method to the TMeter class.

Regards,
James