Page 2 of 3
Re: Grid Sort (Function / Method)
Posted: Tue Aug 23, 2016 1:49 pm
by Rathinagiri
A slight improvement to the procedure:
Now any grid column header can be clicked in ascending order. Immediately if you click again on the same column header it will be arranged in descending order.
Unicode arrow characters are suitably added to the column headers.
Claudio: Can we have a property to find out ColumnHeadClicked just like CellColClicked?
Code: Select all
#include <hmg.ch>
*----------------------------------------------------------------------*
PROCEDURE SortGrid( cWindow , cGrid , nColumn, cSortAs, lDesc )
*----------------------------------------------------------------------*
LOCAL L
LOCAL I
LOCAL aGrid := {}
local cHeader := ''
local nColCount := 0
local aJustify := {}
local aSorted := {}
default lDesc := .f.
default cSortAs := 'C'
default nColumn := 1
domethod( cWindow, cGrid, 'DISABLEUPDATE' )
cHeader := getproperty( cWindow, cGrid, 'ColumnHEADER', nColumn )
if HB_URIGHT( cHeader, 2 ) == ' ▲' // already in ascending order. change to desc!
lDesc := .t.
endif
if HB_URIGHT( cHeader, 2 ) == ' ▼' // already in descending order. change to asc!
lDesc := .f.
endif
nColCount := getproperty( cWindow, cGrid, 'COLUMNCOUNT' )
for i := 1 to nColCount
cHeader := getproperty( cWindow, cGrid, 'ColumnHEADER', i )
if HB_URIGHT( cHeader, 2 ) == ' ▲' .or. HB_URIGHT( cHeader, 2 ) == ' ▼' // remove the exising arrow
cHeader := hb_usubstr( cHeader, 1, hmg_len( cHeader ) - 2 )
setproperty( cWindow, cGrid, 'COLUMNHEADER', i, cHeader )
endif
next i
WAIT WINDOW 'Sorting...' NOWAIT
* Copy the grid content to an array.
L := GetProperty ( cWindow , cGrid , 'ItemCount' )
FOR I := 1 TO L
AADD( aGrid , GetProperty( cWindow , cGrid , 'Item' , I ) )
NEXT I
* Then Sort The Array...
if lDesc
do case
case cSortAS == 'C'
aSorted := asort( aGrid, , , { |x, y| x[nColumn] > y[nColumn] } )
case cSortAS == 'N'
aSorted := asort( aGrid, , , { |x, y| val( x[nColumn] ) > val( y[nColumn] ) } )
case cSortAS == 'D'
aSorted := asort( aGrid, , , { |x, y| ctod( x[nColumn] ) > ctod( y[nColumn] ) } )
endcase
else
do case
case cSortAS == 'C'
aSorted := asort( aGrid, , , { |x, y| x[nColumn] < y[nColumn] } )
case cSortAS == 'N'
aSorted := asort( aGrid, , , { |x, y| val( x[nColumn] ) < val( y[nColumn] ) } )
case cSortAS == 'D'
aSorted := asort( aGrid, , , { |x, y| ctod( x[nColumn] ) < ctod( y[nColumn] ) } )
endcase
endif
* Finally, Fill The Grid With The Sorted Array Content...
DoMethod( cWindow , cGrid , 'DeleteAllItems' )
FOR I := 1 TO L
DoMethod( cWindow , cGrid , 'AddItem' , aSorted[I] )
NEXT I
cHeader := getproperty( cWindow, cGrid, 'ColumnHEADER', nColumn )
if lDesc
cHeader := cHeader + ' ▼'
else
cHeader := cHeader + ' ▲'
endif
setproperty( cWindow, cGrid, 'COLUMNHEADER', nColumn, cHeader )
domethod( cWindow, cGrid, 'ENABLEUPDATE' )
* End
WAIT CLEAR
RETURN

- grid1.jpg (24.32 KiB) Viewed 5708 times

