DbCombo Problem (Solved)

DbCombo Problem (Solved)

Postby anserkk » Fri Aug 07, 2009 7:37 am

Hi friends,

I have a Dialog with 2 DbCombo's.
1) DbCombo1 contains the Department names
2) DbCombo2 contains the Employee Names of those belong to the Department Selected in DbCombo1

My Requirement

Once the user selects a Department Name in DbCombo1, the array items of DbCombo2 is reset and only the employees who belong to the selected department should be listed. This part is working fine.

I need the DbCombo2 to select the name of the 1st employee in the list by default, which is not happening. Eventhough I assign the Employee code, the value is lost.

Actually I am working on MySQL, FWH xHarbour environment. To replicate the problem, I have created a sample program using DBF and arrays. As DbCombo does not support RecordSets, I create Arrays from RecordSet and use it with DbCombo. Instead of MySql Tables I have used DBF files to explain the problem.

Here is the sample code. Any help ?. I don't know where I am going wrong.
A cut and paste of the below given code can be used to test the problem mentioned by me.

Code: Select all  Expand view
#Include "FiveWin.Ch"
#Include "DbCombo.Ch"

*------------------------------------------*
Function LogMeIn()
*------------------------------------------*
Local oDlg,oDbCmbEmployees,oDbCmbDepartment,oBtnLogin,oBtnCancel
Local nStyle,nDeptRecNo
Local aEmpCodes:={}, aEmpNames:={} , aDeptNames:={} , aDeptRecNo:={}
Local IsConnected,IsAllOK
Local aStructure

SET EXCLUSIVE ON


if !File("DEPARTMENT.DBF")
    aStructure := {}
    aAdd(aStructure,{"DEPT_NAME","C",11,0})
    DbCreate("DEPARTMENT.DBF",aStructure)
endif

Select A
USE DEPARTMENT
ZAP

aData:={"Sales Dept.",;
        "IT Dept.   ",;
        "Accts Dept." }
       
For i:=1 to len(aData)        
    APPEND BLANK
    REPLACE DEPT_NAME with aData[i]
Next


if !File("EMPLOYEES.DBF")
    aStructure := {}
    aAdd(aStructure,{"EMP_CODE" ,"N", 3,0})
    aAdd(aStructure,{"EMP_NAME" ,"C",30,0})
    aAdd(aStructure,{"DEPT_NAME","C",11,0})
   
    DbCreate("EMPLOYEES.DBF",aStructure)
ENDIF

Select B
USE EMPLOYEES
ZAP

aData:={}
aData:={ {1,"Anser (Sales)"   , "Sales Dept."},;
         {2,"John (Sales)"    , "Sales Dept."},;
         {3,"Abraham (Sales)" , "Sales Dept."},;        
         {4,"Anser (IT)"      , "IT Dept.   "},;
         {5,"John (IT)"       , "IT Dept.   "},;
         {6,"Abraham (IT)"    , "IT Dept.   "},;        
         {7,"Anser (Accts)"   , "Accts Dept."},;
         {8,"John (Accts)"    , "Accts Dept."},;
         {9,"Abraham (Accts)" , "Accts Dept."} }        
         
For i:=1 to len(aData)
    APPEND BLANK
    REPLACE EMP_CODE  with aData[i][1]
    REPLACE EMP_NAME  with aData[i][2]
    REPLACE DEPT_NAME with aData[i][3]
Next

// Index the Database on Dept. Name
INDEX ON DEPT_NAME to EMPLOYEES
Select B
USE EMPLOYEES INDEX EMPLOYEES


Select DEPARTMENT
Go Top
Do While !eof()
   aAdd(aDeptNames,DEPARTMENT->DEPT_NAME)
   aAdd(aDeptRecNo,RecNo() )
   Skip
Enddo

// nEmpCode is used as Character type, eventhough in DBF it is Numeric
// This is because DbCombo can handle only Character type array
nEmpCode:=space(3)  
aEmpCodes:={} ; aEmpNames:={} ; cDeptName:=space(11)
IsAllOK:=.F.

Sele DEPARTMENT
Go Top
nDeptRecNo:=2  // 1st record in Department.Dbf should be always be Selected by Default


nStyle :=nOR( DS_MODALFRAME, WS_POPUP, WS_CAPTION ) // Removes the ? and x on the dialogue title

