Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby FranciscoA » Thu Apr 09, 2020 12:40 am

Antonio, aqui tienes un ejemplo autocontenido. Pruébalo a ver si te es de utilidad.

Code: Select all  Expand view  RUN
#include "Fivewin.ch"
#include "xBrowse.ch"

//------------------------------------------------//
Function Main()   //Fap_2Arrays()
local oDlg, oCbx1,cVar1,cItems1:={}, oCbx2,cVar2,cItems2:={" "}
local aArr2

cItems1 := CreaArray1()
aArr2   := CreaArray2()

cVar1 := cItems1[1]
cVar2 := cItems2[1]

  DEFINE DIALOG oDlg FROM 1,1 TO 300, 600 PIXEL  TITLE "Prueba 2 ComboBox con Arrays"

 @ 20, 10 COMBOBOX oCbx1 Var cVar1 ITEMS cItems1 SIZE 130,200 PIXEL OF oDlg ;
          ON CHANGE ( cVar1 := cItems1[oCbx1:nAt], CargaItems2(cVar1, @cVar2, @cItems2, oCbx2, aArr2) )

 @ 20,160 COMBOBOX oCbx2 Var cVar2 ITEMS cItems2 SIZE 130,200 PIXEL OF oDlg

  @100,20 BUTTON "Salir" SIZE 100, 20 PIXEL OF oDlg ;
         ACTION ( Msginfo("Bye..."), oDlg:End() )

  CargaItems2(cVar1, @cVar2, @cItems2, oCbx2, aArr2)

  ACTIVATE DIALOG oDlg CENTERED

Return nil

//------------------------------------------------//
Function CargaItems2(cVar1, cVar2, cItems2, oCbx2, aArr2)
local n, nLen := 4  //longitud del codigo

cItems2 := {}

For n := 1 to len(aArr2)
   if Substr(aArr2[n],1,nLen) == Substr(cVar1,1,nLen)
      aadd( cItems2, aArr2[n] )
   endif
Next

/*
O asi:
 AEval( aArr2, {|a| if(Substr(a,1,nLen) == Substr(cVar1,1,nLen), aadd(cItems2, a),) } )
*/


oCbx2:SetItems(cItems2)
cVar2 := cItems2[1]
oCbx2:Refresh()
oCbx2:Open()

Return nil

//----------------------------------//
Function CreaArray1()
local aArray := {}

   aadd(aArray, "COD1 Cajas")
   aadd(aArray, "COD2 Bancos")
   aadd(aArray, "COD3 Cuentas por cobrar")
   aadd(aArray, "COD4 Inventarios")

Return aArray

//----------------------------------//
Function CreaArray2()
local aArray := {}

   aadd(aArray, "COD1 0001 Caja General")
   aadd(aArray, "COD1 0002 Caja Chica")
   aadd(aArray, "COD1 0003 Efectivo para cambio")

   aadd(aArray, "COD2 0001 Banco Produccion")
   aadd(aArray, "COD2 0002 Banco Mercantil")
   aadd(aArray, "COD2 0003 Banco Nacional")
   aadd(aArray, "COD2 0004 Banco Del Campo")
   aadd(aArray, "COD2 0005 Banco Central")

   aadd(aArray, "COD3 0001 Cliente 0001")
   aadd(aArray, "COD3 0002 Cliente 0002")
   aadd(aArray, "COD3 0003 Cliente 0003")
   aadd(aArray, "COD3 0004 Cliente 0004")
   aadd(aArray, "COD3 0005 Cliente 0005")

   aadd(aArray, "COD4 0001 Gasolina")
   aadd(aArray, "COD4 0002 Diesel")
   aadd(aArray, "COD4 0003 Grasas")
   aadd(aArray, "COD4 0004 Aceites")
   aadd(aArray, "COD4 0005 Otros")

Return aArray
 

Saludos.
Last edited by FranciscoA on Thu Apr 09, 2020 2:37 pm, edited 1 time in total.
Francisco J. Alegría P.
Chinandega, Nicaragua.

Fwxh-MySql-TMySql
User avatar
FranciscoA
 
Posts: 2159
Joined: Fri Jul 18, 2008 1:24 am
Location: Chinandega, Nicaragua, C.A.

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby JESUS MARIN » Thu Apr 09, 2020 5:53 am

Buenos días
Aquí tienes un ejemplo montado, con dos opciones de trabajo.
1) Un objeto GET Memo, que te muestra dinámicamente las dos opciones seleccionadas. Yo te he puesto un objeto GET, pon tu lo que necesites.
2) Un objeto BUTTON para ejecutar otras opciones.

Como se han definido 4 constantes C1_CODE, C1_DATA, C2_CODE Y C2_DATA, puedes utilizarlas en otras funciones a ejecutar por el usuario.

Te he puesto bastantes anotaciones y aclaraciones para que veas que se esta realizando en cada línea y también una nota aclaratoria.

Espero te ayude.

Code: Select all  Expand view  RUN

# Include "Fivewin.ch"

# Define C1_CODE aItems1[oCombo1:nAt,1]
# Define C1_DATA aItems1[oCombo1:nAt,2]
# Define C2_CODE aItems2[oCombo2:nAt,1]
# Define C2_DATA aItems2[oCombo2:nAt,2]

STATIC aItems1 := {}
STATIC aItems2 := {}
STATIC oCombo1
STATIC oCombo2


FUNCTION Main()


LOCAL aItemsCombo1:={}, aItemsCombo2:={}
LOCAL cVar1, cVar2
LOCAL oDlg
LOCAL oGet, cText:=""


// Obtenemos los datos de una BASE DE DATOS O LOS MONTAMOS (en este caso lo montamos)

aItems1:={ {"EX","Examen 1"},{"RX","Examen 2"},{"HX","Examen 3"} }

// Creamos el array a mostrar en el combo1. Lo hacemos como indica C.Navarro, en vez de un FOR NEXT como suelo hacer yo

AEVal( aItems1, { | a | AAdd( aItemsCombo1, a[ 2 ] ) }  )

