Tfilter Class

Tfilter Class

Postby Silvio.Falconi » Tue Jan 06, 2015 8:13 pm

Friends,
Here my Tfilter class easy to understand.
I used customers.dbf on all samples.
your comments are wellcome.
I have to thank my friend Mr Rao Nages for his example xbrarray.prg from which I started creating this class

Filter.ch
you can personalize it with your string language

Code: Select all  Expand view
#DEFINE ERRORE  "ERROR FILTER"
#DEFINE ERRORE1 "Error on data inserted ."
#DEFINE ERRORE2 "I cannot continue you must define thename of the filter"
#DEFINE ERRORE3 "I cannot continue you must define an dbf archive"


#DEFINE    DIALOG_FILTERS           "Filter creation"
#DEFINE    FILTER_NAME              "Filter name :"
#DEFINE    FILTER_MSG               "Filter  :"
#DEFINE    TXT_OPERATOR             "Operator"
#DEFINE    TXT_FIELD                "Field"
#DEFINE    TXT_CONDITION            "Condition"
#DEFINE    TXT_EXPRESSION           "Expression"
#DEFINE    TXT_UPPER                "Upper/Lowcase"
#DEFINE    TXT_BUTTON_ADD           "Add"
#DEFINE    TXT_BUTTON_INSERT        "Insert"
#DEFINE    TXT_BUTTON_DELETE        "Delete "
#DEFINE    TXT_BUTTON_ACTIVATE      "&Activate"
#DEFINE    TXT_BUTTON_EXIT          "&Exit"
#DEFINE    TXT_MANAGER_TITLE        "Filter Manager"
#DEFINE    TXT_MANAGER_TABLE_TITLE  "Filters"
#DEFINE    FILTER_SECTION_INI       "Filters"

#DEFINE    FILTER_ARRAY_MENU        "New/Modify"



#DEFINE   OpRelacion1   "                    "
#DEFINE   OpRelacion2   "<> desigual         "
#DEFINE   OpRelacion3   "!= desigual         "
#DEFINE   OpRelacion4   "#  desigual         "
#DEFINE   OpRelacion5   "$  contiene         "
#DEFINE   OpRelacion6   "<  menor que        "
#DEFINE   OpRelacion7   "<= menor o igual que"
#DEFINE   OpRelacion8   ">  mayor que        "
#DEFINE   OpRelacion9   ">= mayor o igual que"
#DEFINE   OpRelacion10  "=  igual            "
#DEFINE   OpRelacion11  "== exactamente igual"

#DEFINE   Operators1     " "
#DEFINE   Operators2     "And"
#DEFINE   Operators3     "Or"
#DEFINE   Operators4     "Not"
 




the File Manager to use with tfilter class
FManager.prg

Code: Select all  Expand view

#include "FiveWin.ch"
#include "xBrowse.ch"
#include "constant.ch"
#include "Filter.ch"

#DEFINE LIGHTCYAN    nRGB( 203, 225, 252 )

* +- Program ----------------------------------------------------------------+
* ¦  Application: Filter Manager                                             ¦
* ¦  Description: -usable with Tfilter                                       ¦
* ¦       Author: Falconi Silvio                                             ¦
* ¦ Date created  09.12.2013                       Date updated:  00.00.0000 ¦
* ¦ Time created:                       Time updated:                        ¦
* ¦    Make File:                                                            ¦
* ¦    Exec File:                       Docs By:                             ¦
* ¦    Copyright: (c) 2013                                                   ¦
* ¦         FILE: crea automaticamente un file INI                           ¦
* +--------------------------------------------------------------------------+



Function  Filter_Manager(cDbf,oGrid,cPref)
   Local  nBottom:=12
   Local  nRight:=55
   Local  nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
   Local  nHeight := nBottom * DLG_CHARPIX_H
   Local  oBtnPrev,oBtnGo,oBtnExit,oBtnHelp
   Local  nitem1,oBtn[6]
   Local  aFilters:= {}


   cIniFilter    := cFilePath( GetModuleFileName( GetInstance() ) )  + cPref +".ini"
   aFilters      := GETPVPROFSECTIONS( cIniFilter )


  nFilters:= Len(  aFilters )

   DEFINE DIALOG oDlgFilterList   ;
   SIZE nWidth, nHeight;
   TITLE TXT_MANAGER_TITLE  PIXEL;
   STYLE nOr( DS_MODALFRAME, WS_POPUP, WS_CAPTION,  4 )

   @ 1, 1 XBROWSE  oLbx OF oDlgFilterList ;
             SIZE nWidth/2, (nHeight/4)+32 PIXEL ;
                 ARRAY aFilters  AUTOCOLS NOBORDER


     WITH OBJECT  oLbx
      :lRecordSelector     := .f.
      :nMarqueeStyle   := MARQSTYLE_HIGHLWIN7
      :lHScroll     := .f.
      :nStretchCol:= -1
      :aCols[1]:cHeader  :=  TXT_MANAGER_TABLE_TITLE
      :CreateFromCode()
     END



     @  oLbx:nbottom+2,2  BUTTON  oBtn[1] PROMPT "&Load"   SIZE 30, 10 ;
                PIXEL    OF oDlgFilterList ACTION (  oDlgFilterList:End(),Load_Filter(cDbf,oGrid,oLbx)  )  WHEN nFilters>0

     @  oLbx:nbottom+2,36 BUTTON  oBtn[2] PROMPT "&Clear"   SIZE 30, 10 ;
                PIXEL    OF oDlgFilterList ACTION     (oDlgFilterList:end(), (cDbf)->(DbClearFilter()),(cDbf)->(DbGoTop()),oGrid:refresh()  )

      @  oLbx:nbottom+2,71 BUTTON  oBtn[3] PROMPT "&New"     SIZE 30, 10 ;
      PIXEL    OF oDlgFilterList ACTION  Create_Filter(cDbf,oGrid,oLbx)


      @  oLbx:nbottom+2,176 BUTTON  oBtn[6] PROMPT "&Exit"   SIZE 30, 10 ;
      PIXEL    OF oDlgFilterList  ACTION  oDlgFilterList:End()



     ACTIVATE DIALOG oDlgFilterList centered

Return nil

//---------------------------------------------------------------------//
 Function Load_Filter(cDbf,oGrid,oLbx)

        Local   nLen := Len( oGrid:aCols )
        Local   aCampos [ nLen ]
        Local   aTitulos[ nLen ]
        Local   aTipos  [ nLen ]
        Local   lNew:=.f.
        Local   n
        Local cFilter:= ""

       FOR n = 1 TO nLen
           aCampos   [ n ]:= oGrid:aCols[ n ]:cExpr
           aTitulos  [ n ]:= oGrid:aCols[ n ]:cHeader
           aTipos    [ n ]:= oGrid:aCols[ n ]:cDataType
       NEXT

       IF !EMPTY(oLbx)
         cSection      :=   oLbx:aArrayData[oLbx:nArrayAt]
      ENDIF


      // call the filter class

      oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:Dialog()
      oFilter:Activate()
      cFilter := oFilter:SetFilter()
      IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif

  RETURN  NIL

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

Function Create_Filter(cDbf,oGrid,oLbx)

        Local   nLen := Len( oGrid:aCols )
        Local   aCampos [ nLen ]
        Local   aTitulos[ nLen ]
        Local   aTipos  [ nLen ]
        Local   lNew:=.t.
        Local   n
        Local cFilter:= ""

       FOR n = 1 TO nLen
           aCampos   [ n ]:= oGrid:aCols[ n ]:cExpr
           aTitulos  [ n ]:= oGrid:aCols[ n ]:cHeader
           aTipos    [ n ]:= oGrid:aCols[ n ]:cDataType
       NEXT

      cSection      := ""

       // call the filter class
      oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:Dialog()
      oFilter:Activate()
      cFilter := oFilter:SetFilter()

     IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif



      RETURN  NIL

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



 Function Go_Filter(cDbf,oGrid,cFilter)

        Local   nLen := Len( oGrid:aCols )
        Local   aCampos [ nLen ]
        Local   aTitulos[ nLen ]
        Local   aTipos  [ nLen ]
        Local   lNew

       FOR n = 1 TO nLen
           aCampos   [ n ]:= oGrid:aCols[ n ]:cExpr
           aTitulos  [ n ]:= oGrid:aCols[ n ]:cHeader
           aTipos    [ n ]:= oGrid:aCols[ n ]:cDataType
       NEXT



       IF alltrim(cFilter)== FILTER_ARRAY_MENU
          lNew:=.t.
          cSection:=""
       else
          cSection      :=   cFilter
          lNew:=.F.
          Endif


        // call the filter class

      oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:Dialog()
      oFilter:Activate()
      cFilter := oFilter:SetFilter()
      IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif




  RETURN