DEFINE DIALOG oDlg FROM 10,20 to 27,90 TITLE "Login " style nStyle

@01  ,3.6 say "Department" of oDlg
@02  ,3.6 say "Employee"   of oDlg

IsConnected:=.F.
IsAppBrSetUpDone:=.F.

@1.2,8 DBCOMBO oDbCmbDepartment VAR nDeptRecNo;
      ITEMS aDeptRecNo;
      size 120,200 ;      // Size Control width, Ht of the list when activated
      LIST aDeptNames;
      of oDlg;
      VALID  if(IsConnected, .T., ;  // If already Connected then Return .T.
                   (IsConnected:=ConnectDB(nDeptRecNo,@nEmpCode,@aEmpCodes,@aEmpNames,oDbCmbEmployees,oDlg), ; // Else connect and Return the result ie T or F
                    IsConnected ) )  ; // Return the status of connection ie either .T. or .F.
      update ;
      ON CHANGE ( IsConnected:=ConnectDB(nDeptRecNo,@nEmpCode,@aEmpCodes,@aEmpNames,oDbCmbEmployees,oDlg),;
                  if(IsConnected,  , ;  // If connected
                      (IsAllOK:=.F. ,oDlg:End() )  ) )  // Not Connected


@2.3,8 DBCOMBO oDbCmbEmployees VAR nEmpCode;
      ITEMS aEmpCodes;
      size 120,200 ;      // Size Control width, Ht of the list when activated
      LIST aEmpNames;
      of oDlg;
      ON CHANGE ( IsAppBrSetUpDone:=SetAppEmployee(nEmpCode) ) ;
      VALID  if (IsAppBrSetUpDone, .T. ,;  // if oApp Branch setup done then return .F.
                               SetAppEmployee(nEmpCode)  ) ; // Else do the setup for oApp Branch details
      update


@05,14 BUTTONBMP oBtnLogin  PROMPT "Login" TEXTRIGHT  SIZE 50,20 ;
         ACTION oDlg:End()

@05,24 BUTTONBMP oBtnCancel PROMPT "Cancel" TEXTRIGHT SIZE 50,20 ;
         ACTION oDlg:End()  CANCEL



oBtnLogin:cToolTip:="Login"
oBtnCancel:cToolTip:="Cancel/Quit"

ACTIVATE DIALOG oDlg CENTERED

SELECT DEPARTMENT
Use
SELECT EMPLOYEES
Use

Return IsAllOK

*-------------------------------------------*
Function ConnectDB(nDeptRecNo,nEmpCode,aEmpCodes,aEmpNames,oDbCmbEmployees,oDlg)
*-------------------------------------------*
Local oError,oRecSet,bDbCmbOnChange,cDeptName

// Reset old values
aEmpCodes:={} ; aEmpNames:={} ; nBranchId:=0

Select DEPARTMENT
Goto nDeptRecNo
// Some validations are done here, like Database connectivity etc
cDeptName:=DEPARTMENT->DEPT_NAME


Sele EMPLOYEES
Go TOP
Seek cDeptName
Do WHILE EMPLOYEES->DEPT_NAME == cDeptName .and. !eof()
    // If I don't use Str(), then I get Alltrim error at SetItems() ie on line 185
    aAdd(aEmpCodes ,str(EMPLOYEES->EMP_CODE,3))
    aAdd(aEmpNames ,EMPLOYEES->EMP_NAME)
    Skip
Enddo

// I need the the 1st item in the DbCombo to be selected by default
if Len(aEmpCodes) > 0
    nEmpCode:=Val(aEmpCodes[1])
Endif
MsgInfo("The Value of nEmpCode is "+str(nEmpCode)) // Shows the correct value
MsgInfo("ValType of nEmpCode is "+ValType(nEmpCode))


// See carefully the below given commands on DbCombo, when we do the SetItems of the DbCombo oDbCmbEmployees
// The On change event of oDbCmbEmployees gets fired before quiting this Function
// So to avoid that I am temporarily changing the OnChange to NIL and later restoring it

bDbCmbOnChange:=oDbCmbEmployees:bChange
oDbCmbEmployees:bChange:=NIL
oDbCmbEmployees:SetItems(aEmpCodes, aEmpNames)
oDbCmbEmployees:bChange:=bDbCmbOnChange
oDbCmbEmployees:Update()