// Obtenemos los datos del array para el segundo combo con la funcion Carga_dos()
// Lo pongo en una funcion separada por si fuera necesario cargarlo en una BASE DE DATOS
// Como estamos inicializando los datos le pediremos que cargue el primer codigo de aItems1

aItems2      := Carga_dos( aItems1[1,1], 2 )    // EL SEGUNDO PARAMETRO "2" CARGA LOS DOS VALORES
aItemsCombo2 := Carga_dos( aItems1[1,1], 1 )    // EL SEGUNDO PARAEMTRO "1" CARGA SOLO UN VALOR (EL SEGUNDO)



DEFINE DIALOG oDlg FROM 1,1 TO 200,500 PIXEL

 @ 012,12 ComboBox oCombo1 Var cVar1 Items aItemsCombo1 SIZE 100,200 PIXEL OF oDlg

 @ 042,12 ComboBox oCombo2 Var cVar2 Items aItemsCombo2 SIZE 100,200 PIXEL OF oDlg

 oCombo1:bChange := { || aItems2:=Carga_dos( C1_CODE, 2 )      ,;
                         aItemsCombo2:=Carga_dos( C1_CODE, 1 ) ,;
                         oCombo2:SetItems(aItemsCombo2)        ,;         // AQUI SE EVALUA oCombo2:bChange
                         cVar2:=aItemsCombo2[1]                ,;
                         oCombo2:Refresh()  }


 oCombo2:bChange := { || ( cText:="Mi selección es : "+CRLF+CRLF+;
                           C1_CODE+CRLF+;
                           C1_DATA+CRLF+;
                           IF(oCombo2:nAt=0,aItems2[1,1],C2_CODE)+CRLF+;      // ver nota
                           IF(oCombo2:nAt=0,aItemsCombo2[1],C2_DATA) ,;
                           oGet:SetText(cText) ) }

              /// NOTA ////////////////////////////////////////////////////////
              // Cuando se realiza el oCombo2:SetItems(aItemsCombo2), se evalua oCombo2:bChange automaticamente
              // Como no se ha refrescado el oCombo2, el valor de oCombo2:nAt es 0 (cero)
              //  (en el método ::Reset() , de la clase TCOMBOBOX, se asigna el valor cero)
              // por lo tanto hay que instrumentar que tome el primer valor de aItems2 y aItemsCombo2.
              //
              // Si no es cero, porque el usuario ha modificado el oCombo2, seleccionando otro valor,
              // se muestra C2_CODE Y C2_DATA
              /////////////////////////////////////////////////////////////////



 // Cargo el texto con los primeros valores
 cText:="Mi selección es : "+CRLF+CRLF+aItems1[1,1]+CRLF+aItems1[1,2]+CRLF+aItems2[1,1]+CRLF+aItems2[1,2]
 @ 012,125 GET oGet VAR cText OF oDlg PIXEL SIZE 120, 60 MEMO

 @ 078,125 BUTTON "Funciones externas" SIZE 120,18 OF oDlg PIXEL ACTION Otra_funcion()

 @ 078,12 BUTTON "Salir" SIZE 35,18 OF oDlg PIXEL ACTION oDlg:End()



ACTIVATE DIALOG oDlg CENTER

RETURN(NIL)



STATIC FUNCTION Carga_dos( cCode, nModo )  // nModo=1 solo carga un elemento(el segundo)
                                           // nModo=2 carga los dos datos

LOCAL aReturn := {}

IF nModo=1

   IF cCode == "EX"
      AADD(aReturn,"DETALLE AA-1")
      AADD(aReturn,"DETALLE AA-2")
      AADD(aReturn,"DETALLE AA-3")
   ENDIF

   IF cCode == "RX"
      AADD(aReturn,"DETALLE BB-1")
      AADD(aReturn,"DETALLE BB-2")
      AADD(aReturn,"DETALLE BB-3")
   ENDIF

   IF cCode == "HX"
      AADD(aReturn,"DETALLE CC-1")
      AADD(aReturn,"DETALLE CC-2")
      AADD(aReturn,"DETALLE CC-3")
   ENDIF

ENDIF


IF nModo=2

   IF cCode == "EX"
      AADD(aReturn,{"A-1","DETALLE AA-1"})
      AADD(aReturn,{"A-2","DETALLE AA-2"})
      AADD(aReturn,{"A-3","DETALLE AA-3"})
   ENDIF

   IF cCode == "RX"
      AADD(aReturn,{"B-1","DETALLE BB-1"})
      AADD(aReturn,{"B-2","DETALLE BB-2"})
      AADD(aReturn,{"B-3","DETALLE BB-3"})
   ENDIF

   IF cCode == "HX"
      AADD(aReturn,{"C-1","DETALLE CC-1"})
      AADD(aReturn,{"C-2","DETALLE CC-2"})
      AADD(aReturn,{"C-3","DETALLE CC-3"})
   ENDIF

ENDIF



RETURN( aReturn )


STATIC FUNCTION Otra_funcion( )

   MSGALERT( C1_CODE )
   MSGALERT( C1_DATA )
   MSGALERT( C2_CODE )
   MSGALERT( C2_DATA )

RETURN(NIL)

 
Jesús Marín
JESUS MARIN
 
Posts: 176
Joined: Wed Jan 02, 2019 8:36 am

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby remtec » Thu Apr 09, 2020 3:00 pm

FranciscoA wrote:Antonio, aqui tienes un ejemplo autocontenido. Pruébalo a ver si te es de utilidad.

Code: Select all  Expand view  RUN
#include "Fivewin.ch"
#include "xBrowse.ch"

//------------------------------------------------//
Function Main()   //Fap_2Arrays()
local oDlg, oCbx1,cVar1,cItems1:={}, oCbx2,cVar2,cItems2:={" "}
local aArr2

cItems1 := CreaArray1()
aArr2   := CreaArray2()