STATIC FUNCTION GETPVPROFSECTIONS( cIni )

        LOCAL cBuf := SPACE( 65536 )

        LOCAL aSec := {}

        GETPRIVATEPROFILESECTIONNAMES( cBuf, 65536, cIni )

        WHILE LEFT( cBuf, 1 ) != CHR( 0 )
            AADD( aSec, LEFT( cBuf, AT( CHR( 0 ), cBuf ) - 1 ) )
            cBuf = SUBSTR( cBuf, AT( CHR( 0 ), cBuf ) + 1 )
        ENDDO

        RETURN aSec


 DLL STATIC FUNCTION GETPRIVATEPROFILESECTIONNAMES( cRetBuf AS LPSTR, nSize AS LONG, cFileName AS LPSTR ) AS DWORD;
        PASCAL FROM "GetPrivateProfileSectionNamesA" LIB "kernel32.dll"
 




Test1.prg
a sample with a button to call file manager and set a filter

Code: Select all  Expand view

#include "FiveWin.ch"
#include "xBrowse.ch"
#include "constant.ch"


#include "Filter.ch"

#DEFINE LIGHTCYAN    nRGB( 203, 225, 252 )







Function Test()

   local oDlg, oBrw, oFont
   Local oBtnFiltro[2]

   SET DATE ITALIAN
   SET CENTURY ON

   FwNumFormat( 'E', .t. )

   USE CUSTOMER ALIAS CUST

   DEFINE FONT oFont NAME 'Tahoma' SIZE 0, -14

   DEFINE DIALOG oDlg SIZE 640,440 PIXEL ;
      FONT oFont TITLE 'XBrowse Windows 7 Bars' ;
      COLOR CLR_BLACK,RGB(250,250,250)

   @ 10,20 XBROWSE oBrw OF oDlg SIZE -10,-20 PIXEL ;
      COLUMNS "First", "State", "Age", "HireDate", "Salary" ;
      ALIAS 'CUST' NOBORDER

   oBrw:lRecordSelector := .f.
   oBrw:nMarqueeStyle   := MARQSTYLE_HIGHLWIN7

   WITH OBJECT oBrw:InsCol( 1 )

      :cHeader       := " "
      :bEditValue    := { || If( AScan( oBrw:aSelected, oBrw:BookMark ) > 0, .t., nil ) }
      :SetCheck()
      :nHeadBmpNo    := { || If( Len( oBrw:aSelected ) == oBrw:nLen, 1, 2 ) }
      :bLClickHeader := { |r,c,f,oCol| If( Len( oBrw:aSelected ) == oBrw:nLen, ;
                                           oBrw:SelectNone(), oBrw:SelectAll() ) }

   END

   oBrw:CreateFromCode()

   @ 204,2 BUTTON oBtnFiltro[1] Prompt "Filter Manager" SIZE 60,10 PIXEL;
             ACTION Filter_Manager('CUST',oBrw,'CUST')

    @ 204,102 BUTTON oBtnFiltro[2] Prompt "Cancellare filtro" SIZE 60,10 PIXEL;
             ACTION  ( CUST->(DbClearFilter()),CUST->(DbGoTop()),oBrw:refresh()  )


   ACTIVATE DIALOG oDlg CENTERED

   RELEASE FONT oFont
   Return nil




Test2.prg
a sample to show a combobox with filters and set the filter ( it is incluede a button forr call the filemanager)
Code: Select all  Expand view

#include 'fivewin.ch'
#include 'xbrowse.ch'
#include 'Filter.ch'

* +- Program ----------------------------------------------------------------+
* ¦  Application: Tfilter                                                    ¦
* ¦  Description: Dialog per creare o caricare un filtro                      ¦
* ¦       Author: Falconi Silvio                                             ¦
* ¦ Date created  09.12.2013                       Date updated:  00.00.0000 ¦
* ¦ Time created:                       Time updated:                        ¦
* ¦    Make File:                                                            ¦
* ¦    Exec File:                       Docs By:                             ¦
* ¦    Copyright: (c) 2013                                                   ¦
* ¦         FILE: crea automaticamente un file INI                           ¦
* +--------------------------------------------------------------------------+

function Main()

   local oDlg, oBrw, oFont
   Local oBtnFiltro[3],cFilter:=""
   //-------------//
   Local cIniFilter:=triM(cFilePath( GetModuleFileName( GetInstance() ) )  + "Cust" +".ini")
   Local  aFilters      := GETPVPROFSECTIONS( cIniFilter )
   //---------------//
 /*  If !Empty( cIniFilter)
          hIniFile      := HB_ReadIni( cIniFilter )
          aFilters:=HGetKeys( hIniFile )
   endif
  *       */


   aadd(aFilters, FILTER_ARRAY_MENU)

   SET DATE ITALIAN
   SET CENTURY ON

   FwNumFormat( 'E', .t. )

   USE CUSTOMER ALIAS CUST

   DEFINE FONT oFont NAME 'Tahoma' SIZE 0, -14

   DEFINE DIALOG oDlg SIZE 640,440 PIXEL ;
      FONT oFont TITLE 'Filter test' ;
      COLOR CLR_BLACK,RGB(250,250,250)

   @ 10,20 XBROWSE oBrw OF oDlg SIZE -10,-20 PIXEL ;
      COLUMNS "First", "State", "Age", "HireDate", "Salary" ;
      ALIAS 'CUST' NOBORDER

   oBrw:lRecordSelector := .f.
   oBrw:nMarqueeStyle   := MARQSTYLE_HIGHLWIN7

   WITH OBJECT oBrw:InsCol( 1 )

      :cHeader       := " "
      :bEditValue    := { || If( AScan( oBrw:aSelected, oBrw:BookMark ) > 0, .t., nil ) }
      :SetCheck()
      :nHeadBmpNo    := { || If( Len( oBrw:aSelected ) == oBrw:nLen, 1, 2 ) }
      :bLClickHeader := { |r,c,f,oCol| If( Len( oBrw:aSelected ) == oBrw:nLen, ;
                                           oBrw:SelectNone(), oBrw:SelectAll() ) }

   END

   oBrw:CreateFromCode()


   @ 204,22 COMBOBOX oBtnFiltro[1] VAR cFilter  ITEMS aFilters SIZE 140,90 PIXEL OF oDlg  ;
   ON CHANGE (Go_Filter('CUST',oBrw,cFilter))

   @ 204,172 BTNBMP  oBtnFiltro[2] FILENAME "SH_FILTER.bmp" SIZE 10,10 PIXEL OF oDlg NOBORDER ;
   ACTION ( CUST->(DbClearFilter()),CUST->(DbGoTop()),oBrw:refresh()  ) ;
   TOOLTIP "Erase filter active"   // WHEN !empty(cFilter)

  @ 204,242 BUTTON  oBtnFiltro[3] PROMPT "MANAGER" SIZE 40,10 PIXEL OF oDlg  ;
   ACTION  (Filter_Manager('CUST',oBrw,"Cust"),;
            aFilters      := GETPVPROFSECTIONS( cIniFilter ),;
            oBtnFiltro[1]:REFRESH())

   ACTIVATE DIALOG oDlg CENTERED

   RELEASE FONT oFont

return nil


STATIC FUNCTION GETPVPROFSECTIONS( cIni )

        LOCAL cBuf := SPACE( 65536 )

        LOCAL aSec := {}

        GETPRIVATEPROFILESECTIONNAMES( cBuf, 65536, cIni )

        WHILE LEFT( cBuf, 1 ) != CHR( 0 )
            AADD( aSec, LEFT( cBuf, AT( CHR( 0 ), cBuf ) - 1 ) )
            cBuf = SUBSTR( cBuf, AT( CHR( 0 ), cBuf ) + 1 )
        ENDDO

        RETURN aSec


 DLL STATIC FUNCTION GETPRIVATEPROFILESECTIONNAMES( cRetBuf AS LPSTR, nSize AS LONG, cFileName AS LPSTR ) AS DWORD;
        PASCAL FROM "GetPrivateProfileSectionNamesA" LIB "kernel32.dll"




 




Tfilter.prg
Code: Select all  Expand view
#include "FiveWin.ch"
#include "xBrowse.ch"
#include "constant.ch"
#include "Filter.ch"

