Page 1 of 1

Cómo actualizo los combos en Xbrowse? (Solucionado)

Posted: Mon Apr 27, 2009 9:19 pm
by sjingo
Saludos amigos

Tengo un browse cuyas celdas se editan mediante combos. El contenido de los combos de cada columna varian de acuerdo a lo seleccionado en la columna anterior. En concreto lo que quiero hacer es mediante los combos seleccionar una provincia, y al hacerlo que se actualice en cascada _ o ciudades de esa provincia, las parroquias de ese cantón y los barrios de esa parroquia.

Ya logro actualizar los arrays de los combos, pero no se refrescan en los combos. No encuentro la forma de que se actualice el combo con los nuevo items.


Yo uso

Code: Select all

oCol:nEditType := EDIT_GET_LISTBOX
oBrwObr:aCols[i]:aEditListTxt   :=accanton
oBrwObr:aCols[i]:aEditListBound :ancanton
oBrwObr:acols[i]:bOnPostEdit := { |o,x,n| If( n != VK_ESCAPE,::SelLugar(i,x,obrwObr) , ) }
 


La función selLugar() se encarga de actualizar los arreglos.

Por ejemplo accanton y ancanton se actualizan con nuevos datos pero no se refrleja en el combo del xbrowse.
por favor si me echan una mano.

Marcelo Jingo

Re: Cómo actualizo los combos en Xbrowse?

Posted: Tue Apr 28, 2009 7:27 pm
by jrestojeda
Hola Marcelo...
Creo que el problema lo tienes en el COMBO no en el xBrowse.
Prueba hacer lo siguiente:

Code: Select all

   FOR Q=1 TO LEN(Array)
      oCombo:Modify(Array[Q],Q)
   NEXT

   oCombo:Select(1)
   oCombo:Refresh()
 
Espero te sirva.

Re: Cómo actualizo los combos en Xbrowse?

Posted: Mon May 04, 2009 3:30 am
by sjingo
Hoy volví a retomar este problema que aún no lo resolvía.

Esteban, gracias por tu interés. El problema es que el combo es un control que se crea en la clase TXBrwColumn y se destruye tan pronto como se sale del combobox y no encontraba cómo actualizar los valores del combo ya destruído. Esto me di cuanta al revisar dicha clase. Al hacerlo también encontré la solución que fue más fácil y no me di cuenta antes :oops:

Tan sólo hay que asignar a las propiedades :aEditListTxt y :aEditListBound los nuevos arrays modificados

Dentro de mi funcion SelLugar(i,x,obrwObr), luego de modificar los arrays con nuevos datos he puesto esto:

Code: Select all

    obrwObr:acols[2]:aEditListTxt:= accanton
    obrwObr:acols[2]:aEditListBound:= ancanton
 
Y ahora funciona OK

Un saludo a todos

Marcelo Jingo

Re: Cómo actualizo los combos en Xbrowse? (Solucionado)

Posted: Fri Mar 04, 2011 10:13 am
by jfafive
Hola,

Estoy trabajando con un XBrowse con RecordSet.
Quiero hacer que las celdas sean editables, para escribir en ellas.
He tomado como ejemplo el xbrowse autoedit de SAMPLES\TESTXBRW.PRG
pero mi idea no funciona.

Lo que quiero es que me permita ir añadiendo / modificando registros que pueda
escribir sobre el mismo xbrowse. El ejemplo de TESTXBRW.PRG trabaja con DBF (creo)
no se si será algun problema del recordset entonces....

Aquí les dejo mi codigo de ejemplo, Un saludo.

Code: Select all


....
TRY

   oRsB := TOleAuto():New( "ADODB.RecordSet" )

   oRsB:CursorLocation  := adUseClient
   oRsB:lockType        := adLockOptimistic
   oRsB:cursorType      := adOpenDynamic

   cStrSqlB := "SELECT * FROM tabla1"

   oRsB:Source := cStrSqlB

   oRsB:activeConnection( oCnnDb )

   oRsB:Open()

CATCH oError

   ShowError( oError, "xx", oCnnDB )

