This is the complete method. It is actually derived from FiveDBU.prg, but customized only for .dbf files since that is all I use in the program.
The purpose is to allow the end user to build a filter string. The aNames array contains the names of the fields. The aTypes array holds the corresponding type for each field so it can be entered properly in the filter.
This worked perfectly until the last library I received from Antonio to correct another issue.
Here is the full method code:
Code: Select all | Expand
METHOD FilterDbf( )
MEMVAR oBrush, oMFont
LOCAL cFilterField := SPACE(20), cFilterValue := SPACE( 50 ), cOpsType := "="
LOCAL cFilterString := SPACE( 200 )
LOCAL lDoFilter := .f., lClearFilter := .t.
LOCAL cProcessString, nFilterField
PRIVATE aTypes, aNames, nFlds, oFRec, cFilterType, cField2, cFField3
PRIVATE aOpsType := { "=", "<", "<=", "<>", ">=", ">" }
nFlds := ::oDbf:Fcount( )
aNames := Array( nFlds )
aTypes := Array( nFlds )
aFields( aNames, aTypes )
// Create the DIALOG
DEFINE DIALOG oFRec OF ::oEwndChild RESOURCE "FEFILTERW" BRUSH oBrush TRANSPARENT TITLE "Search/Filter the Database" FONT oMFont
oFRec:nHelpID := 1300
// And the new value
REDEFINE GET cFilterString ID 601 OF oFRec MESSAGE "Enter the new filter/search command line"
// Select the field
REDEFINE COMBOBOX cFilterField ITEMS aNames ID 602 OF oFRec ;
STYLE CBS_DROPDOWN MESSAGE "Select the field for selecting records"
// Next select the operator
REDEFINE COMBOBOX cOpsType ITEMS aOpsType ID 603 OF oFRec ;
STYLE CBS_DROPDOWN MESSAGE "Select the comparison operator"
// Then get the value
REDEFINE GET cFilterValue ID 604 OF oFRec MESSAGE "Enter the current value to match"
REDEFINE BTNBMP RESOURCE "HROK" PROMPT "Process Filter" ID 610 of oFRec NOBORDER TRANSPARENT ;
ACTION ( lDoFilter := .t., oFRec:end() )
REDEFINE BTNBMP RESOURCE "HREXIT" PROMPT "Exit & Clear Filter" ID 611 of oFRec NOBORDER TRANSPARENT ;
ACTION ( lClearFilter, oFRec:end() )
ACTIVATE DIALOG oFRec ON INIT ( oFRec:center(wndmain()) )
IF lDoFilter
IF EMPTY( cFilterString )
// We want the field number of the replacement field
cFilterField := TRIM( cFilterField )
nFilterField := Ascan( aNames, cFilterField )
// We want the type of data of the selected field
cFilterType := aTypes[ nFilterField ]
// Make sure the new value matches the type of the field and is defined as vNewValue
IF cFilterType = "C" .OR. cFilterType = "M"
cFField3 := ( '"' + TRIM( cFilterValue ) + '"' )
ELSEIF cFilterType = "D"
cFField3 := DTOS( cFilterValue )
ELSEIF cFilterType = "N" .OR. cFilterType = "L"
cFField3 := cValToChar( cFilterValue )
ELSE
cFField3 := " "
ENDIF
IF ! EMPTY( cFField3 )
cProcessString := cFilterField + cOpsType + cFField3
ELSE
cProcessString := " "
ENDIF
ELSE
cProcessString := cFilterString
ENDIF
IF EMPTY( cProcessString )
lClearFilter := .t.
ELSE
::oDbf:setfilter( cProcessString )
::oDbf:gotop( )
lClearFilter := .f.
ENDIF
ENDIF
IF lClearFilter
::oDbf:SetFilter( )
::oDbf:gotop( )
ENDIF
RETURN NIL