#DEFINE LIGHTCYAN    nRGB( 203, 225, 252 )



* +- Program ----------------------------------------------------------------+
* ¦  Application: Tfilter                                                    ¦
* ¦  Description: Dialog per crare o caricare un filtro                      ¦
* ¦       Author: Falconi Silvio                                             ¦
* ¦ Date created  09.12.2013                       Date updated:  00.00.0000 ¦
* ¦ Time created:                       Time updated:                        ¦
* ¦    Make File:                                                            ¦
* ¦    Exec File:                       Docs By:                             ¦
* ¦    Copyright: (c) 2013                                                   ¦
* ¦         FILE: crea automaticamente un file INI                           ¦
* +--------------------------------------------------------------------------+


CLASS TFilter

   DATA aCampos,aTitulos,aTipos  AS ARRAY
   DATA oDlgFilter,cDlgTitle
   DATA oBrwFilter
   DATA oDlgFilterList
   DATA cIniFilter
   DATA lNew
   DATA cFilter
   DATA cDbf
   DATA oBrwDbf
   DATA cNameFilter
   DATA cField
   DATA cCondition
   DATA oCursorBtn
   DATA oFontDialog
   DATA lFilter

   DATA cFiltro

   DATA cOperator
   DATA cEspressione
   DATA cCampo1
   DATA cRelacion1
   DATA cValor1
   DATA nLogico
   DATA acOpRelacion
   DATA acOperators
   DATA cAlias

   DATA lUpper
   DATA lFirstrow

   DATA nRigheSection, cSection
   DATA aGet  AS ARRAY
   DATA oBtn
   DATA aRighefiltro AS ARRAY
   DATA aStringFilter, aRowData
   DATA aArrayFilter


   METHOD New(aCampos,aTitulos,aTipos, cDbf,oBrwDbf,lNew,cNameFilter)   CONSTRUCTOR
   METHOD Dialog()
   METHOD Activate()

   *METHOD End()


    METHOD AddFiltro()
    METHOD BlankRow()
    METHOD InsertRow()
    METHOD DeleteRow()
    METHOD AddRow()

    METHOD  SetFilter()

ENDCLASS
//-------------------------------------------------------------------------------------------//
METHOD New(aCampos,aTitulos,aTipos, cDbf,oBrwDbf,lNew,cNameFilter) CLASS TFilter
   Local n,k

   DEFAULT   cNameFilter := space(40)

   ::aCampos     := aCampos
   ::aTitulos    := aTitulos
   ::aTipos      := aTipos
   ::cDbf        := cDbf
   ::oBrwDbf     := oBrwDbf
   ::lNew        := lNew
   ::cNameFilter := cNameFilter
   ::cIniFilter  := cFilePath( GetModuleFileName( GetInstance() ) )  + ::cDbf +".ini"

   ::cSection    := cNameFilter
   ::nRigheSection := 0
   ::aArrayFilter := {}
   ::aRighefiltro := {}
   ::oCursorBtn   := TCursor():New(,'HAND')
   *::i            := 0
   ::lFilter     := .F.
   ::cFiltro      := ""
   ::aget:=array(6)
   ::oBtn:=array(10)

  ::cOperator    := Space( 10 )
  ::cEspressione := Space( 10 )
  ::cCampo1      := Space( 20 )
  ::cRelacion1   := Space( 20 )
  ::cValor1      := Space( 20 )

   ::nLogico      := 1
   ::acOpRelacion :=     {OpRelacion1 ,;
                              OpRelacion2 ,;
                              OpRelacion3 ,;
                              OpRelacion4 ,;
                              OpRelacion5 ,;
                              OpRelacion6 ,;
                              OpRelacion7 ,;
                              OpRelacion8 ,;
                              OpRelacion9 ,;
                              OpRelacion10 ,;
                              OpRelacion11 }

    ::acOperators     := {Operators1,Operators2,Operators3,Operators4 }

    ::cAlias := Alias()


     DEFINE FONT ::oFontDialog NAME 'Tahoma' SIZE 0, -14

 IF Empty( ::cAlias )
      MsgStop( OemToAnsi( ERRORE3 ) )
      RETURN NIL
   ENDIF




       IF ::lNew
          ::lUpper := .F.
          ::cNameFilter := space(40)
          ::lFirstrow :=.t.

       ELSE

          ::lFirstrow :=.F.
          ::nRigheSection := VAL(GetIni( ::cIniFilter, ::cSection, "Totalerighe",  ))
          ::lUpper    := IIF(GetIni( ::cIniFilter, ::cSection, "UpperCase",  )=="S",.t.,.f.)




           // scompongo le righe del file INI
           FOR n=1 to  ::nRigheSection
                AaDd(::aRighefiltro,GetIni( ::cIniFilter, ::cSection, "Riga"+ALLTRIM(str(n)),  ))
             NEXT

             FOR k=1 to len(::aRighefiltro)
                     ::aStringFilter      := New_aToken( ::aRighefiltro[k], "|" )
                     ::cOperator    := ::aStringFilter[1]
                     ::cField       := ::aStringFilter[2]
                     ::cCondition   := ::aStringFilter[3]
                     ::cEspressione := ::aStringFilter[4]
                     ::aRowData:=   { ::cOperator, ::cField, ::cCondition,  ::cEspressione}
                     AaDd(::aArrayFilter,::aRowData)
                NEXT k
                     ::cOperator    := ""
                     ::cField       := ""
                     ::cCondition   := ""
                     ::cEspressione := ""
                     adel(::aStringFilter)
        ENDIF

            IF  ::cNameFilter =FILTER_ARRAY_MENU
                ::cNameFilter := space(40)
            ENDIF

           * ::Dialog()


   RETURN self



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


 METHOD Dialog() CLASS TFilter
   Local  nBottom   := 21
   Local  nRight    := 70
   Local  nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
   Local  nHeight := nBottom * DLG_CHARPIX_H
   Local  oBtnPrev,oBtnGo,oBtnExit,oBtnHelp
   Local  bClrGrad := { | lPressed | If( ! lPressed,;
                           { { 1, nRGB( 253, 254, 255 ), nRGB( 179, 217, 255 ) } },;
                           { { 1, nRGB( 179, 217, 255 ), nRGB( 253, 254, 255 ) } } ) }

   Local oThis:=self

   DEFINE DIALOG ::oDlgFilter          ;
         SIZE nWidth, nHeight   PIXEL  ;
         TITLE ::cDlgTitle      ;
         GRADIENT { { 1,CLR_WHITE, LIGHTCYAN } } TRANSPARENT

            ::oDlgFilter:lHelpIcon := .F.
            ::oDlgFilter:nStyle    := nOR( DS_MODALFRAME, WS_POPUP, WS_CAPTION,  4 )
            ::oDlgFilter:SetFont( ::oFontDialog )





       @ 2,1 XBROWSE oThis:oBrwFilter OF oThis:oDlgFilter               ;
      COLUMNS 1, 2, 3, 4                   ;
      HEADERS TXT_OPERATOR,TXT_FIELD,TXT_CONDITION,TXT_EXPRESSION   ;
      COLSIZES 100, 100, 160, 150           ;
      ARRAY oThis:aArrayFilter LINES FASTEDIT CELL SIZE 260,80 // NOBORDER


 WITH OBJECT oThis:oBrwFilter
     :nEditTypes   := EDIT_GET
     :bPastEof     := { ||  oThis:AddRow() }
     :bKeyDown  := { |nKey| If( nKey == VK_DELETE, oThis:DeleteRow(), ;
                              If( nKey == VK_INSERT, oThis:InsertRow(), ;
                              nil ) ) }

      :lRecordSelector     := .f.
     :lHScroll             := .f.
      :lVScroll             := .f.

    :nMarqueeStyle   := MARQSTYLE_HIGHLWIN7
     :nColDividerStyle := LINESTYLE_LIGHTGRAY
     :lColDividerComplete := .t.

   :CreateFromCode()
  END



    @ 120,8    COMBOBOX ::aGet[1] VAR ::cOperator  ITEMS ::acOperators   OF ::oDlgFilter   SIZE 50,60 PIXEL  STYLE CBS_DROPDOWN
    @ 120,59   COMBOBOX ::aGet[2] VAR ::cField     ITEMS ::aTitulos      OF ::oDlgFilter   SIZE 50,60 PIXEL  STYLE CBS_DROPDOWN
    @ 120,115  COMBOBOX ::aGet[3] VAR ::cCondition ITEMS ::acOpRelacion  OF ::oDlgFilter   SIZE 75,60 PIXEL  STYLE CBS_DROPDOWN
    @ 120,195  GET      ::aGet[4] VAR ::cEspressione                     OF ::oDlgFilter   SIZE 75,12 PIXEL



    @ 10,10 SAY FILTER_NAME OF ::oDlgFilter   SIZE 80,10 PIXEL
    @ 10,55 GET ::aGet[5] VAR  ::cNameFilter   OF ::oDlgFilter   SIZE 80,10 PIXEL
    @ 10,150 CHECKBOX ::aGet[6] VAR  ::lUpper Prompt TXT_UPPER    OF ::oDlgFilter   SIZE 80,10 PIXEL


     @ 140, 10  BUTTON  ::oBtn[1] PROMPT TXT_BUTTON_ADD  SIZE 45, 12 PIXEL OF ::oDlgFilter;
                        ACTION ( oThis:AddRow( ::oBrwFilter,::aGet,::cField,::cCondition, ::cEspressione,;
                                ::cOperator,::lFirstRow,::oDlgFilter ),   ::oBrwFilter:SetFocus() )

    @ 140, 60  BUTTON   ::oBtn[2] PROMPT TXT_BUTTON_INSERT   SIZE 45, 12  PIXEL OF ::oDlgFilter;
                         ACTION ( oThis:InsertRow(), ::oBrwFilter:SetFocus() )

    @ 140,110  BUTTON   ::oBtn[3] PROMPT TXT_BUTTON_DELETE  SIZE 45, 12  PIXEL OF ::oDlgFilter;
                         ACTION ( oThis:DeleteRow(), ::oBrwFilter:SetFocus() )


    @ 140, 165  BUTTON   ::oBtn[4] PROMPT TXT_BUTTON_ACTIVATE  SIZE 45, 12  PIXEL OF ::oDlgFilter  ACTION ( ::oDlgFilter:end( IDOK ))
    @ 140, 221  BUTTON   ::oBtn[5] PROMPT TXT_BUTTON_EXIT      SIZE 45, 12  PIXEL OF ::oDlgFilter  ACTION ( ::oDlgFilter:end( IDCANCEL ) )


