Page 1 of 1
Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 12:38 am
by TimStone
In the past I have used the following code to obtain the field names and types for an "in use" database. This is used to build a Filter statement in a variant of FiveDBU. It has worked correctly for many years.
Code: Select all | Expand
nFlds := ::oDbf:Fcount( )
aNames := Array( nFlds )
aTypes := Array( nFlds )
aFields( aNames, aTypes )
aFields would fill the array with the names of each field, and aTypes with the data type for that same field. Now it simply inserting 3 items into the aNames array ( labels ), and nothing else, although the database has 12 actual fields. What is inserted has no bearing to the actual fields.
As I said, it was never a problem until the latest FWH libs. I'm open to a better way if anyone has a suggestion. NOTE: I am using a database object in this class.
Tim
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 5:14 am
by Antonio Linares
Dear Tim,
This is working fine:
local aInfo := DbStruct()
XBrowse( aInfo )
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 5:22 am
by TimStone
With a data object ?
ODbf is opened in a class, and here we need to see it’s fields in a combobox to build a filter.
I did not see dbstruct() as a method in tdatabase class
Sent from my iPhone using Tapatalk
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 5:25 am
by Antonio Linares
Dear Tim,
DbStruct() is a Harbour function, so as long as you are in the right workarea it will work fine
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 5:57 am
by Antonio Linares
It can be easily added to Class TDataBase this way:
METHOD DbStruct() INLINE ( ::cAlias )->( DbStruct() )
or simply
METHOD Struct() INLINE ( ::cAlias )->( DbStruct() )
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 6:56 am
by nageswaragunupudi
Even without any changes to TDatabase class, you can use
Note: If you are using unmodified tdatabase class, you can use any Harbour function as a method.
eg:
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 7:08 am
by nageswaragunupudi
Is aFields() your function?
There has never been a function with this name in FWH in any version
till now.
Can you please let us know in which version of FWH the code you posted was working?
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 7:39 am
by nageswaragunupudi
In any case, if you want an array of only fieldnames and fieldtypes
Code: Select all | Expand
aFields := ArrTranspose( ASize( ArrTranspose( oDbf:aStruct ), 2 ) )
Test:
Code: Select all | Expand
oDbf := TDatabase():Open( nil, "STATES.DBF" )
aFields := ArrTranspose( ASize( ArrTranspose( oDbf:aStruct ), 2 ) )
XBROWSER aFields
Re: Problem with aFields( ) in most recent version of FWH
Posted: Thu Jul 04, 2024 6:55 pm
by TimStone
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