END

REDEFINE XBROWSE oXbrB ;
   RECSET oRsB ID ID_XBR OF oDlg

ACTIVATE DIALOG oDlg CENTER ;
   ON INIT ( oDlg:lHelpIcon := .f.,;
             oXbrB:aCols[1]:nEditType := 1 ) 
 

Re: Cómo actualizo los combos en Xbrowse? (Solucionado)

Posted: Tue Mar 08, 2011 5:48 pm
by sjingo
Javier
Espero no responder muy tarde.

La edición sobre la tabla o recordset le dejo al propio xbrowse , en el siguiente codigo establesco qué columnas quiero editar y qué tipo de edición realizar:

Code: Select all

    for i:=3 to len(oBrw2:acols)
        if i=4
            oBrw2:acols[i]:nEditType := EDIT_GET_LISTBOX //edicion con combo
            oBrw2:aCols[i]:aEditListTxt   := atareas_u  //contenido delcombo
        else
            oBrw2:acols[i]:nEditType := EDIT_GET //edicion normal
        endif
    next
    oBrw2:lFastEdit:=.t.
    oBrw2:lEditmode:=.t.
 
Para eliminar o crear nuevos registros en cambio uso botones que llaman a funciones con consultas SQL usando el objeto command creado previamente tal como se lo hace con el objeto recordset. Al crear el registro hay que tener en cuenta el asunto del autoincremento y de las claves foraneas, sino obtendremos errores difíciles de encontrar. La siguiente funcion la uso para añadir, a lo mejor esté algo confusa pero tú la puedes hacer más sencilla:

Code: Select all

//----------------------------------------------------------------------------//
//Inserto Un registro vacío para luego rellenar en el los datos
//Esto es conveniente así tenemos el registro con el siguiente numero autoincrementado
//oRs        Recordset que maneja la tabla
//tabla      nombre de la tabla donde se va a insertar
//is_auto    indica si el registro es autoincremental, por defecto es verdadero
//akey_ext   array con el nombre y valor del campo con clave externa
//akey_ext2  array con el nombre y valor de otro segundo campo que puede ser o no otra clave externa
//filltxt    .t. para rellenar con espacio un campo text, .f. no rellena con nada
//ncampos
METHOD InsIt(oRs,tabla,is_auto,akey_ext,akey_ext2,filltxt,ncampos) CLASS TVehic
local cQuery,nobra,cfilt
local i,acampotxt:={},cCampo:="",cValor:=""
default is_auto:=.t.
default filltxt:=.f.

if filltxt
    default ncampos:=oRs:fields:count
endif

//si filltxt está en verdadero Buscar si  no hay campos tipo texto
if filltxt
    for i:=1 to ncampos
        //msgalert(ors:fields(i-1):name)
        if ors:fields(i-1):Type = 203  //adLongVarchar en ADO
            aadd(acampotxt,ors:fields(i-1):name)
        endif
    next
    if len(acampotxt)>0
        for i:=1 to len(acampotxt)
              cCampo+=","+acampotxt[i]
              cValor+=",' '"
        next
    endif
endif


CursorWait()
if is_auto
    if akey_ext!=nil .and. akey_ext2!=nil
        cQuery :="insert into " + tabla + "(" + oRs:Fields(0):Name + ","+ akey_ext[1] +","+ akey_ext2[1] + cCampo+;
                                                        ") values(0,"+str(akey_ext[2])+","+str(akey_ext2[2]) + cValor +")"
    elseif  akey_ext!=nil
        cQuery :="insert into " + tabla + "(" + oRs:Fields(0):Name + ","+ akey_ext[1] + cCampo +;
                                                        ") values(0,"+alltrim(str(akey_ext[2]))+ cValor + ")"
    else
        cQuery :="insert into " + tabla + "(" + oRs:Fields(0):Name + cCampo + ") values(0"+cValor+")"
    endif