- grid2.jpg (25.79 KiB) Viewed 5708 times
Re: Grid Sort (Function / Method)
Posted: Tue Aug 23, 2016 3:04 pm
by jorge.posadas
Rathinagiri
Utilice tu funcion de SORTGRID, y ya me pone la flecha y me ordena el grid, pero si doy clic en la flecha no hace nada, yo implemente asi en mi codigo
SortGrid("Frm_ShowStates" ,"Grd_States" , 1, "C", .T. ) pero no funciona.
Use your SORTGRID function, and it makes me arrow and ordered me the grid, but if I click the arrow does nothing, so I implement in my code
SortGrid ("Frm_ShowStates", "Grd_States", 1, "C", .T.) Does not work.
Re: Grid Sort (Function / Method)
Posted: Tue Aug 23, 2016 3:30 pm
by srvet_claudio
Rathinagiri wrote:
Claudio: Can we have a property to find out ColumnHeadClicked just like CellColClicked?
I will investigate.
Re: Grid Sort (Function / Method)
Posted: Tue Aug 23, 2016 4:02 pm
by Rathinagiri
Use your SORTGRID function, and it makes me arrow and ordered me the grid, but if I click the arrow does nothing, so I implement in my code
SortGrid ("Frm_ShowStates", "Grd_States", 1, "C", .T.) Does not work.
As you can see in the code, the fifth parameter is not used inside the function. Have you clicked repeatedly the same column and the ascending and descending order are working alternatively. Right?
Re: Grid Sort (Function / Method)
Posted: Thu Aug 25, 2016 3:26 am
by jorge.posadas
I try differents test:
SortGrid("Frm_ShowStates" ,"Grd_States" , 1, "C",.F. )
SortGrid("Frm_ShowStates" ,"Grd_States" , 1, "C",.T. )
SortGrid("Frm_ShowStates" ,"Grd_States" , 1, "C")
I try diferents way
and any case dos no work. I'm using SQLITE
Re: Grid Sort (Function / Method)
Posted: Thu Aug 25, 2016 5:18 am
by Rathinagiri
Hi,
Please try to use the following procedure. This will take care if the 5th parameter is present.
Code: Select all
*----------------------------------------------------------------------*
PROCEDURE SortGrid( cWindow , cGrid , nColumn, cSortAs, lDesc )
*----------------------------------------------------------------------*
LOCAL L
LOCAL I
LOCAL aGrid := {}
local cHeader := ''
local nColCount := 0
local aJustify := {}
local aSorted := {}
default lDesc := .f.
default cSortAs := 'C'
default nColumn := 1
domethod( cWindow, cGrid, 'DISABLEUPDATE' )
if pcount() < 5 // ldesc parameter not given
cHeader := getproperty( cWindow, cGrid, 'ColumnHEADER', nColumn )
if HB_URIGHT( cHeader, 2 ) == ' ▲' // already in ascending order. change to desc!
lDesc := .t.
endif
if HB_URIGHT( cHeader, 2 ) == ' ▼' // already in descending order. change to asc!
lDesc := .f.
endif
endif
nColCount := getproperty( cWindow, cGrid, 'COLUMNCOUNT' )
for i := 1 to nColCount
cHeader := getproperty( cWindow, cGrid, 'ColumnHEADER', i )
if HB_URIGHT( cHeader, 2 ) == ' ▲' .or. HB_URIGHT( cHeader, 2 ) == ' ▼' // remove the exising arrow
cHeader := hb_usubstr( cHeader, 1, hmg_len( cHeader ) - 2 )
setproperty( cWindow, cGrid, 'COLUMNHEADER', i, cHeader )
endif
next i
WAIT WINDOW 'Sorting...' NOWAIT
* Copy the grid content to an array.
L := GetProperty ( cWindow , cGrid , 'ItemCount' )
FOR I := 1 TO L
AADD( aGrid , GetProperty( cWindow , cGrid , 'Item' , I ) )
NEXT I
* Then Sort The Array...
if lDesc
do case
case cSortAS == 'C'
aSorted := asort( aGrid, , , { |x, y| x[nColumn] > y[nColumn] } )
case cSortAS == 'N'
aSorted := asort( aGrid, , , { |x, y| val( x[nColumn] ) > val( y[nColumn] ) } )
case cSortAS == 'D'
aSorted := asort( aGrid, , , { |x, y| ctod( x[nColumn] ) > ctod( y[nColumn] ) } )
endcase
else
do case
case cSortAS == 'C'
aSorted := asort( aGrid, , , { |x, y| x[nColumn] < y[nColumn] } )
case cSortAS == 'N'
aSorted := asort( aGrid, , , { |x, y| val( x[nColumn] ) < val( y[nColumn] ) } )
case cSortAS == 'D'
aSorted := asort( aGrid, , , { |x, y| ctod( x[nColumn] ) < ctod( y[nColumn] ) } )
endcase
endif
* Finally, Fill The Grid With The Sorted Array Content...
DoMethod( cWindow , cGrid , 'DeleteAllItems' )
FOR I := 1 TO L
DoMethod( cWindow , cGrid , 'AddItem' , aSorted[I] )
NEXT I
cHeader := getproperty( cWindow, cGrid, 'ColumnHEADER', nColumn )
if lDesc
cHeader := cHeader + ' ▼'
else
cHeader := cHeader + ' ▲'
endif
setproperty( cWindow, cGrid, 'COLUMNHEADER', nColumn, cHeader )
domethod( cWindow, cGrid, 'ENABLEUPDATE' )
* End
WAIT CLEAR
RETURN
Re: Grid Sort (Function / Method)
Posted: Thu Aug 25, 2016 6:25 am
by serge_girard
Thanks Rathi !
Serge
Re: Grid Sort (Function / Method)
Posted: Wed Jan 11, 2017 8:03 pm
by KDJ
Below I present a different solution (set HDF_SORTUP/HDF_SORTDOWN format in listview header).
Code: Select all
#include 'hmg.ch'
FUNCTION Main()
SET FONT TO 'MS Shell Dlg', 8
OpenDB()
DEFINE WINDOW MainWA;
MAIN;
WIDTH 380;
HEIGHT 290;
TITLE 'Grid - Sort Header';
NOMAXIMIZE;
NOSIZE
DEFINE GRID CompGR
ROW 10
COL 10
WIDTH 350
HEIGHT 180
HEADERS {'RecNo', 'Name', 'Code', 'Price'}
WIDTHS {75, 110, 70, 70}
CELLNAVIGATION .T.
ROWSOURCE 'Comp'
COLUMNFIELDS {'RecNo()', 'Name', 'Code', 'Price'}
JUSTIFY {GRID_JTFY_RIGHT, GRID_JTFY_LEFT, GRID_JTFY_CENTER, GRID_JTFY_RIGHT}
END GRID
DEFINE BUTTON ExitBU
ROW 200
COL 140
WIDTH 80
HEIGHT 25
CAPTION 'E&xit'
ACTION MainWA.RELEASE
END BUTTON
DEFINE MAINMENU
DEFINE POPUP 'Set order'
MENUITEM 'RecNo' ACTION SetOrder(1, .F.)
SEPARATOR
MENUITEM 'Name - ascending' ACTION SetOrder(2, .F.)
MENUITEM 'Name - descending' ACTION SetOrder(2, .T.)
SEPARATOR
MENUITEM 'Code - ascending' ACTION SetOrder(3, .F.)
MENUITEM 'Code - descending' ACTION SetOrder(3, .T.)
SEPARATOR
MENUITEM 'Price - ascending' ACTION SetOrder(4, .F.)
MENUITEM 'Price - descending' ACTION SetOrder(4, .T.)
END POPUP
END MENU
END WINDOW
MainWA.CompGR.RECNO := RecNo()
MainWA.CompGR.ColumnONHEADCLICK(1) := { || SetOrder(1) }
MainWA.CompGR.ColumnONHEADCLICK(2) := { || SetOrder(2) }
MainWA.CompGR.ColumnONHEADCLICK(3) := { || SetOrder(3) }
MainWA.CompGR.ColumnONHEADCLICK(4) := { || SetOrder(4) }
SetOrder(2, .F.)
MainWA.CENTER
MainWA.ACTIVATE
RETURN NIL
FUNCTION SetOrder(nColumn, lDescend)
LOCAL nOrder := ordNumber(ordSetFocus())
LOCAL nRecord := MainWA.CompGR.RECNO
GridHeader_SetSort(MainWA.CompGR.HANDLE, nOrder + 1, 0)
IF ValType(lDescend) != 'L'
IF nColumn == 1
lDescend := .F.
ELSE
lDescend := If(nOrder == nColumn - 1, ! ordDescend(nOrder), .F.)
ENDIF
ENDIF
nOrder := nColumn - 1
GridHeader_SetSort(MainWA.CompGR.HANDLE, nColumn, If(lDescend, -1, 1))
ordSetFocus(nOrder)
ordDescend(nOrder, NIL, lDescend)
MainWA.CompGR.RECNO := nRecord
MainWA.CompGR.REFRESH
RETURN NIL
FUNCTION OpenDB()
LOCAL cDbf := 'Comp.dbf'
LOCAL cNtx := 'Comp.ntx'
LOCAL lIsDbf := File(cDbf)
IF lIsDbf
dbUseArea(NIL, NIL, cDbf)
ELSE
dbCreate(cDbf, {{'Name', 'C', 30, 0}, {'Code', 'C', 3, 0}, {'Price', 'N', 6, 2}})
dbUseArea(NIL, NIL, cDbf)
dbAppend()
Comp->Name := 'Main board'
Comp->Code := '002'
Comp->Price := 120.34
dbAppend()
Comp->Name := 'Processor'
Comp->Code := '004'
Comp->Price := 97.95
dbAppend()
Comp->Name := 'RAM'
Comp->Code := '006'
Comp->Price := 204.58
dbAppend()
Comp->Name := 'HDD'
Comp->Code := '008'
Comp->Price := 142.71
dbAppend()
Comp->Name := 'SSD'
Comp->Code := '010'
Comp->Price := 316.94
dbAppend()
Comp->Name := 'Graphics card'
Comp->Code := '012'
Comp->Price := 143.48
dbAppend()
Comp->Name := 'Power supply'
Comp->Code := '014'
Comp->Price := 54.29
dbAppend()
Comp->Name := 'PC case'
Comp->Code := '013'
Comp->Price := 72.85
dbAppend()
Comp->Name := 'Pendrive'
Comp->Code := '011'
Comp->Price := 12.78
dbAppend()
Comp->Name := 'Monitor'
Comp->Code := '009'
Comp->Price := 315.61
dbAppend()
Comp->Name := 'Keyboard'
Comp->Code := '007'
Comp->Price := 16.92
dbAppend()
Comp->Name := 'Mouse'
Comp->Code := '005'
Comp->Price := 9.84
dbAppend()
Comp->Name := 'Modem'
Comp->Code := '003'
Comp->Price := 31.45
dbAppend()
Comp->Name := 'Speakers'
Comp->Code := '001'
Comp->Price := 43.59
ENDIF
IF lIsDbf .and. File(cNtx)
ordListAdd(cNtx)
ELSE
ordCreate(cNtx, 'Name', 'Name', {|| Comp->Name}, .F. /*lUnique*/)
ordCreate(cNtx, 'Code', 'Code', {|| Comp->Code}, .F. /*lUnique*/)
ordCreate(cNtx, 'Price', 'Price', {|| Comp->Price}, .F. /*lUnique*/)
ENDIF
dbGoTop()
RETURN NIL
#pragma BEGINDUMP
#include "SET_COMPILE_HMG_UNICODE.ch"
#include "HMG_UNICODE.h"
#include <windows.h>
#include <commctrl.h>
#include "hbapi.h"
//GridHeader_SetSort(nHWndLV, nColumn[, nType /*0==none, positive==UP arrow or negative==DOWN arrow*/]) -> nType (previous setting)
HB_FUNC ( GRIDHEADER_SETSORT )
{
HWND hWndHD = (HWND) SendMessage((HWND) HMG_parnl(1), LVM_GETHEADER, 0, 0);
INT nItem = hb_parni(2) - 1;
INT nType;
HDITEM hdItem;
hdItem.mask = HDI_FORMAT;
SendMessage(hWndHD, HDM_GETITEM, nItem, (LPARAM) &hdItem);
if (hdItem.fmt & HDF_SORTUP)
hb_retni(1);
else if (hdItem.fmt & HDF_SORTDOWN)
hb_retni(-1);
else
hb_retni(0);
if ((hb_pcount() > 2) && HB_ISNUM(3))
{
nType = hb_parni(3);
if (nType == 0)
hdItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
else if (nType > 0)
hdItem.fmt = (hdItem.fmt & ~HDF_SORTDOWN) | HDF_SORTUP;
else
hdItem.fmt = (hdItem.fmt & ~HDF_SORTUP) | HDF_SORTDOWN;
SendMessage(hWndHD, HDM_SETITEM, nItem, (LPARAM) &hdItem);
}
}
#pragma ENDDUMP
Re: Grid Sort (Function / Method)
Posted: Thu Jan 12, 2017 1:24 am
by srvet_claudio
KDJ wrote: ↑Wed Jan 11, 2017 8:03 pm
Below I present a different solution (set HDF_SORTUP/HDF_SORTDOWN format in listview header).
Code: Select all
#include 'hmg.ch'
FUNCTION Main()
SET FONT TO 'MS Shell Dlg', 8
OpenDB()
DEFINE WINDOW MainWA;
MAIN;
WIDTH 380;
HEIGHT 290;
TITLE 'Grid - Sort Header';
NOMAXIMIZE;
NOSIZE
DEFINE GRID CompGR
ROW 10
COL 10
WIDTH 350
HEIGHT 180
HEADERS {'RecNo', 'Name', 'Code', 'Price'}
WIDTHS {75, 110, 70, 70}
CELLNAVIGATION .T.
ROWSOURCE 'Comp'
COLUMNFIELDS {'RecNo()', 'Name', 'Code', 'Price'}
JUSTIFY {GRID_JTFY_RIGHT, GRID_JTFY_LEFT, GRID_JTFY_CENTER, GRID_JTFY_RIGHT}
END GRID
DEFINE BUTTON ExitBU
ROW 200
COL 140
WIDTH 80
HEIGHT 25
CAPTION 'E&xit'
ACTION MainWA.RELEASE
END BUTTON
DEFINE MAINMENU
DEFINE POPUP 'Set order'
MENUITEM 'RecNo' ACTION SetOrder(1, .F.)
SEPARATOR
MENUITEM 'Name - ascending' ACTION SetOrder(2, .F.)
MENUITEM 'Name - descending' ACTION SetOrder(2, .T.)
SEPARATOR
MENUITEM 'Code - ascending' ACTION SetOrder(3, .F.)
MENUITEM 'Code - descending' ACTION SetOrder(3, .T.)
SEPARATOR
MENUITEM 'Price - ascending' ACTION SetOrder(4, .F.)
MENUITEM 'Price - descending' ACTION SetOrder(4, .T.)
END POPUP
END MENU
END WINDOW
MainWA.CompGR.RECNO := RecNo()
MainWA.CompGR.ColumnONHEADCLICK(1) := { || SetOrder(1) }
MainWA.CompGR.ColumnONHEADCLICK(2) := { || SetOrder(2) }
MainWA.CompGR.ColumnONHEADCLICK(3) := { || SetOrder(3) }
MainWA.CompGR.ColumnONHEADCLICK(4) := { || SetOrder(4) }
SetOrder(2, .F.)
MainWA.CENTER
MainWA.ACTIVATE
RETURN NIL
FUNCTION SetOrder(nColumn, lDescend)
LOCAL nOrder := ordNumber(ordSetFocus())
LOCAL nRecord := MainWA.CompGR.RECNO
GridHeader_SetSort(MainWA.CompGR.HANDLE, nOrder + 1, 0)
IF ValType(lDescend) != 'L'
IF nColumn == 1
lDescend := .F.
ELSE
lDescend := If(nOrder == nColumn - 1, ! ordDescend(nOrder), .F.)
ENDIF
ENDIF
nOrder := nColumn - 1
GridHeader_SetSort(MainWA.CompGR.HANDLE, nColumn, If(lDescend, -1, 1))
ordSetFocus(nOrder)
ordDescend(nOrder, NIL, lDescend)
MainWA.CompGR.RECNO := nRecord
MainWA.CompGR.REFRESH
RETURN NIL
FUNCTION OpenDB()
LOCAL cDbf := 'Comp.dbf'
LOCAL cNtx := 'Comp.ntx'
LOCAL lIsDbf := File(cDbf)
IF lIsDbf
dbUseArea(NIL, NIL, cDbf)
ELSE
dbCreate(cDbf, {{'Name', 'C', 30, 0}, {'Code', 'C', 3, 0}, {'Price', 'N', 6, 2}})
dbUseArea(NIL, NIL, cDbf)
dbAppend()
Comp->Name := 'Main board'
Comp->Code := '002'
Comp->Price := 120.34
dbAppend()
Comp->Name := 'Processor'
Comp->Code := '004'
Comp->Price := 97.95
dbAppend()
Comp->Name := 'RAM'
Comp->Code := '006'
Comp->Price := 204.58
dbAppend()
Comp->Name := 'HDD'
Comp->Code := '008'
Comp->Price := 142.71
dbAppend()
Comp->Name := 'SSD'
Comp->Code := '010'
Comp->Price := 316.94
dbAppend()
Comp->Name := 'Graphics card'
Comp->Code := '012'
Comp->Price := 143.48
dbAppend()
Comp->Name := 'Power supply'
Comp->Code := '014'
Comp->Price := 54.29
dbAppend()
Comp->Name := 'PC case'
Comp->Code := '013'
Comp->Price := 72.85
dbAppend()
Comp->Name := 'Pendrive'
Comp->Code := '011'
Comp->Price := 12.78
dbAppend()
Comp->Name := 'Monitor'
Comp->Code := '009'
Comp->Price := 315.61
dbAppend()
Comp->Name := 'Keyboard'
Comp->Code := '007'
Comp->Price := 16.92
dbAppend()
Comp->Name := 'Mouse'
Comp->Code := '005'
Comp->Price := 9.84
dbAppend()
Comp->Name := 'Modem'
Comp->Code := '003'
Comp->Price := 31.45
dbAppend()
Comp->Name := 'Speakers'
Comp->Code := '001'
Comp->Price := 43.59
ENDIF
IF lIsDbf .and. File(cNtx)
ordListAdd(cNtx)
ELSE
ordCreate(cNtx, 'Name', 'Name', {|| Comp->Name}, .F. /*lUnique*/)
ordCreate(cNtx, 'Code', 'Code', {|| Comp->Code}, .F. /*lUnique*/)
ordCreate(cNtx, 'Price', 'Price', {|| Comp->Price}, .F. /*lUnique*/)
ENDIF
dbGoTop()
RETURN NIL
#pragma BEGINDUMP
#include "SET_COMPILE_HMG_UNICODE.ch"
#include "HMG_UNICODE.h"
#include <windows.h>
#include <commctrl.h>
#include "hbapi.h"
//GridHeader_SetSort(nHWndLV, nColumn[, nType /*0==none, positive==UP arrow or negative==DOWN arrow*/]) -> nType (previous setting)
HB_FUNC ( GRIDHEADER_SETSORT )
{
HWND hWndHD = (HWND) SendMessage((HWND) HMG_parnl(1), LVM_GETHEADER, 0, 0);
INT nItem = hb_parni(2) - 1;
INT nType;
HDITEM hdItem;
hdItem.mask = HDI_FORMAT;
SendMessage(hWndHD, HDM_GETITEM, nItem, (LPARAM) &hdItem);
if (hdItem.fmt & HDF_SORTUP)
hb_retni(1);
else if (hdItem.fmt & HDF_SORTDOWN)
hb_retni(-1);
else
hb_retni(0);
if ((hb_pcount() > 2) && HB_ISNUM(3))
{
nType = hb_parni(3);
if (nType == 0)
hdItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
else if (nType > 0)
hdItem.fmt = (hdItem.fmt & ~HDF_SORTDOWN) | HDF_SORTUP;
else
hdItem.fmt = (hdItem.fmt & ~HDF_SORTUP) | HDF_SORTDOWN;
SendMessage(hWndHD, HDM_SETITEM, nItem, (LPARAM) &hdItem);
}
}
#pragma ENDDUMP
Very Nice!!
PD:The refence is:
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
Re: Grid Sort (Function / Method)
Posted: Fri Jan 13, 2017 4:17 am
by bpd2000
Nice, Thx for sharing