RETURN NIL
//-------------------------------------------------------------------------------------------//
 METHOD Activate() CLASS TFilter
   local o := self
   ACTIVATE DIALOG o:oDlgFilter center;
         ON INIT IIF(o:lNew,o:aGet[1]:hide(),)

RETURN ( ::oDlgFilter:nResult == IDOK )

//-------------------------------------------------------------------------------------------//
METHOD AddRow() CLASS TFilter
    Local RowData:=   { ::cOperator, ::cField, ::cCondition,  ::cEspressione}

   AAdd( ::oBrwFilter:aArrayData, RowData )

   ::oBrwFilter:Refresh()
   ::oBrwFilter:GoBottom()

   ::aGet[1]:show()
   ::aGet[1]:set("            ")
   ::aGet[2]:set("            ")
   ::aGet[3]:set("            ")
   ::aGet[4]:ctext:="            "

   FOR n=1 TO 4
     ::aGet[n]:refresh()
  NEXT

   ::oDlgFilter:refresh()
return nil

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

METHOD InsertRow() CLASS TFilter

   AIns( ::oBrwFilter:aArrayData, ::oBrwFilter:nArrayAt, ::BlankRow(), .t. )
   ::oBrwFilter:Refresh()

return nil

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

METHOD BlankRow  CLASS TFilter
      return { "    ", "    ", "    ", "    "}

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


METHOD DeleteRow() CLASS TFilter
   if ! Empty( ::oBrwFilter:aArrayData )
      ADel( ::oBrwFilter:aArrayData, ::oBrwFilter:nArrayAt, .t. )
      ::oBrwFilter:Refresh()
   endif

return nil

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

METHOD AddFiltro(cNomeCampo, cOpRelazione, cValore ,lUppercase)  CLASS TFilter
   LOCAL i       := 0
   LOCAL cCampo  := ""
   Local cFilterString:=""

   IF Empty( cNomeCampo ) .OR. Empty( cOpRelazione ) .OR. Empty( cValore )
      MsgStop( ERRORE1, ERRORE )
   ELSE

      cOpRelazione := Left( cOpRelazione, 2 )

      FOR i := 1 TO Len( ::aTitulos )
          IF AllTrim( ::aTitulos[ i ] ) == AllTrim( cNomeCampo )
             cCampo := ::aCampos[ i ]
             IF AllTrim( ::aTipos[ i ] ) = "C"
              If lUppercase
                cCampo := "Upper( " + cCampo + " )"
                cValore := "Upper( " + Chr(34) + AllTrim( cValore ) + Chr( 34 ) + " )"
               else
                cCampo := " " + cCampo + " "
                cValore := " " + Chr(34) + AllTrim( cValore ) + Chr( 34 ) + " "
              endif
             ELSEIF AllTrim( ::aTipos[ i ] ) = "D"
                cCampo := "DTOS( " + cCampo + " )"
                cValore := "DTOS( " + AllTrim( cValore ) + " )"
             ENDIF

             EXIT
          ENDIF
      NEXT

      cFilterString += AllTrim( cCampo ) + " " + AllTrim( cOpRelazione ) + " " + ;
                 AllTrim( cValore )

   ENDIF
RETURN cFilterString

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


METHOD  SetFilter()  CLASS TFilter
      Local  cStringFilter :=""



    IF ::oDlgFilter:nresult == IDOK

               IF !Empty(::cNameFilter)
                       cSection:=ALLtrim(::cNameFilter)
                             SetIni(  ::cIniFilter, cSection,"NomeFiltro", ::cNameFilter)
                             SetIni(  ::cIniFilter, cSection,"Uppercase", IIF(::lUpper,"S","N"))
                             SetIni(  ::cIniFilter, cSection,"TotaleRighe", ALLTRIM(str(Len( ::oBrwFilter:aArrayData))))



         For n=1 to Len( ::oBrwFilter:aArrayData)


            If n=1

                         ::cFiltro += ::AddFiltro( ::oBrwFilter:aArrayData[n][2],;
                                                   ::oBrwFilter:aArrayData[n][3],;
                                                   ::oBrwFilter:aArrayData[n][4],::lUpper )


                           SetIni( ::cIniFilter, cSection, "Riga"+ALLTRIM(str(n)),;
                                                         ALLTRIM(::oBrwFilter:aArrayData[n][1]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][2]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][3]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][4]))


                        Elseif n>1

                             DO CASE
                                CASE ::oBrwFilter:aArrayData[n][1] = Operators2
                                     ::cFiltro += " .AND. "
                                CASE ::oBrwFilter:aArrayData[n][1] = Operators3
                                     ::cFiltro += " .OR. "
                                CASE ::oBrwFilter:aArrayData[n][1] = Operators4
                                     ::cFiltro += " .NOT. "
                                  ENDCASE



                                  ::cFiltro += ::AddFiltro(::oBrwFilter:aArrayData[n][2],;
                                                           ::oBrwFilter:aArrayData[n][3],;
                                                           ::oBrwFilter:aArrayData[n][4],::lUpper )

                          SetIni( ::cIniFilter, cSection, "Riga"+ALLTRIM(str(n)),;
                                                         ALLTRIM(::oBrwFilter:aArrayData[n][1]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][2]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][3]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][4]))


                       endif
             next

                    // attiva filtro
                  //     Alert( FILTER_MSG + ::cfiltro )


            return ::cFiltro

          ELSE
             msgstop(ERRORE2)
         ENDIF
    ENDIF
RETURN NIL

* +--------------------------------------------------------------------------+
* ¦  Functions                                                               ¦
* +--------------------------------------------------------------------------+


STATIC FUNCTION SetIni( cIni, cSection, cEntry, xVar )

   LOCAL oIni


   INI oIni FILE cIni
      SET SECTION cSection ;
         ENTRY cEntry      ;
         TO xVar           ;
         OF oIni
   ENDINI

RETURN nil


STATIC FUNCTION GetIni( cIni, cSection, cEntry, xDefault )

   LOCAL oIni
   LOCAL xVar := xDefault


   INI oIni FILE cIni
      GET xVar            ;
         SECTION cSection ;
         ENTRY cEntry     ;
         DEFAULT xDefault ;
         OF oIni
   ENDINI

RETURN xVar