cVar1 := cItems1[1]
cVar2 := cItems2[1]

  DEFINE DIALOG oDlg FROM 1,1 TO 300, 600 PIXEL  TITLE "Prueba 2 ComboBox con Arrays"

 @ 20, 10 COMBOBOX oCbx1 Var cVar1 ITEMS cItems1 SIZE 130,200 PIXEL OF oDlg ;
          ON CHANGE ( cVar1 := cItems1[oCbx1:nAt], CargaItems2(cVar1, @cVar2, @cItems2, oCbx2, aArr2) )

 @ 20,160 COMBOBOX oCbx2 Var cVar2 ITEMS cItems2 SIZE 130,200 PIXEL OF oDlg

  @100,20 BUTTON "Salir" SIZE 100, 20 PIXEL OF oDlg ;
         ACTION ( Msginfo("Bye..."), oDlg:End() )

  CargaItems2(cVar1, @cVar2, @cItems2, oCbx2, aArr2)

  ACTIVATE DIALOG oDlg CENTERED

Return nil

//------------------------------------------------//
Function CargaItems2(cVar1, cVar2, cItems2, oCbx2, aArr2)
local n, nLen := 4  //longitud del codigo

cItems2 := {}

For n := 1 to len(aArr2)
   if Substr(aArr2[n],1,nLen) == Substr(cVar1,1,nLen)
      aadd( cItems2, aArr2[n] )
   endif
Next

/*
O asi:
 AEval( aArr2, {|a| if(Substr(a,1,nLen) == Substr(cVar1,1,nLen), aadd(cItems2, a),) } )
*/


oCbx2:SetItems(cItems2)
cVar2 := cItems2[1]
oCbx2:Refresh()
oCbx2:Open()

Return nil

//----------------------------------//
Function CreaArray1()
local aArray := {}

   aadd(aArray, "COD1 Cajas")
   aadd(aArray, "COD2 Bancos")
   aadd(aArray, "COD3 Cuentas por cobrar")
   aadd(aArray, "COD4 Inventarios")

Return aArray

//----------------------------------//
Function CreaArray2()
local aArray := {}

   aadd(aArray, "COD1 0001 Caja General")
   aadd(aArray, "COD1 0002 Caja Chica")
   aadd(aArray, "COD1 0003 Efectivo para cambio")

   aadd(aArray, "COD2 0001 Banco Produccion")
   aadd(aArray, "COD2 0002 Banco Mercantil")
   aadd(aArray, "COD2 0003 Banco Nacional")
   aadd(aArray, "COD2 0004 Banco Del Campo")
   aadd(aArray, "COD2 0005 Banco Central")

   aadd(aArray, "COD3 0001 Cliente 0001")
   aadd(aArray, "COD3 0002 Cliente 0002")
   aadd(aArray, "COD3 0003 Cliente 0003")
   aadd(aArray, "COD3 0004 Cliente 0004")
   aadd(aArray, "COD3 0005 Cliente 0005")

   aadd(aArray, "COD4 0001 Gasolina")
   aadd(aArray, "COD4 0002 Diesel")
   aadd(aArray, "COD4 0003 Grasas")
   aadd(aArray, "COD4 0004 Aceites")
   aadd(aArray, "COD4 0005 Otros")

Return aArray
 

Saludos.


Hola Francisco,

Amigo como te encuentras, tanto tiempo, deseo que muy bien.

Muchas gracias, siempre atento a responder.

Probare ambas opciones y comento durante la tarde.

Muchos saludos
Antonio
FWH 22.10 - HARBOUR - PELLES C
remtec
 
Posts: 719
Joined: Fri May 12, 2017 2:50 pm

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby remtec » Thu Apr 09, 2020 3:03 pm

JESUS MARIN wrote:Buenos días
Aquí tienes un ejemplo montado, con dos opciones de trabajo.
1) Un objeto GET Memo, que te muestra dinámicamente las dos opciones seleccionadas. Yo te he puesto un objeto GET, pon tu lo que necesites.
2) Un objeto BUTTON para ejecutar otras opciones.

Como se han definido 4 constantes C1_CODE, C1_DATA, C2_CODE Y C2_DATA, puedes utilizarlas en otras funciones a ejecutar por el usuario.

Te he puesto bastantes anotaciones y aclaraciones para que veas que se esta realizando en cada línea y también una nota aclaratoria.

Espero te ayude.

Code: Select all  Expand view  RUN

# Include "Fivewin.ch"

# Define C1_CODE aItems1[oCombo1:nAt,1]
# Define C1_DATA aItems1[oCombo1:nAt,2]
# Define C2_CODE aItems2[oCombo2:nAt,1]
# Define C2_DATA aItems2[oCombo2:nAt,2]

STATIC aItems1 := {}
STATIC aItems2 := {}
STATIC oCombo1
STATIC oCombo2


FUNCTION Main()


LOCAL aItemsCombo1:={}, aItemsCombo2:={}
LOCAL cVar1, cVar2
LOCAL oDlg
LOCAL oGet, cText:=""


// Obtenemos los datos de una BASE DE DATOS O LOS MONTAMOS (en este caso lo montamos)

aItems1:={ {"EX","Examen 1"},{"RX","Examen 2"},{"HX","Examen 3"} }

// Creamos el array a mostrar en el combo1. Lo hacemos como indica C.Navarro, en vez de un FOR NEXT como suelo hacer yo

AEVal( aItems1, { | a | AAdd( aItemsCombo1, a[ 2 ] ) }  )

// Obtenemos los datos del array para el segundo combo con la funcion Carga_dos()
// Lo pongo en una funcion separada por si fuera necesario cargarlo en una BASE DE DATOS
// Como estamos inicializando los datos le pediremos que cargue el primer codigo de aItems1

aItems2      := Carga_dos( aItems1[1,1], 2 )    // EL SEGUNDO PARAMETRO "2" CARGA LOS DOS VALORES
aItemsCombo2 := Carga_dos( aItems1[1,1], 1 )    // EL SEGUNDO PARAEMTRO "1" CARGA SOLO UN VALOR (EL SEGUNDO)



