Indexar un listbox dando click en el encabezado

Post Reply
User avatar
mariordz
Posts: 127
Joined: Tue Dec 26, 2006 4:50 pm
Location: Ciudad de México

Indexar un listbox dando click en el encabezado

Post by mariordz »

Asi de simple como parece no he podido hacer que el usuario pueda ordenar el contenido de un browse dando click en la columna correspondiente, estoy usando un Browse simple:

define dialog oDialsv resource "DLGVERDB6" of oVentprinc title "Test"
redefine listbox oLbx1sv FIELDS clientes->nombre,cliente->direccion,clientes-ciudad.....
redefine button oBtn1sv ID 23 of oDialsv action(oDialsv:end(),repos:=report_no,conts:=continue,encuesta())
redefine button oBtn2sv ID 24 of oDialsv action (oDialsv:end(),cicsur:="N")
activate dialog oDialsv center


La pregunta es como puedo hacer que el usuario pueda tener esta caracteristica usando el brose que ya tengo desarrollado?

Les agradezco mucho la ayuda que me puedan brindar.

Saludos.
User avatar
wmormar
Posts: 1050
Joined: Fri Oct 07, 2005 10:41 pm
Location: México
Contact:

Re: Indexar un listbox dando click en el encabezado

Post by wmormar »

Puedes hacer que en el bloque click del header le cambies en el caso de CDX el TAG correspondiente y en el caso de NTX el indice respectivo.

por ejemplo con xbrowse.

Code: Select all