STATIC FUNCTION New_aToken( cString, cSeparator )
   LOCAL nPos
   LOCAL aString := {}
   DEFAULT cSeparator := "|"
   cString := ALLTRIM( cString ) + cSeparator
   DO WHILE .T.
      nPos := AT( cSeparator, cString )
      IF nPos = 0
         EXIT
      ENDIF
      AADD( aString, SUBSTR( cString, 1, nPos-1 ) )
      cString := SUBSTR( cString, nPos+1 )
   ENDDO
RETURN ( aString )










 
Last edited by Silvio.Falconi on Wed Jan 07, 2015 8:47 pm, edited 2 times in total.
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6849
Joined: Thu Oct 18, 2012 7:17 pm

Re: Tfiler Class

Postby cnavarro » Tue Jan 06, 2015 8:25 pm

Sivio
Thanks for sharing your work
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6504
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Tfiler Class

Postby elvira » Tue Jan 06, 2015 8:59 pm

Thanks a lot :D
elvira
 
Posts: 516
Joined: Fri Jun 29, 2012 12:49 pm

Re: Tfiler Class

Postby Silvio.Falconi » Tue Jan 06, 2015 10:17 pm

I made some modifies this evening . Someone ask me it into private mail

the problem : the final user not want show the dialog to modify or show filter strings but want only set the filter on his brw when select a filter name fron the list



Now you can load a filter and not show allways string filter result or dialog of creation filter

with easy commands

Code: Select all  Expand view
oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:lShowString := .T.
      cFilter :=  oFilter:LoadFilter()


      IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif
 


I change this function on File Manager and other into tfilter class
Code: Select all  Expand view


Function Load_Filter(cDbf,oGrid,oLbx)

        Local   nLen := Len( oGrid:aCols )
        Local   aCampos [ nLen ]
        Local   aTitulos[ nLen ]
        Local   aTipos  [ nLen ]
        Local   lNew:=.f.
        Local   n
        Local cFilter:= ""

       FOR n = 1 TO nLen
           aCampos   [ n ]:= oGrid:aCols[ n ]:cExpr
           aTitulos  [ n ]:= oGrid:aCols[ n ]:cHeader
           aTipos    [ n ]:= oGrid:aCols[ n ]:cDataType
       NEXT

       IF !EMPTY(oLbx)
         cSection      :=   oLbx:aArrayData[oLbx:nArrayAt]
      ENDIF


      // call the filter class

      oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:lShowString := .T.
      cFilter :=  oFilter:LoadFilter()


      IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif

  RETURN  NIL



oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)

create the obj of filter

oFilter:lShowString := .T.
show or not the string filter inti a msgalert

cFilter := oFilter:LoadFilter()

IF ! Empty( cFilter)
SET FILTER TO &cFilter
(cDbf)->( dbGoTop() )
oGrid:refresh()
Endif
set the filter on his brw and not show the dialog of filter creation


the class Tfilter with last features

Code: Select all  Expand view
#include "FiveWin.ch"
#include "xBrowse.ch"
#include "constant.ch"
#include "Filter.ch"

#DEFINE LIGHTCYAN    nRGB( 203, 225, 252 )



* +- Program ----------------------------------------------------------------+
* ¦  Application: Tfilter                                                    ¦
* ¦  Description: Dialog per crare o caricare un filtro                      ¦
* ¦       Author: Falconi Silvio                                             ¦
* ¦ Date created  09.12.2013                       Date updated:  00.00.0000 ¦
* ¦ Time created:                       Time updated:                        ¦
* ¦    Make File:                                                            ¦
* ¦    Exec File:                       Docs By:                             ¦
* ¦    Copyright: (c) 2013                                                   ¦
* ¦         FILE: crea automaticamente un file INI                           ¦
* +--------------------------------------------------------------------------+


CLASS TFilter

   DATA aCampos,aTitulos,aTipos  AS ARRAY
   DATA oDlgFilter,cDlgTitle
   DATA oBrwFilter
   DATA oDlgFilterList
   DATA cIniFilter
   DATA lNew
   DATA cFilter
   DATA cDbf
   DATA oBrwDbf
   DATA cNameFilter
   DATA cField
   DATA cCondition
   DATA oCursorBtn
   DATA oFontDialog
   DATA lFilter

   DATA cFiltro

   DATA cOperator
   DATA cEspressione
   DATA cCampo1
   DATA cRelacion1
   DATA cValor1
   DATA nLogico
   DATA acOpRelacion
   DATA acOperators
   DATA cAlias

   DATA lUpper
   DATA lFirstrow

   DATA nRigheSection, cSection
   DATA aGet  AS ARRAY
   DATA oBtn
   DATA aRighefiltro AS ARRAY
   DATA aStringFilter, aRowData
   DATA aArrayFilter

   DATA lShowString
   DATA lshowdialog


    METHOD New(aCampos,aTitulos,aTipos, cDbf,oBrwDbf,lNew,cNameFilter)   CONSTRUCTOR
    METHOD Dialog()
    METHOD Activate()
    METHOD AddFiltro()
    METHOD BlankRow()
    METHOD InsertRow()
    METHOD DeleteRow()
    METHOD AddRow()
    METHOD SetFilter()
    METHOD LoadFilter()


ENDCLASS
//-------------------------------------------------------------------------------------------//
METHOD New(aCampos,aTitulos,aTipos, cDbf,oBrwDbf,lNew,cNameFilter,lShowString) CLASS TFilter
   Local n,k