DEFINE DIALOG oDlg FROM 1,1 TO 200,500 PIXEL

 @ 012,12 ComboBox oCombo1 Var cVar1 Items aItemsCombo1 SIZE 100,200 PIXEL OF oDlg

 @ 042,12 ComboBox oCombo2 Var cVar2 Items aItemsCombo2 SIZE 100,200 PIXEL OF oDlg

 oCombo1:bChange := { || aItems2:=Carga_dos( C1_CODE, 2 )      ,;
                         aItemsCombo2:=Carga_dos( C1_CODE, 1 ) ,;
                         oCombo2:SetItems(aItemsCombo2)        ,;         // AQUI SE EVALUA oCombo2:bChange
                         cVar2:=aItemsCombo2[1]                ,;
                         oCombo2:Refresh()  }


 oCombo2:bChange := { || ( cText:="Mi selección es : "+CRLF+CRLF+;
                           C1_CODE+CRLF+;
                           C1_DATA+CRLF+;
                           IF(oCombo2:nAt=0,aItems2[1,1],C2_CODE)+CRLF+;      // ver nota
                           IF(oCombo2:nAt=0,aItemsCombo2[1],C2_DATA) ,;
                           oGet:SetText(cText) ) }

              /// NOTA ////////////////////////////////////////////////////////
              // Cuando se realiza el oCombo2:SetItems(aItemsCombo2), se evalua oCombo2:bChange automaticamente
              // Como no se ha refrescado el oCombo2, el valor de oCombo2:nAt es 0 (cero)
              //  (en el método ::Reset() , de la clase TCOMBOBOX, se asigna el valor cero)
              // por lo tanto hay que instrumentar que tome el primer valor de aItems2 y aItemsCombo2.
              //
              // Si no es cero, porque el usuario ha modificado el oCombo2, seleccionando otro valor,
              // se muestra C2_CODE Y C2_DATA
              /////////////////////////////////////////////////////////////////



 // Cargo el texto con los primeros valores
 cText:="Mi selección es : "+CRLF+CRLF+aItems1[1,1]+CRLF+aItems1[1,2]+CRLF+aItems2[1,1]+CRLF+aItems2[1,2]
 @ 012,125 GET oGet VAR cText OF oDlg PIXEL SIZE 120, 60 MEMO

 @ 078,125 BUTTON "Funciones externas" SIZE 120,18 OF oDlg PIXEL ACTION Otra_funcion()

 @ 078,12 BUTTON "Salir" SIZE 35,18 OF oDlg PIXEL ACTION oDlg:End()



ACTIVATE DIALOG oDlg CENTER

RETURN(NIL)



STATIC FUNCTION Carga_dos( cCode, nModo )  // nModo=1 solo carga un elemento(el segundo)
                                           // nModo=2 carga los dos datos

LOCAL aReturn := {}

IF nModo=1

   IF cCode == "EX"
      AADD(aReturn,"DETALLE AA-1")
      AADD(aReturn,"DETALLE AA-2")
      AADD(aReturn,"DETALLE AA-3")
   ENDIF

   IF cCode == "RX"
      AADD(aReturn,"DETALLE BB-1")
      AADD(aReturn,"DETALLE BB-2")
      AADD(aReturn,"DETALLE BB-3")
   ENDIF

   IF cCode == "HX"
      AADD(aReturn,"DETALLE CC-1")
      AADD(aReturn,"DETALLE CC-2")
      AADD(aReturn,"DETALLE CC-3")
   ENDIF

ENDIF


IF nModo=2

   IF cCode == "EX"
      AADD(aReturn,{"A-1","DETALLE AA-1"})
      AADD(aReturn,{"A-2","DETALLE AA-2"})
      AADD(aReturn,{"A-3","DETALLE AA-3"})
   ENDIF

   IF cCode == "RX"
      AADD(aReturn,{"B-1","DETALLE BB-1"})
      AADD(aReturn,{"B-2","DETALLE BB-2"})
      AADD(aReturn,{"B-3","DETALLE BB-3"})
   ENDIF

   IF cCode == "HX"
      AADD(aReturn,{"C-1","DETALLE CC-1"})
      AADD(aReturn,{"C-2","DETALLE CC-2"})
      AADD(aReturn,{"C-3","DETALLE CC-3"})
   ENDIF

ENDIF



RETURN( aReturn )


STATIC FUNCTION Otra_funcion( )

   MSGALERT( C1_CODE )
   MSGALERT( C1_DATA )
   MSGALERT( C2_CODE )
   MSGALERT( C2_DATA )

RETURN(NIL)

 


Hola Jesus.

Como estas, deseo que muy bien.

Eternamente agradecido por tu preocupacion, tiempo y trabajo dedicado para ayudarme.

Revisare y probare tu codigo, comentare durante la tarde.

Muy agradecido.

Saludos,

Antonio.
FWH 22.10 - HARBOUR - PELLES C
remtec
 
Posts: 719
Joined: Fri May 12, 2017 2:50 pm

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby remtec » Thu Apr 09, 2020 9:48 pm

FranciscoA wrote:Antonio, aqui tienes un ejemplo autocontenido. Pruébalo a ver si te es de utilidad.

Code: Select all  Expand view  RUN
#include "Fivewin.ch"
#include "xBrowse.ch"

//------------------------------------------------//
Function Main()   //Fap_2Arrays()
local oDlg, oCbx1,cVar1,cItems1:={}, oCbx2,cVar2,cItems2:={" "}
local aArr2

cItems1 := CreaArray1()
aArr2   := CreaArray2()

cVar1 := cItems1[1]
cVar2 := cItems2[1]

  DEFINE DIALOG oDlg FROM 1,1 TO 300, 600 PIXEL  TITLE "Prueba 2 ComboBox con Arrays"

 @ 20, 10 COMBOBOX oCbx1 Var cVar1 ITEMS cItems1 SIZE 130,200 PIXEL OF oDlg ;
          ON CHANGE ( cVar1 := cItems1[oCbx1:nAt], CargaItems2(cVar1, @cVar2, @cItems2, oCbx2, aArr2) )

 @ 20,160 COMBOBOX oCbx2 Var cVar2 ITEMS cItems2 SIZE 130,200 PIXEL OF oDlg

  @100,20 BUTTON "Salir" SIZE 100, 20 PIXEL OF oDlg ;
         ACTION ( Msginfo("Bye..."), oDlg:End() )

  CargaItems2(cVar1, @cVar2, @cItems2, oCbx2, aArr2)

  ACTIVATE DIALOG oDlg CENTERED