else
    if akey_ext!=nil .and. akey_ext2!=nil
        cQuery :="insert into " + tabla + "(" + oRs:Fields(0):Name + ","+ akey_ext[1] + ","+ akey_ext2[1]+ cCampo+;
                                                        ") values('" + space(20) + "'," + str(akey_ext[2]) + "," + str(akey_ext2[2]) + cValor+")"
    elseif akey_ext!=nil
        cQuery :="insert into " + tabla + "(" + oRs:Fields(0):Name + ","+ akey_ext[1] + cCampo +;
                                                        ") values('" + space(20) + "'," + str(akey_ext[2]) + cValor + ")"
    else
        cQuery :="insert into " + tabla + "(" + oRs:Fields(0):Name + cCampo +;
                                                        ") values('"+space(20)+"'" + cValor+ ")" //ojo si el primer campo es numerico puede dar error
    endif
endif
try
//msgalert(cQuery)
 ors:Requery()
 oCon:Execute(cQuery,"INSERT")
 oRs:Requery()
 oRs:Movelast()
catch oError
  showError(oError,oCon)
end

return .t.

//-------------------------------------
//Borra registro de un recordset
METHOD DelIt(oRs,ctabla,oBrw) CLASS TVehic
local cQuery,nrec,nlen
local uclave //Registro actual //asumimos que el campo clave es el primero
local cfield

CursorWait()
if !oRs:BOF .and. !oRs:EOF
    uclave:=oRs:Fields(0):Value //Registro actual //asumimos que el campo clave es el primero
    cfield:=oRs:Fields(0):Name
    cQuery :="delete from " + ctabla + " where "+ cfield +" = " +if(valtype(uclave)="N",str(uclave),"'"+alltrim(uclave)+"'")
    nrec:=oRs:AbsolutePosition
    oCon:Execute(cQuery,"DELETE")
    oRs:Requery()
    nLen:=oRs:RecordCount()
    if !oRs:BOF .and. !oRs:EOF
        if nlen+1 == nrec
            oRs:MoveLast()
        else
            oRs:Move(nrec-1)
        endif
    endif
else
    msgstop("No hay nada para borrar")
endif
return nil
 

Espero sea de guia. Saludos

Re: Cómo actualizo los combos en Xbrowse? (Solucionado)

Posted: Tue Mar 08, 2011 7:49 pm
by jfafive
Gracias Marcelo,

No ha sido muy tarde. Me ha dado una idea para solucionarlo.
Parece que el problema estaba en que no controlaba el bloque bOnPostEdit de la columna.
Entonces si escribia el mismo valor que tenia antes, se me colgaba la aplicación.

Le he puesto una condición para decirle que solo actualice el recordset si ha habido cambios.

Queda así, como sigue y me funciona:

Code: Select all

ACTIVATE DIALOG oDlgSC CENTER ;
   ON INIT ( oDlgSC:lHelpIcon := .f.,;
                  oXbrB:aCols[2]:nEditType   := EDIT_GET,;
                  oXbrB:aCols[3]:nEditType   := EDIT_GET,;
                  oXbrB:aCols[1]:nWidth      := 40,;
                  // Aquí es donde me aseguro que solo actualice si hay cambios...
                  oXbrB:aCols[2]:bOnPostEdit :=  { | o, v, n | if( v != oRsB:Fields( "nombre" ):Value,;
                                                                    oRsB:Fields( "nombre" ):Value := v, nil ) },;
             nRs := oRsB:RecordCount() ) ;
   VALID !( GetKeyState(27) )
 
Pero tengo otra pregunta,

Intento que una celda de mi xbrowse, sea un control DTPick donde cargar una fecha.
¿sabes si se puede hacer?

Un saludo,
Javier.

Re: Cómo actualizo los combos en Xbrowse? (Solucionado)

Posted: Wed Mar 09, 2011 10:01 pm
by sjingo
Javier
Si se puede, es más si revisas bien el ejemplo que te recomiendan en el otro post hace lo que estás buscando. Yo lo probé y funciona, da la opcion de editar manualmente la fecha o si das click en el bmp te muestra el calendario para seleccionar una fecha. Está en la columna 3.

Un Saludo