DEFAULT cNameFilter := space(40)
DEFAULT lShowString    := .F.



   ::aCampos     := aCampos
   ::aTitulos    := aTitulos
   ::aTipos      := aTipos
   ::cDbf        := cDbf
   ::oBrwDbf     := oBrwDbf
   ::lNew        := lNew
   ::cNameFilter := cNameFilter
   ::cIniFilter  := cFilePath( GetModuleFileName( GetInstance() ) )  + ::cDbf +".ini"

   ::cSection    := cNameFilter
   ::nRigheSection := 0
   ::aArrayFilter := {}
   ::aRighefiltro := {}
   ::oCursorBtn   := TCursor():New(,'HAND')
   *::i            := 0
   ::lFilter     := .F.
   ::cFiltro      := ""
   ::aget:=array(6)
   ::oBtn:=array(10)

  ::cOperator    := Space( 10 )
  ::cEspressione := Space( 40 )
  ::cCampo1      := Space( 20 )
  ::cRelacion1   := Space( 20 )
  ::cValor1      := Space( 40 )


 
  ::lShowString := lShowString

   ::nLogico      := 1
   ::acOpRelacion :=     {OpRelacion1 ,;
                              OpRelacion2 ,;
                              OpRelacion3 ,;
                              OpRelacion4 ,;
                              OpRelacion5 ,;
                              OpRelacion6 ,;
                              OpRelacion7 ,;
                              OpRelacion8 ,;
                              OpRelacion9 ,;
                              OpRelacion10 ,;
                              OpRelacion11 }

    ::acOperators     := {Operators1,Operators2,Operators3,Operators4 }

    ::cAlias := Alias()


     DEFINE FONT ::oFontDialog NAME 'Tahoma' SIZE 0, -14

 IF Empty( ::cAlias )
      MsgStop( OemToAnsi( ERRORE3 ) )
      RETURN NIL
   ENDIF




       IF ::lNew
          ::lUpper := .F.
          ::cNameFilter := space(40)
          ::lFirstrow :=.t.

       ELSE

          ::lFirstrow :=.F.
          ::nRigheSection := VAL(GetIni( ::cIniFilter, ::cSection, "Totalerighe",  ))
          ::lUpper    := IIF(GetIni( ::cIniFilter, ::cSection, "UpperCase",  )=="S",.t.,.f.)




           // scompongo le righe del file INI
           FOR n=1 to  ::nRigheSection
                AaDd(::aRighefiltro,GetIni( ::cIniFilter, ::cSection, "Riga"+ALLTRIM(str(n)),  ))
             NEXT

             FOR k=1 to len(::aRighefiltro)
                     ::aStringFilter      := New_aToken( ::aRighefiltro[k], "|" )
                     ::cOperator    := ::aStringFilter[1]
                     ::cField       := ::aStringFilter[2]
                     ::cCondition   := ::aStringFilter[3]
                     ::cEspressione := ::aStringFilter[4]
                     ::aRowData:=   { ::cOperator, ::cField, ::cCondition,  ::cEspressione}
                     AaDd(::aArrayFilter,::aRowData)
                NEXT k
                     ::cOperator    := ""
                     ::cField       := ""
                     ::cCondition   := ""
                     ::cEspressione := ""
                     adel(::aStringFilter)
        ENDIF

            IF  ::cNameFilter =FILTER_ARRAY_MENU
                ::cNameFilter := space(40)
            ENDIF



   RETURN self



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


 METHOD Dialog() CLASS TFilter
   Local  nBottom   := 21
   Local  nRight    := 70
   Local  nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
   Local  nHeight := nBottom * DLG_CHARPIX_H
   Local  oBtnPrev,oBtnGo,oBtnExit,oBtnHelp
   Local  bClrGrad := { | lPressed | If( ! lPressed,;
                           { { 1, nRGB( 253, 254, 255 ), nRGB( 179, 217, 255 ) } },;
                           { { 1, nRGB( 179, 217, 255 ), nRGB( 253, 254, 255 ) } } ) }

   Local oThis:=self





   DEFINE DIALOG ::oDlgFilter          ;
         SIZE nWidth, nHeight   PIXEL  ;
         TITLE ::cDlgTitle      ;
         GRADIENT { { 1,CLR_WHITE, LIGHTCYAN } } TRANSPARENT

            ::oDlgFilter:lHelpIcon := .F.
            ::oDlgFilter:nStyle    := nOR( DS_MODALFRAME, WS_POPUP, WS_CAPTION,  4 )
            ::oDlgFilter:SetFont( ::oFontDialog )





       @ 2,1 XBROWSE oThis:oBrwFilter OF oThis:oDlgFilter               ;
      COLUMNS 1, 2, 3, 4                   ;
      HEADERS TXT_OPERATOR,TXT_FIELD,TXT_CONDITION,TXT_EXPRESSION   ;
      COLSIZES 100, 100, 160, 150           ;
      ARRAY oThis:aArrayFilter LINES FASTEDIT CELL SIZE 260,80 // NOBORDER


 WITH OBJECT oThis:oBrwFilter
     :nEditTypes   := EDIT_GET
     :bPastEof     := { ||  oThis:AddRow() }
     :bKeyDown  := { |nKey| If( nKey == VK_DELETE, oThis:DeleteRow(), ;
                              If( nKey == VK_INSERT, oThis:InsertRow(), ;
                              nil ) ) }

      :lRecordSelector     := .f.
     :lHScroll             := .f.
      :lVScroll             := .f.

    :nMarqueeStyle   := MARQSTYLE_HIGHLWIN7
     :nColDividerStyle := LINESTYLE_LIGHTGRAY
     :lColDividerComplete := .t.

   :CreateFromCode()
  END



    @ 120,8    COMBOBOX ::aGet[1] VAR ::cOperator  ITEMS ::acOperators   OF ::oDlgFilter   SIZE 50,60 PIXEL  STYLE CBS_DROPDOWN
    @ 120,59   COMBOBOX ::aGet[2] VAR ::cField     ITEMS ::aTitulos      OF ::oDlgFilter   SIZE 50,60 PIXEL  STYLE CBS_DROPDOWN
    @ 120,115  COMBOBOX ::aGet[3] VAR ::cCondition ITEMS ::acOpRelacion  OF ::oDlgFilter   SIZE 75,60 PIXEL  STYLE CBS_DROPDOWN
    @ 120,195  GET      ::aGet[4] VAR ::cEspressione                     OF ::oDlgFilter   SIZE 75,12 PIXEL



    @ 10,10 SAY FILTER_NAME OF ::oDlgFilter   SIZE 80,10 PIXEL
    @ 10,55 GET ::aGet[5] VAR  ::cNameFilter   OF ::oDlgFilter   SIZE 80,10 PIXEL
    @ 10,150 CHECKBOX ::aGet[6] VAR  ::lUpper Prompt TXT_UPPER    OF ::oDlgFilter   SIZE 80,10 PIXEL


     @ 140, 10  BUTTON  ::oBtn[1] PROMPT TXT_BUTTON_ADD  SIZE 45, 12 PIXEL OF ::oDlgFilter;
                        ACTION ( oThis:AddRow( ::oBrwFilter,::aGet,::cField,::cCondition, ::cEspressione,;
                                ::cOperator,::lFirstRow,::oDlgFilter ),   ::oBrwFilter:SetFocus() )

    @ 140, 60  BUTTON   ::oBtn[2] PROMPT TXT_BUTTON_INSERT   SIZE 45, 12  PIXEL OF ::oDlgFilter;
                         ACTION ( oThis:InsertRow(), ::oBrwFilter:SetFocus() )

    @ 140,110  BUTTON   ::oBtn[3] PROMPT TXT_BUTTON_DELETE  SIZE 45, 12  PIXEL OF ::oDlgFilter;
                         ACTION ( oThis:DeleteRow(), ::oBrwFilter:SetFocus() )


    @ 140, 165  BUTTON   ::oBtn[4] PROMPT TXT_BUTTON_ACTIVATE  SIZE 45, 12  PIXEL OF ::oDlgFilter  ACTION ( ::oDlgFilter:end( IDOK ))
    @ 140, 221  BUTTON   ::oBtn[5] PROMPT TXT_BUTTON_EXIT      SIZE 45, 12  PIXEL OF ::oDlgFilter  ACTION ( ::oDlgFilter:end( IDCANCEL ) )

 

RETURN NIL
//-------------------------------------------------------------------------------------------//
 METHOD Activate() CLASS TFilter
    local o := self

 
   ACTIVATE DIALOG o:oDlgFilter center;
         ON INIT IIF(o:lNew,o:aGet[1]:hide(),)
 


RETURN ( ::oDlgFilter:nResult == IDOK )

//-------------------------------------------------------------------------------------------//
METHOD AddRow() CLASS TFilter
    Local RowData:=   { ::cOperator, ::cField, ::cCondition,  ::cEspressione}

   AAdd( ::oBrwFilter:aArrayData, RowData )

   ::oBrwFilter:Refresh()
   ::oBrwFilter:GoBottom()

   ::aGet[1]:show()
   ::aGet[1]:set("            ")
   ::aGet[2]:set("            ")
   ::aGet[3]:set("            ")
   ::aGet[4]:ctext:="            "

   FOR n=1 TO 4
     ::aGet[n]:refresh()
  NEXT

   ::oDlgFilter:refresh()
return nil

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

METHOD InsertRow() CLASS TFilter

   AIns( ::oBrwFilter:aArrayData, ::oBrwFilter:nArrayAt, ::BlankRow(), .t. )
   ::oBrwFilter:Refresh()

return nil

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

METHOD BlankRow  CLASS TFilter
      return { "    ", "    ", "    ", "    "}

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


METHOD DeleteRow() CLASS TFilter
   if ! Empty( ::oBrwFilter:aArrayData )
      ADel( ::oBrwFilter:aArrayData, ::oBrwFilter:nArrayAt, .t. )
      ::oBrwFilter:Refresh()
   endif

return nil

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

METHOD AddFiltro(cNomeCampo, cOpRelazione, cValore ,lUppercase)  CLASS TFilter
   LOCAL i       := 0
   LOCAL cCampo  := ""
   Local cFilterString:=""

   IF Empty( cNomeCampo ) .OR. Empty( cOpRelazione ) .OR. Empty( cValore )
      MsgStop( ERRORE1, ERRORE )
   ELSE

      cOpRelazione := Left( cOpRelazione, 2 )

      FOR i := 1 TO Len( ::aTitulos )
          IF AllTrim( ::aTitulos[ i ] ) == AllTrim( cNomeCampo )
             cCampo := ::aCampos[ i ]
             IF AllTrim( ::aTipos[ i ] ) = "C"
              If lUppercase
                cCampo := "Upper( " + cCampo + " )"
                cValore := "Upper( " + Chr(34) + AllTrim( cValore ) + Chr( 34 ) + " )"
               else
                cCampo := " " + cCampo + " "
                cValore := " " + Chr(34) + AllTrim( cValore ) + Chr( 34 ) + " "
              endif
             ELSEIF AllTrim( ::aTipos[ i ] ) = "D"
                cCampo := "DTOS( " + cCampo + " )"
                cValore := "DTOS( " + AllTrim( cValore ) + " )"
             ENDIF

             EXIT
          ENDIF
      NEXT

      cFilterString += AllTrim( cCampo ) + " " + AllTrim( cOpRelazione ) + " " + ;
                 AllTrim( cValore )

   ENDIF
RETURN cFilterString

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