Return nil

//------------------------------------------------//
Function CargaItems2(cVar1, cVar2, cItems2, oCbx2, aArr2)
local n, nLen := 4  //longitud del codigo

cItems2 := {}

For n := 1 to len(aArr2)
   if Substr(aArr2[n],1,nLen) == Substr(cVar1,1,nLen)
      aadd( cItems2, aArr2[n] )
   endif
Next

/*
O asi:
 AEval( aArr2, {|a| if(Substr(a,1,nLen) == Substr(cVar1,1,nLen), aadd(cItems2, a),) } )
*/


oCbx2:SetItems(cItems2)
cVar2 := cItems2[1]
oCbx2:Refresh()
oCbx2:Open()

Return nil

//----------------------------------//
Function CreaArray1()
local aArray := {}

   aadd(aArray, "COD1 Cajas")
   aadd(aArray, "COD2 Bancos")
   aadd(aArray, "COD3 Cuentas por cobrar")
   aadd(aArray, "COD4 Inventarios")

Return aArray

//----------------------------------//
Function CreaArray2()
local aArray := {}

   aadd(aArray, "COD1 0001 Caja General")
   aadd(aArray, "COD1 0002 Caja Chica")
   aadd(aArray, "COD1 0003 Efectivo para cambio")

   aadd(aArray, "COD2 0001 Banco Produccion")
   aadd(aArray, "COD2 0002 Banco Mercantil")
   aadd(aArray, "COD2 0003 Banco Nacional")
   aadd(aArray, "COD2 0004 Banco Del Campo")
   aadd(aArray, "COD2 0005 Banco Central")

   aadd(aArray, "COD3 0001 Cliente 0001")
   aadd(aArray, "COD3 0002 Cliente 0002")
   aadd(aArray, "COD3 0003 Cliente 0003")
   aadd(aArray, "COD3 0004 Cliente 0004")
   aadd(aArray, "COD3 0005 Cliente 0005")

   aadd(aArray, "COD4 0001 Gasolina")
   aadd(aArray, "COD4 0002 Diesel")
   aadd(aArray, "COD4 0003 Grasas")
   aadd(aArray, "COD4 0004 Aceites")
   aadd(aArray, "COD4 0005 Otros")

Return aArray
 

Saludos.


Hola Francisco

Revise tu codigo, veo que trabaja como Array Unidimensional, en mi caso lo necesito ambos Array multidimensional.

Muy agradecido.

Muchos saludos,

Antonio
FWH 22.10 - HARBOUR - PELLES C
remtec
 
Posts: 719
Joined: Fri May 12, 2017 2:50 pm

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby remtec » Thu Apr 09, 2020 9:59 pm

JESUS MARIN wrote:Buenos días
Aquí tienes un ejemplo montado, con dos opciones de trabajo.
1) Un objeto GET Memo, que te muestra dinámicamente las dos opciones seleccionadas. Yo te he puesto un objeto GET, pon tu lo que necesites.
2) Un objeto BUTTON para ejecutar otras opciones.

Como se han definido 4 constantes C1_CODE, C1_DATA, C2_CODE Y C2_DATA, puedes utilizarlas en otras funciones a ejecutar por el usuario.

Te he puesto bastantes anotaciones y aclaraciones para que veas que se esta realizando en cada línea y también una nota aclaratoria.

Espero te ayude.

Code: Select all  Expand view  RUN

# Include "Fivewin.ch"

# Define C1_CODE aItems1[oCombo1:nAt,1]
# Define C1_DATA aItems1[oCombo1:nAt,2]
# Define C2_CODE aItems2[oCombo2:nAt,1]
# Define C2_DATA aItems2[oCombo2:nAt,2]

STATIC aItems1 := {}
STATIC aItems2 := {}
STATIC oCombo1
STATIC oCombo2


FUNCTION Main()


LOCAL aItemsCombo1:={}, aItemsCombo2:={}
LOCAL cVar1, cVar2
LOCAL oDlg
LOCAL oGet, cText:=""


// Obtenemos los datos de una BASE DE DATOS O LOS MONTAMOS (en este caso lo montamos)

aItems1:={ {"EX","Examen 1"},{"RX","Examen 2"},{"HX","Examen 3"} }

// Creamos el array a mostrar en el combo1. Lo hacemos como indica C.Navarro, en vez de un FOR NEXT como suelo hacer yo

AEVal( aItems1, { | a | AAdd( aItemsCombo1, a[ 2 ] ) }  )

// Obtenemos los datos del array para el segundo combo con la funcion Carga_dos()
// Lo pongo en una funcion separada por si fuera necesario cargarlo en una BASE DE DATOS
// Como estamos inicializando los datos le pediremos que cargue el primer codigo de aItems1

aItems2      := Carga_dos( aItems1[1,1], 2 )    // EL SEGUNDO PARAMETRO "2" CARGA LOS DOS VALORES
aItemsCombo2 := Carga_dos( aItems1[1,1], 1 )    // EL SEGUNDO PARAEMTRO "1" CARGA SOLO UN VALOR (EL SEGUNDO)