oBrw := TXBrowse():new( oDlg )
oBrw:aCols[1]:bLClickHeader :={|| mi_alias->(dbsetorder( "indice1"), oBrw:refresh()) 
Así podría ser una idea.
William, Morales
Saludos

méxico.sureste
User avatar
pedrog
Posts: 34
Joined: Tue Dec 30, 2008 7:22 pm
Location: Navarra, Spain

Re: Indexar un listbox dando click en el encabezado

Post by pedrog »

Yo por ejemplo lo hago con el bRclicked(), pero bueno, eso ya es cuetión de gustos...

aquí te dejo algo de código por si te puede servir para coger ideas, está hecho para TSbrowse.

Code: Select all

#include "FiveWin.ch"
#include "TSBrowse.ch"

#define CLR_PINK   nRGB( 255, 128, 128)
#define CLR_NBLUE  nRGB( 128, 128, 192)
#define CLR_1 nRGB( 190, 215, 190 ) // Azul Clarito
#define CLR_2 nRGB( 230, 230, 230 ) // Gris muy Clarito
#define CLR_3 nRGB( 217, 217, 255 ) // Morado Clarito

//----------------------------------------------------------------------------//
// Nueva implementación con la clase TSBrowse de Manuel Mercado.
FUNCTION Browse3( cTitle, cListName, bNew, bModify, bDelete, bSearch, bList, oParWnd, oDbf )

   LOCAL oDlg, oLbx, oFont, nOrden
   LOCAL btnList, btnEnd, i, aFields:={}

   //Guardamos el orden de entrada.
   nOrden:= IndexOrd()

   
   DEFAULT cTitle  := "Ver fichas ", cListName := "",;
           bList   := { || Reporte( oLbx ) }

   DEFINE FONT oFont NAME "Arial" SIZE 0, -12 //BOLD

   DEFINE DIALOG oDlg FROM 3, 3 TO 26, 79 TITLE cTitle FONT oFont

   @ 0, 1 SAY cListName  OF oDlg

   @ 1, 1 BROWSE oLbx SIZE 284, 137 OF oDlg FONT oFont;
          ON CHANGE ( IF(oDbf!=NIL,oDbf:Gather(),), IF( oParWnd!=NIL,oParWnd:Update(),) );
          ON dblClick ( oDlg:End() )

   oLbx:LoadFields( .F. )
   oLbx:nLineStyle := LINES_DOTTED 
   oLbx:nHeightHead += 4
   oLbx:lMoveCols := .T. 
   oLbx:nAdjColumn := 0

   aFields:= DbStruct()
   FOR i:=1 TO LEN( oLbx:aColumns )
       oLbx:aColumns[ i ]:cHeading:= UPPER( oLbx:aColumns[ i ]:cHeading )
       oLbx:aColumns[ i ]:l3DLookHead:=.T.
       oLbx:SetColSize( i, oLbx:aColumns[ i ]:nWidth + 42 )
       IF aFields[i][2] = "N"   // Numérico
         oLbx:aColumns[ i ]:nAlign:= 2
     oLbx:aColumns[ i ]:nHAlign:= 0
       ENDIF
       //oLbx:Set3DText( , ,  i , 2  ) 
   NEXT

   // Seteo de colores del Browse.
   oLbx:SetColor( { 2, 3, 4, 5, 6, 15 },{ { | Pos | If( Pos % 2 = 0, ;
                                              CLR_3, CLR_2 ) }, ;
                                              CLR_WHITE,;
                          { CLR_WHITE, CLR_BLUE },;
                                              CLR_WHITE,;
                          { CLR_WHITE, CLR_BLACK },;
                                              CLR_BLUE })

   
   //Botones del dialogo
   @ 10.4, 33.6 BUTTON btnList   PROMPT "&Imprimir" OF oDlg SIZE 40, 12
   @ 10.4, 41.7 BUTTON btnEnd    PROMPT "&Salir"    OF oDlg SIZE 40, 12


   btnList:bAction   = { || Eval( bList ), oLbx:Refresh() }
   btnEnd:bAction    = { || oDlg:End() }

   // Para ejecutar la función de ordenar por la columna.
   oLbx:bRClicked := {|nRowPix, nColPix| CreaIndice( oLbx, oDbf, aFields, oLbx:nATCol(nColPix)) }


   ACTIVATE DIALOG oDlg Centered;
            ON PAINT FillWnd( oDlg, nRGB( 13, 147, 185 ),, 10 );
            ON INIT CampoIndice( oLbx, aFields );
        VALID ( DBSETORDER(nOrden), .T. )
// En el ON INIT estamos colocando como primera columna al campo clave del índice activo

RELEASE FONT oFont

return nil


//----------------------------------------------------------------------------//
// Colocación del campo índice activo como primera columna en el browse
//----------------------------------------------------------------------------//
STATIC FUNCTION CreaIndice( oLbx, oDbf, aFields, nCol )
LOCAL aIndices:={}, aIndices2:={}, n, j

//Averiguamos si el campo ya tiene un índice activo, en caso de tenerlo lo activamos
//En caso contrario generamos un índice temporal y lo añadimos a los índices activos.
//Cambiamos la columna a la 1ª posición en el browse.


//Indices en uso del fichero:
FOR j := 1 TO 15
   IF !Empty( cExpKey:= IndexKey( j ) )
      AADD( aIndices2,  ORDBAGNAME(j)  )
         IF (n := AT("(", cExpKey)) > 0//n > 0   //Quitamos _ STR(
            cExpKey:= LEFT(cExpKey, n-4) + RIGHT(cExpKey, LEN(ALLTRIM(cExpKey))-n )
         ENDIF
         IF (n := AT(")", cExpKey) ) > 0    //n > 0   //Quitamos _ ,n,y)
            cExpKey:= LEFT(cExpKey, n-5) + RIGHT(cExpKey, LEN(ALLTRIM(cExpKey))-n )
         ENDIF
         IF (n := AT("+", cExpKey) ) >0 //n > 0 //Quitamos todo lo que está por detrás del caracter +
            cExpKey:=LEFT(cExpKey, n-1)
         ENDIF
      AADD( aIndices,  UPPER(cExpKey)  )
    ENDIF
NEXT

IF ( n:=ASCAN( aIndices, oLbx:aColumns[ nCol ]:cHeading  ) ) > 0
   //Ya existe ese índice
   //Ponemos el orden como activo.
   DBSETORDER(n)
ELSE
   //Creamos un índice si no existe.
   CreaIndex( oLbx:aColumns[ nCol ]:cHeading, aIndices2 )
   SET INDEX TO
   FOR j := 1 TO LEN( aIndices2 )
     oDbf:AddIndex(aIndices2[j],aIndices2[j])
   NEXT
   SELECT( oDbf:cAlias )
   DBSETORDER( LEN(aIndices2) )
ENDIF

//Cambiamos el campo índice como 1ª columna
oLbx:MoveColumn( nCol, 1 )
oDbf:GoFirst()
oLbx:GoTop()
oLbx:Reset()

RETURN NIL

//----------------------------------------------------------------------------//
// Colocación del campo índice activo como primera columna en el browse
//----------------------------------------------------------------------------//
STATIC FUNCTION CreaIndex( cHeading, aIndices2 )
LOCAL tempind1, passind, pasfor

tempind1 = "CC" + SUBSTR(TIME(),1,2) + SUBSTR(TIME(),4,2) + SUBSTR(TIME(),7,2) + ".ntx"
passind  = cHeading //"Recno()"
passfor  = "Recno() > 0"

MsgMeter( { | ometer, otext, odlg, lend | genindex( ometer, otext, odlg, @lend, tempind1, passind, passfor ) }, ;
            "Ordenando fichero ...", "Ordenando fichero ...." )
AADD( aIndices2,  tempind1  )

RETURN NIL

//----------------------------------------------------------------------------//
// Creación del fichero índice temporal.
//----------------------------------------------------------------------------//
STATIC FUNCTION genindex( ometer, otext, odlg, lend, tempind1, passind, passfor )
LOCAL cDbf
cDbf:=ALIAS()
ometer:ntotal := LASTREC()

INDEX ON &passind TO &tempind1  FOR &passfor ;
   EVAL ( ometer:SET( RECNO() ), otext:settext("Ordenando ficha " + ALLTRIM(STR(RECNO()))), ;
   sysrefresh(), !lend )

RETURN( nil )

//----------------------------------------------------------------------------//
// Colocación del campo índice activo como primera columna en el browse
//----------------------------------------------------------------------------//
STATIC FUNCTION CampoIndice( oLbx, aFields )
LOCAL nOrden, cExpKey
   //Posicionamiento de campo índice activo en primer lugar.
   nOrden:= IndexOrd()
   cExpKey:= IndexKey( nOrden )
   IF LEN(ALLTRIM(cExpKey)) > 0
      n := AT("(", cExpKey) //Quitamos _ STR(
      IF n > 0
         cExpKey:= LEFT(cExpKey, n-4) + RIGHT(cExpKey, LEN(ALLTRIM(cExpKey))-n )
      ENDIF
      n := AT(")", cExpKey) //Quitamos _ ,n,y)
      IF n > 0
         cExpKey:= LEFT(cExpKey, n-5) + RIGHT(cExpKey, LEN(ALLTRIM(cExpKey))-n )
      ENDIF
      n := AT("+", cExpKey) //Quitamos todo lo que está por detrás del caracter +
      IF n > 0
         cExpKey:=LEFT(cExpKey, n-1)
      ENDIF
      //La movemos a la primera columna
      IF (nPos:=ASCAN( aFields, {|x| x[1] = UPPER(cExpKey) } ) ) > 0
         oLbx:MoveColumn( nPos, 1 )
      ENDIF
   ENDIF

RETURN NIL
Pedro
FWH9.06 / XMate 1.15 / Borland C++ 5.5.1 / xHarbour build 1.1.0 Intl. (SimpLex) (Rev. 6195)
User avatar
acuellar
Posts: 1312
Joined: Tue Oct 28, 2008 6:26 pm
Location: Santa Cruz-Bolivia

Re: Indexar un listbox dando click en el encabezado

Post by acuellar »

Mario, tenes que usar TAG en tus indices

Code: Select all

//En el programas de índices
USE DATOS ALIAS DATPER EXCLUSIVE
INDEX On NOMBRE  TAG DATOS1
INDEX On CARGO  TAG DATOS2
DATPER->( dBCloseArea() )
...
//En el programa del Browse
Use DATOS INDEX DATOS ALIAS DATPER NEW SHARED
 
  DEFINE DIALOG oDlg RESOURCE "MUESTRA" Title 'MUESTRA DATOS PERSONALESS'
   oBrw:=TXBrowse():New( oDlg )
   oBrw:nMarqueeStyle:=MARQSTYLE_HIGHLROW
   oBrw:nColDividerStyle:= LINESTYLE_LIGHTGRAY
   oBrw:nRowDividerStyle:= LINESTYLE_LIGHTGRAY
      
   oCol:=oBrw:AddCol()
   oCol:bStrData  := { || DATPER->NOMBRE}
   oCol:nHeadStrAlign := AL_CENTER
   oCol:cHeader:= "NOMBRE"
   oCol:nWidth:=200
   oCol:cSortOrder:="DATOS1"
   oCol:bLClickHeader:= {|| oBrw:Gotop() }  //Por si queres que puntero se vaya al inicio
   
   oCol:=oBrw:AddCol()
   oCol:bStrData  := { || DATPER->CARGO}
   oCol:nHeadStrAlign := AL_CENTER
   oCol:cHeader:= "CARGO"
   oCol:nWidth:=150
   oCol:cSortOrder:="DATOS2"
   oCol:bLClickHeader:= {|| oBrw:Gotop() } 
 
   oBrw:CreateFromCode()

  ACTIVATE DIALOG oDlg CENTERED 

 
Dando Click sobre el Header se ordena por esa columna si le volves a dar se invierte el orden

Saludos

Adhemar
Saludos,

Adhemar C.
User avatar
mariordz
Posts: 127
Joined: Tue Dec 26, 2006 4:50 pm
Location: Ciudad de México

Re: Indexar un listbox dando click en el encabezado

Post by mariordz »

Compañeros del foro, muchas gracias por su apoyo hasta el momento no he logrado implementar esta opción, al compilar me aparece el error:

Error description: Error BASE/1005 Message not found: TXBRWCOLUMN:_CSORTORDER
Stack Calls
===========
Called from TXBRWCOLUMN:ERROR(175)
Called from (b)HBOBJECT(105)
Called from TXBRWCOLUMN:MSGNOTFOUND(0)
Called from TXBRWCOLUMN:_CSORTORDER(167)
Called from INVGRAL(67)
Called from (b)CREAMENU(388)
Called from TMENU:COMMAND(0)
Called from TWINDOW:COMMAND(0)
Called from TMDIFRAME:COMMAND(0)
Called from TMDIFRAME:HANDLEEVENT(0)
Called from _FWH(0)
Called from WINRUN(0)
Called from TMDIFRAME:ACTIVATE(0)
Called from MAIN(139)

Estoy usando la versión 2.6 de Fivewin (si, es algo "viejita"), posiblemente esta versión no soporta esta caracteristica, por cuestiones de "presupuesto" no he podido actualizar a la ultima versión, asi que si este es el problema tendré que seguir con él y dejar a los usuarios sin esta caracteristica, a menos de que se pueda hacer de otra manera :(

Disculpen mi novatez en este tema, pero no estoy seguro de si el"TXBROWSE" es generado en un dialogo independiente o puede ser asociado a un recurso dentro de un dialogo con otros elementos? (por ejemplo ID 100 of oDialogo)?

Muchas gracias nuevamente por el apoyo


Aqui les paso mi codigo a ver si alguien tiene una idea para mejorarlo

Code: Select all

Function invgral
   local oDialig, oBtn1ig, oBtn2ig, oBtn3ig, oSay1ig, oLbx1ig
   close all
   use &dbmapt shared new alias parts
   index on part_no TAG iXpar
   index on descr TAG iXdes3
   index on descreal TAG iXdesc
   *index on part_no to &dbidx1
   copy to &dbtmp1
   close all
   use &dbmapt shared new alias parts
   define dialog oDialig resource "DLGVERDB4" of oVentprinc title "Inventario en almacen"
   redefine say oSay1ig prompt "Inventario general en almacen" id 1 of oDialig
   oBrw:=TXBrowse():New( oDialig )
   oBrw:nMarqueeStyle:=MARQSTYLE_HIGHLROW
   oBrw:nColDividerStyle:= LINESTYLE_LIGHTGRAY
   oBrw:nRowDividerStyle:= LINESTYLE_LIGHTGRAY

   oCol:=oBrw:AddCol()
   oCol:bStrData  := { || parts->part_no}
   oCol:nHeadStrAlign := AL_CENTER
   oCol:cHeader:= "No. de parte"
   oCol:nWidth:=200
   *oCol:cSortOrder:="iXpar"
   oCol:bLClickHeader:= {|| oBrw:Gotop() }  //Por si queres que puntero se vaya al inicio

   oCol:=oBrw:AddCol()
   oCol:bStrData  := { || parts->descr}
   oCol:nHeadStrAlign := AL_CENTER
   oCol:cHeader:= "Descripción 3M"
   oCol:nWidth:=150
   *oCol:cSortOrder:="iXdes3"
   oCol:bLClickHeader:= {|| oBrw:Gotop() }

   oCol:=oBrw:AddCol()
   oCol:bStrData  := { || parts->descreal}
   oCol:nHeadStrAlign := AL_CENTER
   oCol:cHeader:= "Descripción CS"
   oCol:nWidth:=150
   *oCol:cSortOrder:="iXdesc"
   oCol:bLClickHeader:= {|| oBrw:Gotop() }

   oBrw:CreateFromCode()

/*   redefine listbox oLbx1ig fields substr(parts->part_no,1,2)+"-"+substr(parts->part_no,3,4)+"-"+substr(parts->part_no,7,4)+"-"+substr(parts->part_no,11,1),;
   parts->descr, parts->descreal, str(parts->q_bal), parts->commodity, parts->location id 0 of oDialig alias "parts";
   headers "No. de parte","Descripción 3M","Descripción CS","Cantidad","Commodity","Ubicación"*/
   redefine button oBtn1ig ID 2 of oDialig prompt"&Imprimir" action(oDialig:end(),impres())
   redefine button oBtn2ig ID 3 of oDialig prompt"&Exportar" action (oDialig:end(),expres())
   redefine button oBtn3ig ID 4 of oDialig prompt"&Regresar" action (odialig:end())
   activate dialog oDialig center
return
User avatar
wmormar
Posts: 1050
Joined: Fri Oct 07, 2005 10:41 pm
Location: México
Contact:

Re: Indexar un listbox dando click en el encabezado

Post by wmormar »

mariordz,

Efectivamente puede ser una limitación de la versión que tienes.

Te comento que Antonio Linares ha liberado la versión 6.2

aqui el link
http://forums.fivetechsupport.com/viewt ... ilit=libre

Espero te sirva
William, Morales
Saludos

méxico.sureste
Post Reply