METHOD  SetFilter()  CLASS TFilter
      Local  cStringFilter :=""


    IF ::oDlgFilter:nresult == IDOK

               IF !Empty(::cNameFilter)
                       cSection:=ALLtrim(::cNameFilter)
                             SetIni(  ::cIniFilter, cSection,"NomeFiltro", ::cNameFilter)
                             SetIni(  ::cIniFilter, cSection,"Uppercase", IIF(::lUpper,"S","N"))
                             SetIni(  ::cIniFilter, cSection,"TotaleRighe", ALLTRIM(str(Len( ::oBrwFilter:aArrayData))))



         For n=1 to Len( ::oBrwFilter:aArrayData)


            If n=1

                         ::cFiltro += ::AddFiltro( ::oBrwFilter:aArrayData[n][2],;
                                                   ::oBrwFilter:aArrayData[n][3],;
                                                   ::oBrwFilter:aArrayData[n][4],::lUpper )


                           SetIni( ::cIniFilter, cSection, "Riga"+ALLTRIM(str(n)),;
                                                         ALLTRIM(::oBrwFilter:aArrayData[n][1]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][2]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][3]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][4]))


                        Elseif n>1

                             DO CASE
                                CASE ::oBrwFilter:aArrayData[n][1] = Operators2
                                     ::cFiltro += " .AND. "
                                CASE ::oBrwFilter:aArrayData[n][1] = Operators3
                                     ::cFiltro += " .OR. "
                                CASE ::oBrwFilter:aArrayData[n][1] = Operators4
                                     ::cFiltro += " .NOT. "
                                  ENDCASE



                                  ::cFiltro += ::AddFiltro(::oBrwFilter:aArrayData[n][2],;
                                                           ::oBrwFilter:aArrayData[n][3],;
                                                           ::oBrwFilter:aArrayData[n][4],::lUpper )

                          SetIni( ::cIniFilter, cSection, "Riga"+ALLTRIM(str(n)),;
                                                         ALLTRIM(::oBrwFilter:aArrayData[n][1]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][2]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][3]+"|"+;
                                                                 ::oBrwFilter:aArrayData[n][4]))


                       endif
             next

             IF ::lShowString
                    // attiva filtro
                       Alert( FILTER_MSG + ::cfiltro )
              ENDIF

            return ::cFiltro

          ELSE
             msgstop(ERRORE2)
         ENDIF
    ENDIF
    RETURN NIL



  METHOD LoadFilter()    CLASS TFilter
      Local n

                   For n=1 to Len( ::aArrayFilter)


                   If n=1

                         ::cFiltro += ::AddFiltro( ::aArrayFilter[n][2],;
                                                   ::aArrayFilter[n][3],;
                                                   ::aArrayFilter[n][4],::lUpper )



                     Elseif n>1

                             DO CASE
                                CASE ::aArrayFilter[n][1] = Operators2
                                     ::cFiltro += " .AND. "
                                CASE ::aArrayFilter[n][1] = Operators3
                                     ::cFiltro += " .OR. "
                                CASE ::aArrayFilter[n][1] = Operators4
                                     ::cFiltro += " .NOT. "
                                  ENDCASE

                       ::cFiltro += ::AddFiltro(::aArrayFilter[n][2],;
                                                ::aArrayFilter[n][3],;
                                                ::aArrayFilter[n][4],::lUpper )

                        endif
             next

             IF ::lShowString
                    // attiva filtro
                       Alert( FILTER_MSG + ::cfiltro )
              ENDIF

            return ::cFiltro

           



* +--------------------------------------------------------------------------+
* ¦  Functions                                                               ¦
* +--------------------------------------------------------------------------+


STATIC FUNCTION SetIni( cIni, cSection, cEntry, xVar )

   LOCAL oIni


   INI oIni FILE cIni
      SET SECTION cSection ;
         ENTRY cEntry      ;
         TO xVar           ;
         OF oIni
   ENDINI

RETURN nil


STATIC FUNCTION GetIni( cIni, cSection, cEntry, xDefault )

   LOCAL oIni
   LOCAL xVar := xDefault


   INI oIni FILE cIni
      GET xVar            ;
         SECTION cSection ;
         ENTRY cEntry     ;
         DEFAULT xDefault ;
         OF oIni
   ENDINI

RETURN xVar

STATIC FUNCTION New_aToken( cString, cSeparator )
   LOCAL nPos
   LOCAL aString := {}
   DEFAULT cSeparator := "|"
   cString := ALLTRIM( cString ) + cSeparator
   DO WHILE .T.
      nPos := AT( cSeparator, cString )
      IF nPos = 0
         EXIT
      ENDIF
      AADD( aString, SUBSTR( cString, 1, nPos-1 ) )
      cString := SUBSTR( cString, nPos+1 )
   ENDDO
RETURN ( aString )
 




If you want modify a filter you must create a function like this ( or use it from your app)

Code: Select all  Expand view
Function Modify_Filter(cDbf,oGrid,oLbx)

        Local   nLen := Len( oGrid:aCols )
        Local   aCampos [ nLen ]
        Local   aTitulos[ nLen ]
        Local   aTipos  [ nLen ]
        Local   lNew:=.f.
        Local   n
        Local cFilter:= ""

       FOR n = 1 TO nLen
           aCampos   [ n ]:= oGrid:aCols[ n ]:cExpr
           aTitulos  [ n ]:= oGrid:aCols[ n ]:cHeader
           aTipos    [ n ]:= oGrid:aCols[ n ]:cDataType
       NEXT

       IF !EMPTY(oLbx)
         cSection      :=   oLbx:aArrayData[oLbx:nArrayAt]
      ENDIF


      // call the filter class

      oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:Dialog()
      oFilter:Activate()
      cFilter := oFilter:SetFilter()


      IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif

  RETURN  NIL



Remember to call tfilter class you need

an array with the name of fields

an array with the name of headers

an array with type of fields

a dbf

a object oGrid ( I use xbrowse )

lnew value if is a new filter or not

and the name of cSection of Ini file

the ini file where you saved or you'll save the string filter

I created filmanager to use easy the tfilter class


If you use LoadFilter() method to load only the cFilter string

then not must use Dialog(),Activate() and setfilter() methods

the loadFilter method read on your inifile the filter ( csection) selected by user


a sample of filter saved on a file INI ( I used on samples cus.ini)

If we want show all customer with name Frank



Code: Select all  Expand view

[All customers his name is Frank]
NomeFiltro=All customers his name is Frank                                  
Uppercase=S
TotaleRighe=1
Riga1=|First|=  uguale          |Frank

 


on this code yuofound only a row, luppercase is .t.
you can try it
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6849
Joined: Thu Oct 18, 2012 7:17 pm

Re: Tfiler Class

Postby Silvio.Falconi » Wed Jan 07, 2015 9:32 am

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6849
Joined: Thu Oct 18, 2012 7:17 pm

Re: Tfilter Class

Postby cdmmaui » Fri Jan 23, 2015 4:54 pm

Dear Silvio,

Can you send RAR directly to me? My security is blocking that website for some reason. My e-mail address is Darrell DOT Ortiz AT cdmsoft DOT com.

I appreciate your assistance!
*~*~*~*~*~*~*~*~*~*
Darrell Ortiz
CDM Software Solutions, Inc.
https://www.cdmsoft.com
User avatar
cdmmaui
 
Posts: 689
Joined: Fri Oct 28, 2005 9:53 am
Location: Houston ∙ Chicago ∙ Los Angeles ∙ Miami ∙ London ∙ Hong Kong

Re: Tfilter Class

Postby cdmmaui » Tue Jan 27, 2015 3:27 am

Dear Silvio,

Is it possible for you to send me RAR of Tfilter class with sample code?

Thank you,
*~*~*~*~*~*~*~*~*~*
Darrell Ortiz
CDM Software Solutions, Inc.
https://www.cdmsoft.com
User avatar
cdmmaui
 
Posts: 689
Joined: Fri Oct 28, 2005 9:53 am
Location: Houston ∙ Chicago ∙ Los Angeles ∙ Miami ∙ London ∙ Hong Kong

Re: Tfilter Class

Postby richard-service » Tue Jan 27, 2015 5:11 am

cdmmaui wrote:Dear Silvio,

Is it possible for you to send me RAR of Tfilter class with sample code?

Thank you,


Dear Darrell
I will send to you right now. Please check your EMail.
Best Regards,

Richard

Harbour 3.2.0dev (r2402101027) => Borland C++ v7.7 32bit
MySQL v5.7 /ADS v10
Harbour 3.2.0dev (r2011030937) => Borland C++ v7.4 64bit
User avatar
richard-service
 
Posts: 772
Joined: Tue Oct 16, 2007 8:57 am
Location: New Taipei City, Taiwan