DEFINE DIALOG oDlg FROM 1,1 TO 200,500 PIXEL

 @ 012,12 ComboBox oCombo1 Var cVar1 Items aItemsCombo1 SIZE 100,200 PIXEL OF oDlg

 @ 042,12 ComboBox oCombo2 Var cVar2 Items aItemsCombo2 SIZE 100,200 PIXEL OF oDlg

 oCombo1:bChange := { || aItems2:=Carga_dos( C1_CODE, 2 )      ,;
                         aItemsCombo2:=Carga_dos( C1_CODE, 1 ) ,;
                         oCombo2:SetItems(aItemsCombo2)        ,;         // AQUI SE EVALUA oCombo2:bChange
                         cVar2:=aItemsCombo2[1]                ,;
                         oCombo2:Refresh()  }


 oCombo2:bChange := { || ( cText:="Mi selección es : "+CRLF+CRLF+;
                           C1_CODE+CRLF+;
                           C1_DATA+CRLF+;
                           IF(oCombo2:nAt=0,aItems2[1,1],C2_CODE)+CRLF+;      // ver nota
                           IF(oCombo2:nAt=0,aItemsCombo2[1],C2_DATA) ,;
                           oGet:SetText(cText) ) }

              /// NOTA ////////////////////////////////////////////////////////
              // Cuando se realiza el oCombo2:SetItems(aItemsCombo2), se evalua oCombo2:bChange automaticamente
              // Como no se ha refrescado el oCombo2, el valor de oCombo2:nAt es 0 (cero)
              //  (en el método ::Reset() , de la clase TCOMBOBOX, se asigna el valor cero)
              // por lo tanto hay que instrumentar que tome el primer valor de aItems2 y aItemsCombo2.
              //
              // Si no es cero, porque el usuario ha modificado el oCombo2, seleccionando otro valor,
              // se muestra C2_CODE Y C2_DATA
              /////////////////////////////////////////////////////////////////



 // Cargo el texto con los primeros valores
 cText:="Mi selección es : "+CRLF+CRLF+aItems1[1,1]+CRLF+aItems1[1,2]+CRLF+aItems2[1,1]+CRLF+aItems2[1,2]
 @ 012,125 GET oGet VAR cText OF oDlg PIXEL SIZE 120, 60 MEMO

 @ 078,125 BUTTON "Funciones externas" SIZE 120,18 OF oDlg PIXEL ACTION Otra_funcion()

 @ 078,12 BUTTON "Salir" SIZE 35,18 OF oDlg PIXEL ACTION oDlg:End()



ACTIVATE DIALOG oDlg CENTER

RETURN(NIL)



STATIC FUNCTION Carga_dos( cCode, nModo )  // nModo=1 solo carga un elemento(el segundo)
                                           // nModo=2 carga los dos datos

LOCAL aReturn := {}

IF nModo=1

   IF cCode == "EX"
      AADD(aReturn,"DETALLE AA-1")
      AADD(aReturn,"DETALLE AA-2")
      AADD(aReturn,"DETALLE AA-3")
   ENDIF

   IF cCode == "RX"
      AADD(aReturn,"DETALLE BB-1")
      AADD(aReturn,"DETALLE BB-2")
      AADD(aReturn,"DETALLE BB-3")
   ENDIF

   IF cCode == "HX"
      AADD(aReturn,"DETALLE CC-1")
      AADD(aReturn,"DETALLE CC-2")
      AADD(aReturn,"DETALLE CC-3")
   ENDIF

ENDIF


IF nModo=2

   IF cCode == "EX"
      AADD(aReturn,{"A-1","DETALLE AA-1"})
      AADD(aReturn,{"A-2","DETALLE AA-2"})
      AADD(aReturn,{"A-3","DETALLE AA-3"})
   ENDIF

   IF cCode == "RX"
      AADD(aReturn,{"B-1","DETALLE BB-1"})
      AADD(aReturn,{"B-2","DETALLE BB-2"})
      AADD(aReturn,{"B-3","DETALLE BB-3"})
   ENDIF

   IF cCode == "HX"
      AADD(aReturn,{"C-1","DETALLE CC-1"})
      AADD(aReturn,{"C-2","DETALLE CC-2"})
      AADD(aReturn,{"C-3","DETALLE CC-3"})
   ENDIF

ENDIF



RETURN( aReturn )


STATIC FUNCTION Otra_funcion( )

   MSGALERT( C1_CODE )
   MSGALERT( C1_DATA )
   MSGALERT( C2_CODE )
   MSGALERT( C2_DATA )

RETURN(NIL)

 


Hola Jesus.

He estado estudiando tu codigo y tratando de entender la logica, ya que debo adaptarlo a mi necesidad real.

Para el caso del Array Combobox 2, este sera llenado desde una Dbf, dependiendo del codigo seleccionado en el combobox 1, por lo que necesito que me aclares la siguienta duda.

oCombo1:bChange := { || aItems2:=Carga_dos( C1_CODE, 2 ) ,;
aItemsCombo2:=Carga_dos( C1_CODE, 1 ) ,;
oCombo2:SetItems(aItemsCombo2) ,; // AQUI SE EVALUA oCombo2:bChange
cVar2:=aItemsCombo2[1] ,;
oCombo2:Refresh() }
Aqui envias a Cargar_dos, en 2 oportunidades, por la cantidad de datos, necesariamente se deben cargar ambas variables (aItems2 y aItemsCombo2) ?

Estoy tratando de modificar para que solo vaya 1 vez y cargue ambos array, debido que debo sacarlos de una DBF y podria tardar segunda la cantidad de datos, espero lograrlo.

Por que finalmente al ir a grabar, debo llevarme el C1_CODE y C2_CODE, que contiene los codigos de los elementos seleccionados en ambos Combobox.

Quedo atento a tus comentarios.

Muy agradecido.

Saludos
Antonio.
FWH 22.10 - HARBOUR - PELLES C
remtec
 
Posts: 719
Joined: Fri May 12, 2017 2:50 pm

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby JESUS MARIN » Fri Apr 10, 2020 4:44 am

Buenos días Antonio

Efectivamente, como yo pensaba, vas a rellenar el segundo array buscando en una Base de Datos.
Para el ejemplo, que solo era para que te sirviera de ayuda, lo había montado de esa manera, pues desconocía el origen de tus datos.
Simplemente lo que debes hacer es modificar esa función a tu gusto para que solo pase una vez.
En esa, única vez, rellenas el array aItems2.
Luego utilizas la función ArrTranspose() para que se rellene el array aItemsCombo2.
No encuentro en mi versión la función ArrTranspose(), por lo que no puedo probarlo. Pero por lo que he leído debe funcionar correctamente lo que te mando ahora.
Desarrolla tu función de búsqueda en la función Carga_dos() y pruébalo.
Ya nos cuentas.