/*
I tried all these, but failed to make DbCombo to select a default value
nEmpCode:=Val(oDbCmbEmployees:aItems[ 1 ])
MsgInfo("List "+oDbCmbEmployees:aItems[ 1 ])
oDbCmbEmployees:nAt:=1
*/

oDlg:cTitle:="Selected Dept :"+cDeptName+" -- Employee Code "+nEmpCode

// I can't understand what is happening here. The value of nEmpCode is Lost at this point
// I have even tested after removing the SetItem commands ie from line 178 to line 182
// really cant understand why this behavior
MsgInfo("Before Quiting ConnectDb() the Value of nEmpCode is lost, the val is :"+nEmpCode)
RETURN .T.

*-----------------------------------------------*
Function SetAppEmployee(nEmpCode)
*-----------------------------------------------*
Return .T.




Regards
Anser
Last edited by anserkk on Fri Aug 07, 2009 10:57 am, edited 1 time in total.
User avatar
anserkk
 
Posts: 1332
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: DbCombo Problem

Postby anserkk » Fri Aug 07, 2009 10:57 am

Hi all,

Solved the problem.

The problem occurred because I was trying to Assign a Default value to DBCombo before the SetItems()

But I still wonder why I have to convert the aItems to Character type before calling a DbCombo SetItems()

Regards
Anser
User avatar
anserkk
 
Posts: 1332
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: DbCombo Problem (Solved)

Postby James Bott » Fri Aug 07, 2009 11:23 pm

Anser,

>But I still wonder why I have to convert the aItems to Character type before calling a DbCombo SetItems()

Because DBCombo inherits from Combobox and Combobox only handles character types. I tried once to modify DBCombo to handle numerics, but it became too complex.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: DbCombo Problem (Solved)

Postby anserkk » Sat Aug 08, 2009 5:30 am

Dear Mr.James,

But I still wonder why I have to convert the aItems to Character type before calling a DbCombo SetItems()


Now it seems working without converting to Character type. I am herewith providing the modified sample below.

Code: Select all  Expand view
#Include "FiveWin.Ch"
#Include "DbCombo.Ch"

*------------------------------------------*
Function Main()
*------------------------------------------*
Local oDlg,oDbCmbEmployees,oDbCmbDepartment,oBtnLogin,oBtnCancel
Local nStyle,nDeptRecNo,nEmpCode,i
Local aEmpCodes:={}, aEmpNames:={} , aDeptNames:={} , aDeptRecNo:={}, aData
Local lListGenerated
Local aStructure

SET EXCLUSIVE ON

if !File("DEPARTMENT.DBF")
    aStructure := {}
    aAdd(aStructure,{"DEPT_NAME","C",11,0})
    DbCreate("DEPARTMENT.DBF",aStructure)
endif

Select A
USE DEPARTMENT
ZAP

aData:={"Sales Dept.",;
        "IT Dept.   ",;
        "Accts Dept." }
       
For i:=1 to len(aData)        
    APPEND BLANK
    REPLACE DEPT_NAME with aData[i]
Next

if !File("EMPLOYEES.DBF")
    aStructure := {}
    aAdd(aStructure,{"EMP_CODE" ,"N", 3,0})
    aAdd(aStructure,{"EMP_NAME" ,"C",30,0})
    aAdd(aStructure,{"DEPT_NAME","C",11,0})
   
    DbCreate("EMPLOYEES.DBF",aStructure)
ENDIF

Select B
USE EMPLOYEES
ZAP

aData:={}
aData:={ {1,"Anser (Sales)"   , "Sales Dept."},;
         {2,"John (Sales)"    , "Sales Dept."},;
         {3,"Abraham (Sales)" , "Sales Dept."},;        
         {4,"Anser (IT)"      , "IT Dept.   "},;
         {5,"John (IT)"       , "IT Dept.   "},;
         {6,"Abraham (IT)"    , "IT Dept.   "},;        
         {7,"Anser (Accts)"   , "Accts Dept."},;
         {8,"John (Accts)"    , "Accts Dept."},;
         {9,"Abraham (Accts)" , "Accts Dept."} }        
         