Re: Tfilter Class

Postby cdmmaui » Tue Jan 27, 2015 5:26 am

Thank you Richard. I received it
*~*~*~*~*~*~*~*~*~*
Darrell Ortiz
CDM Software Solutions, Inc.
https://www.cdmsoft.com
User avatar
cdmmaui
 
Posts: 689
Joined: Fri Oct 28, 2005 9:53 am
Location: Houston ∙ Chicago ∙ Los Angeles ∙ Miami ∙ London ∙ Hong Kong

Re: Tfilter Class

Postby Antonio Linares » Tue Jan 27, 2015 6:09 am

Silvio,

Could you provide a screenshot ?

Filters are very slow. Whats the point to use them ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41405
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Tfilter Class

Postby Silvio.Falconi » Tue Jan 27, 2015 8:25 am

Antonio,

I use this for my app for sample I wish show (on a xbrowe) all customers of a city or Region or
By saving a file suits research I can see in a moment what I want to see.

Another example: I have a small program to the family budget. Use the calss Tfilter to try the movements of all the months from January to December without being each time to recreate the filter

The filter manager is an small a function to show the filter but I use a combo with Xbrowse to show the filters and recreate a new

Perhaps a second simply test can show what I say


Image

Image

Image




insert CUSTOMER.dbf on your folder test

cust.ini
Code: Select all  Expand view
[State IL]
NomeFiltro=State IL                                
Uppercase=S
TotaleRighe=1
Riga1=|State|== esattamente uguale|IL
[State WA]
NomeFiltro=State WA                                
Uppercase=S
TotaleRighe=1
Riga1=|State|== esattamente uguale|WA



test2.prg
Code: Select all  Expand view

#include 'fivewin.ch'
#include 'xbrowse.ch'
#include 'Filter.ch'

* +- Program ----------------------------------------------------------------+
* ¦  Application: Tfilter                                                    ¦
* ¦  Description: Dialog per creare o caricare un filtro                      ¦
* ¦       Author: Falconi Silvio                                             ¦
* ¦ Date created  09.12.2013                       Date updated:  00.00.0000 ¦
* ¦ Time created:                       Time updated:                        ¦
* ¦    Make File:                                                            ¦
* ¦    Exec File:                       Docs By:                             ¦
* ¦    Copyright: (c) 2013                                                   ¦
* ¦         FILE: crea automaticamente un file INI                           ¦
* +--------------------------------------------------------------------------+

function Main()

   local oDlg, oBrw, oFont
   Local oBtnFiltro[3],cFilter:=""
   //-------------//
   Local cIniFilter:=triM(cFilePath( GetModuleFileName( GetInstance() ) )  + "Cust" +".ini")
   Local  aFilters      := GETPVPROFSECTIONS( cIniFilter )
   //---------------//
 /*  If !Empty( cIniFilter)
          hIniFile      := HB_ReadIni( cIniFilter )
          aFilters:=HGetKeys( hIniFile )
   endif
  *       */


   aadd(aFilters, FILTER_ARRAY_MENU)

   SET DATE ITALIAN
   SET CENTURY ON

   FwNumFormat( 'E', .t. )

   USE CUSTOMER ALIAS CUST

   DEFINE FONT oFont NAME 'Tahoma' SIZE 0, -14

   DEFINE DIALOG oDlg SIZE 640,440 PIXEL ;
      FONT oFont TITLE 'Filter test' ;
      COLOR CLR_BLACK,RGB(250,250,250)

   @ 10,20 XBROWSE oBrw OF oDlg SIZE -10,-20 PIXEL ;
      COLUMNS "First", "State", "Age", "HireDate", "Salary" ;
      ALIAS 'CUST' NOBORDER

   oBrw:lRecordSelector := .f.
   oBrw:nMarqueeStyle   := MARQSTYLE_HIGHLWIN7

   WITH OBJECT oBrw:InsCol( 1 )

      :cHeader       := " "
      :bEditValue    := { || If( AScan( oBrw:aSelected, oBrw:BookMark ) > 0, .t., nil ) }
      :SetCheck()
      :nHeadBmpNo    := { || If( Len( oBrw:aSelected ) == oBrw:nLen, 1, 2 ) }
      :bLClickHeader := { |r,c,f,oCol| If( Len( oBrw:aSelected ) == oBrw:nLen, ;
                                           oBrw:SelectNone(), oBrw:SelectAll() ) }

   END

   oBrw:CreateFromCode()


   @ 204,22 COMBOBOX oBtnFiltro[1] VAR cFilter  ITEMS aFilters SIZE 140,90 PIXEL OF oDlg  ;
   ON CHANGE (Go_Filter('CUST',oBrw,cFilter))


   @ 204,172 BTNBMP  oBtnFiltro[2] FILENAME "SH_NOFILTER.bmp" SIZE 10,10 PIXEL OF oDlg NOBORDER ;
   ACTION ( CUST->(DbClearFilter()),CUST->(DbGoTop()),oBrw:refresh()  ) ;
   TOOLTIP "Erase filter active"   // WHEN !empty(cFilter)

  @ 204,242 BUTTON  oBtnFiltro[3] PROMPT "MANAGER" SIZE 40,10 PIXEL OF oDlg  ;
   ACTION  (Filter_Manager('CUST',oBrw,"Cust"),;
            aFilters      := GETPVPROFSECTIONS( cIniFilter ),;
            oBtnFiltro[1]:REFRESH())

   ACTIVATE DIALOG oDlg CENTERED

   RELEASE FONT oFont

return nil


STATIC FUNCTION GETPVPROFSECTIONS( cIni )

        LOCAL cBuf := SPACE( 65536 )

        LOCAL aSec := {}

        GETPRIVATEPROFILESECTIONNAMES( cBuf, 65536, cIni )

        WHILE LEFT( cBuf, 1 ) != CHR( 0 )
            AADD( aSec, LEFT( cBuf, AT( CHR( 0 ), cBuf ) - 1 ) )
            cBuf = SUBSTR( cBuf, AT( CHR( 0 ), cBuf ) + 1 )
        ENDDO

        RETURN aSec


 DLL STATIC FUNCTION GETPRIVATEPROFILESECTIONNAMES( cRetBuf AS LPSTR, nSize AS LONG, cFileName AS LPSTR ) AS DWORD;
        PASCAL FROM "GetPrivateProfileSectionNamesA" LIB "kernel32.dll"





 




the Go_filter function ( it is very fast)
the variable : oFilter:lShowString := .F. is for not show the string of filter ( with a msginfo)
when you select a option from combobox it create the filter and refresh the xbrowse


Set the vaule of FILTER_ARRAY_MENU
it is aoption of combobox sample "Insert or Modify"
when the final user select it from combobox it open the filemananger app



Code: Select all  Expand view

Function Go_Filter(cDbf,oGrid,cFilter)

        Local   nLen := Len( oGrid:aCols )
        Local   aCampos [ nLen ]
        Local   aTitulos[ nLen ]
        Local   aTipos  [ nLen ]
        Local   lNew

       FOR n = 1 TO nLen
           aCampos   [ n ]:= oGrid:aCols[ n ]:cExpr
           aTitulos  [ n ]:= oGrid:aCols[ n ]:cHeader
           aTipos    [ n ]:= oGrid:aCols[ n ]:cDataType
       NEXT



       IF alltrim(cFilter)==FILTER_ARRAY_MENU
          lNew:=.t.
          cSection:=""
          Create_Filter(cDbf,oGrid)
       else
          cSection      :=   cFilter
          lNew:=.F.
       Endif



      oFilter:= TFilter():New(aCampos,aTitulos,aTipos, cDbf,oGrid,lNew,cSection)
      oFilter:lShowString := .f.
      cFilter :=  oFilter:LoadFilter()


      IF ! Empty( cFilter)
             SET FILTER TO &cFilter
             (cDbf)->(  dbGoTop() )
             oGrid:refresh()
       Endif

  RETURN

 


If you use the combo it is more fast

remember to press the button no filter to clear the filter on xbrowse and generate another filter


then on future when can insert the possibility to insert function on field and expression...
Last edited by Silvio.Falconi on Tue Jan 27, 2015 8:30 am, edited 1 time in total.
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6849
Joined: Thu Oct 18, 2012 7:17 pm

Re: Tfilter Class

Postby Silvio.Falconi » Tue Jan 27, 2015 8:27 am

I thik it could be insert on Xbrowse class ... so we can filter any data
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6849
Joined: Thu Oct 18, 2012 7:17 pm


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 31 guests