Code: Select all  Expand view  RUN

# Include "Fivewin.ch"

# Define C1_CODE aItems1[oCombo1:nAt,1]
# Define C1_DATA aItems1[oCombo1:nAt,2]
# Define C2_CODE aItems2[oCombo2:nAt,1]
# Define C2_DATA aItems2[oCombo2:nAt,2]

STATIC aItems1 := {}
STATIC aItems2 := {}
STATIC oCombo1
STATIC oCombo2


FUNCTION Main()


LOCAL aItemsCombo1:={}, aItemsCombo2:={}
LOCAL cVar1, cVar2
LOCAL oDlg
LOCAL oGet, cText:=""


// Obtenemos los datos de una BASE DE DATOS O LOS MONTAMOS (en este caso lo montamos)

aItems1:={ {"EX","Examen 1"},{"RX","Examen 2"},{"HX","Examen 3"} }

// Creamos el array a mostrar en el combo1. Lo hacemos como indica C.Navarro, en vez de un FOR NEXT como suelo hacer yo

AEVal( aItems1, { | a | AAdd( aItemsCombo1, a[ 2 ] ) }  )

// Obtenemos los datos del array para el segundo combo con la funcion Carga_dos()
// Lo pongo en una funcion separada por si fuera necesario cargarlo en una BASE DE DATOS
// Como estamos inicializando los datos le pediremos que cargue el primer codigo de aItems1

aItems2      := Carga_dos( aItems1[1,1] )       // <-            modifica esta linea
aItemsCombo2 := ArrTranspose(aItems2)[2]        // <-            modifica esta linea



DEFINE DIALOG oDlg FROM 1,1 TO 200,500 PIXEL

 @ 012,12 ComboBox oCombo1 Var cVar1 Items aItemsCombo1 SIZE 100,200 PIXEL OF oDlg

 @ 042,12 ComboBox oCombo2 Var cVar2 Items aItemsCombo2 SIZE 100,200 PIXEL OF oDlg

 oCombo1:bChange := { || aItems2:=Carga_dos( C1_CODE )         ,;   // <-    modifica esta linea
                         aItemsCombo2:=ArrTranspose(aItems2)[2],;   // <-       modifica esta linea
                         oCombo2:SetItems(aItemsCombo2)        ,;         // AQUI SE EVALUA oCombo2:bChange
                         cVar2:=aItemsCombo2[1]                ,;
                         oCombo2:Refresh()  }


 oCombo2:bChange := { || ( cText:="Mi selección es : "+CRLF+CRLF+;
                           C1_CODE+CRLF+;
                           C1_DATA+CRLF+;
                           IF(oCombo2:nAt=0,aItems2[1,1],C2_CODE)+CRLF+;      // ver nota
                           IF(oCombo2:nAt=0,aItemsCombo2[1],C2_DATA) ,;
                           oGet:SetText(cText) ) }

              /// NOTA ////////////////////////////////////////////////////////
              // Cuando se realiza el oCombo2:SetItems(aItemsCombo2), se evalua oCombo2:bChange automaticamente
              // Como no se ha refrescado el oCombo2, el valor de oCombo2:nAt es 0 (cero)
              // por lo tanto hay que instrumentar que tome el primer valor.
              // Si no es cero, porque el usuario a modificado el oCombo2, seleccionando otro valor,
              // se muestra C2_CODE Y C2_DATA
              /////////////////////////////////////////////////////////////////



 // Cargo el texto con los primeros valores
 cText:="Mi selección es : "+CRLF+CRLF+aItems1[1,1]+CRLF+aItems1[1,2]+CRLF+aItems2[1,1]+CRLF+aItems2[1,2]
 @ 012,125 GET oGet VAR cText OF oDlg PIXEL SIZE 120, 60 MEMO

 @ 078,125 BUTTON "Funciones externas" SIZE 120,18 OF oDlg PIXEL ACTION Otra_funcion()

 @ 078,12 BUTTON "Salir" SIZE 35,18 OF oDlg PIXEL ACTION oDlg:End()



ACTIVATE DIALOG oDlg CENTER

RETURN(NIL)



STATIC FUNCTION Carga_dos( cCode )          // modifica esta linea y adapta tu código

LOCAL aReturn := {}


// escribe aqui tu rutina para buscar los datos que necesitas
// recuerda que la estructura del array debe tener al menos dos elementos cada uno

// ejemplo
//
// USE database [shared][new]
// SET INDEX TO ficheroindice
// DBSEEK( cCode )
// IF FOUND()
//  DO WHILE .T.
//    IF EOF() ; EXIT ; ENDIF
//    IF DATABASE->DATO1<>cCode ; EXIT ; ENDIF
//    AADD(aReturn, { dato1, dato2 } )
//    DBSKIP(1)
//  ENDDO
// ENDIF
//


RETURN( aReturn )


STATIC FUNCTION Otra_funcion( )

   MSGALERT( C1_CODE )
   MSGALERT( C1_DATA )
   MSGALERT( C2_CODE )
   MSGALERT( C2_DATA )


RETURN(NIL)


 
Jesús Marín
JESUS MARIN
 
Posts: 176
Joined: Wed Jan 02, 2019 8:36 am

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby JESUS MARIN » Fri Apr 10, 2020 5:31 am

Otra alternativa. Simplificada.

Como aItems2 se ha definido como variable STATIC y por tanto es visible en todo el .prg

llamas a la función Carga_dos() y rellenas aItems2 con los dos valores y rellenas aReturn solo con el segundo valor.
Veamos si de esta manera te parece mas sencillo. Ahora ya no es necesario llamar a ArrTranspose().
Tampoco es necesario llamar dos veces a Carga_dos()
He revisado la clase TComboBox y debe ser un array de una sola dimensión.

Code: Select all  Expand view  RUN

# Include "Fivewin.ch"

# Define C1_CODE aItems1[oCombo1:nAt,1]
# Define C1_DATA aItems1[oCombo1:nAt,2]
# Define C2_CODE aItems2[oCombo2:nAt,1]
# Define C2_DATA aItems2[oCombo2:nAt,2]