For i:=1 to len(aData)
    APPEND BLANK
    REPLACE EMP_CODE  with aData[i][1]
    REPLACE EMP_NAME  with aData[i][2]
    REPLACE DEPT_NAME with aData[i][3]
Next

// Index the Database on Dept. Name
INDEX ON EMPLOYEES->DEPT_NAME to EMPLOYEES
Select B
USE EMPLOYEES INDEX EMPLOYEES


Select DEPARTMENT
Go Top
Do While !eof()
   aAdd(aDeptNames,DEPARTMENT->DEPT_NAME)
   aAdd(aDeptRecNo,RecNo() )
   Skip
Enddo
Sele DEPARTMENT
Go Top

nEmpCode:=0 // Numeric Type
aEmpCodes:={} ; aEmpNames:={}   // Array to hold Employ codes and Employ Name
nDeptRecNo:=1  // 1st record in Department.Dbf should be always be Selected by Default

nStyle :=nOR( DS_MODALFRAME, WS_POPUP, WS_CAPTION ) // Removes the ? and x on the dialogue title

DEFINE DIALOG oDlg FROM 10,20 to 27,90 TITLE "Login " style nStyle

@01  ,3.6 say "Department" of oDlg
@02  ,3.6 say "Employee"   of oDlg

lListGenerated:=.F.

@1.2,8 DBCOMBO oDbCmbDepartment VAR nDeptRecNo;
      ITEMS aDeptRecNo;
      size 120,200 ;    
      LIST aDeptNames;
      of oDlg;
      VALID  if(lListGenerated, .T., ;  // If DbCombo2 List is already  then Return .T.
                   ( lListGenerated:=GenEmployList(nDeptRecNo,@nEmpCode,@aEmpCodes,@aEmpNames,oDbCmbEmployees), ;
                     lListGenerated ) )  ; // Return the status ie either .T. or .F.
      ON CHANGE ( lListGenerated:=GenEmployList(nDeptRecNo,@nEmpCode,@aEmpCodes,@aEmpNames,oDbCmbEmployees) ) ;
      update

@2.3,8 DBCOMBO oDbCmbEmployees VAR nEmpCode;
      ITEMS aEmpCodes;
      size 120,200 ;    
      LIST aEmpNames;
      of oDlg;
      update

@05,14 BUTTONBMP oBtnLogin  PROMPT "Login" TEXTRIGHT  SIZE 50,20 ;
         ACTION oDlg:End()

@05,24 BUTTONBMP oBtnCancel PROMPT "Cancel" TEXTRIGHT SIZE 50,20 ;
         ACTION oDlg:End()  CANCEL

ACTIVATE DIALOG oDlg CENTERED

SELECT DEPARTMENT
Use
SELECT EMPLOYEES
Use

Return .T.

*-------------------------------------------*
Function GenEmployList(nDeptRecNo,nEmpCode,aEmpCodes,aEmpNames,oDbCmbEmployees)
*-------------------------------------------*
Local oError,oRecSet,bDbCmbOnChange,cDeptName

// Reset old values
aEmpCodes:={} ; aEmpNames:={}

Select DEPARTMENT
Goto nDeptRecNo
// Some validations are done here, like Database connectivity etc
cDeptName:=DEPARTMENT->DEPT_NAME

Sele EMPLOYEES
Go TOP
Seek cDeptName
Do WHILE EMPLOYEES->DEPT_NAME == cDeptName .and. !eof()
    aAdd(aEmpCodes ,EMPLOYEES->EMP_CODE)  // Works without using Str()
    aAdd(aEmpNames ,EMPLOYEES->EMP_NAME)
    Skip
Enddo

bDbCmbOnChange:=oDbCmbEmployees:bChange
oDbCmbEmployees:bChange:=NIL
oDbCmbEmployees:SetItems(aEmpCodes, aEmpNames)
oDbCmbEmployees:bChange:=bDbCmbOnChange

// I need the the 1st item in the DbCombo to be selected by default
if Len(aEmpCodes) > 0
    nEmpCode:=aEmpCodes[1]
Endif
MsgInfo("Quiting GenEmployList(), the Value of nEmpCode is :"+str(nEmpCode)+CRLF+;
        "ValType of nEmpCode is "+ValType(nEmpCode))
RETURN .T.




Regards

Anser
User avatar
anserkk
 
Posts: 1332
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 92 guests