STATIC aItems1 := {}
STATIC aItems2 := {}
STATIC oCombo1
STATIC oCombo2


FUNCTION Main()


LOCAL aItemsCombo1:={}, aItemsCombo2:={}
LOCAL cVar1, cVar2
LOCAL oDlg
LOCAL oGet, cText:=""




aItems1:={ {"EX","Examen 1"},{"RX","Examen 2"},{"HX","Examen 3"} }
AEVal( aItems1, { | a | AAdd( aItemsCombo1, a[ 2 ] ) }  )


aItemsCombo2 := Carga_dos( aItems1[1,1] )



DEFINE DIALOG oDlg FROM 1,1 TO 200,500 PIXEL

 @ 012,12 ComboBox oCombo1 Var cVar1 Items aItemsCombo1 SIZE 100,200 PIXEL OF oDlg

 @ 042,12 ComboBox oCombo2 Var cVar2 Items aItemsCombo2 SIZE 100,200 PIXEL OF oDlg

 oCombo1:bChange := { || aItemsCombo2:=Carga_dos( C1_CODE )    ,;
                         oCombo2:SetItems(aItemsCombo2)        ,;
                         cVar2:=aItemsCombo2[1]                ,;
                         oCombo2:Refresh()  }


 oCombo2:bChange := { || ( cText:="Mi selección es : "+CRLF+CRLF+;
                           C1_CODE+CRLF+;
                           C1_DATA+CRLF+;
                           IF(oCombo2:nAt=0,aItems2[1,1],C2_CODE)+CRLF+;
                           IF(oCombo2:nAt=0,aItemsCombo2[1],C2_DATA) ,;
                           oGet:SetText(cText) ) }

 cText:="Mi selección es : "+CRLF+CRLF+aItems1[1,1]+CRLF+aItems1[1,2]+CRLF+aItems2[1,1]+CRLF+aItems2[1,2]
 @ 012,125 GET oGet VAR cText OF oDlg PIXEL SIZE 120, 60 MEMO

 @ 078,125 BUTTON "Funciones externas" SIZE 120,18 OF oDlg PIXEL ACTION Otra_funcion()

 @ 078,12 BUTTON "Salir" SIZE 35,18 OF oDlg PIXEL ACTION oDlg:End()



ACTIVATE DIALOG oDlg CENTER

RETURN(NIL)



STATIC FUNCTION Carga_dos( cCode )

LOCAL aReturn := {}

aItems2:={}

// ALTERNATIVA. Como aItems2 se ha definido como una variables STATIC y por tanto visible en todo el prg
// Rellena aItems2 con el codigo y el dato
// Rellena aReturn con el dato


// ejemplo
//
// USE database [shared][new]
// SET INDEX TO ficheroindice
// DBSEEK( cCode )
// IF FOUND()
//  DO WHILE .T.
//    IF EOF() ; EXIT ; ENDIF
//    IF DATABASE->DATO1<>cCode ; EXIT ; ENDIF

//      AADD(aItems2, { dato1, dato2 } )
//      AADD(aReturn, dato2 )



//    DBSKIP(1)
//  ENDDO
// ENDIF
//


// POR SI NO ENCUENTRA DATOS, PARA QUE NO SE PRODUZCA UN ERROR.
IF LEN(aItems2)=0
   AADD(aItems2,{"",""})
ENDIF
IF LEN(aReturn)=0
   AADD(aReturn,"")
ENDIF


RETURN( aReturn )


STATIC FUNCTION Otra_funcion( )

   MSGALERT( C1_CODE )
   MSGALERT( C1_DATA )
   MSGALERT( C2_CODE )
   MSGALERT( C2_DATA )


RETURN(NIL)


 
Jesús Marín
JESUS MARIN
 
Posts: 176
Joined: Wed Jan 02, 2019 8:36 am

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby remtec » Sat Apr 11, 2020 5:40 pm

Hola Jesus

Te agradezco enormemente toda la dedicación, tiempo, trabajo y preocupación por escribir el código solución.

He usado tu ultimo código para solucionar mi problema, Funciona PERFECTO.

Tengo una consulta, al llenar el 2° combobox, me queda en algunos casos con 300 elementos, no se si vera muy feo con tantos datos, pero me gustaria poder implementar busqueda incremental, ya que al digitar, solo busca la primera letra?

Muchas gracias de todo corazón.

Muchos saludos

Antonio.
FWH 22.10 - HARBOUR - PELLES C
remtec
 
Posts: 719
Joined: Fri May 12, 2017 2:50 pm

Re: Como Actilizar 2º Combobox ANIDADOS " URGENTE "

Postby JESUS MARIN » Sun Apr 12, 2020 4:44 am

remtec wrote:Hola Jesus

Te agradezco enormemente toda la dedicación, tiempo, trabajo y preocupación por escribir el código solución.

He usado tu ultimo código para solucionar mi problema, Funciona PERFECTO.

Tengo una consulta, al llenar el 2° combobox, me queda en algunos casos con 300 elementos, no se si vera muy feo con tantos datos, pero me gustaria poder implementar busqueda incremental, ya que al digitar, solo busca la primera letra?

Muchas gracias de todo corazón.

Muchos saludos

Antonio.


Buenos días Antonio
Me alegro que mi solución funcione.

Para las búsquedas incrementales dentro de un COMBO, te sugiero que abras un nuevo hilo.
Da por finalizado este, poniendo SOLUCIONADO.

La búsqueda en el Combo dependerá de la versión de FWH que tengas. Creo que hubieron muchos cambios.
Yo para ese tipo de búsquedas, cuando hay tantos registros, me ayudo de un Buscador Incremental propio.
Tal vez, otros compañeros te puedan ayudar mas que yo, en ese sentido, dentro de un Combo.

Saludos
Jesús
Jesús Marín
JESUS MARIN
 
Posts: 176
Joined: Wed Jan 02, 2019 8:36 am

Previous

Return to FiveWin para Harbour/xHarbour

Who is online

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