Sign in to follow this  
Followers 0
Rishav

Sorting a listview

6 posts in this topic

Hi folks

I have written a simple UI to show the contents of a csv file in a listview. However, i wanted the columns to be sortable by clicking on the column headers. I tried to use _GUICtrlListView_SimpleSort function but have absolutely no idea how to proceed. the helpfile gives no description of the $iCol parameter and the example provided is too tough for me to understand.

$csv_file = FileOpenDialog("Select CSV file", "C:\Documents and Settings\rishavs\My Documents\My Dropbox\Workspace\Automata\Automata Scripts\Output Log\System Log.csv","csv files (*.csv)",1)
;~ $csv_file = "C:\Documents and Settings\rishavs\My Documents\My Dropbox\Workspace\Automata\Automata Scripts\Output Log\System Log.csv"

#include <GUIConstants.au3>
#include <File.au3>
#include <GuiListView.au3>


Dim $csvArray

;Read CSV to array
_FileReadToArray($csv_file, $csvArray)

;Replace all commas with pipe symbols
For $i = 1 To $csvArray[0]
    $csvArray[$i] = StringReplace($csvArray[$i], ",", "|")
Next

$LogViewer_gui = GUICreate("System Log Viewer", 1200, 900, -1, -1)

;Use first row as header
$listview = GUICtrlCreateListView($csvArray[1], 10, 10, 1180, 880, $LVS_REPORT, $LVS_EX_GRIDLINES )
GUICtrlSetBkColor($listview, $GUI_BKCOLOR_LV_ALTERNATE)
_GUICtrlListView_SimpleSort($listview, True, 1)


_GUICtrlListView_BeginUpdate($listview)
;Create all listview items
For $i = 2 To $csvArray[0]
    GUICtrlCreateListViewItem($csvArray[$i], $listview)
    GUICtrlSetBkColor(-1, 0xEcEcEc)
Next

For $a = 0 To _GUICtrlListView_GetColumnCount($listview)
    _GUICtrlListView_SetColumnWidth($listview, $a, $LVSCW_AUTOSIZE_USEHEADER)
Next

_GUICtrlListView_EndUpdate($listview)

GUISetState()

Do
    $msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE

I have also added a csv file incase you want one.

thanks and regards

Rishav

System Log.zip

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Based on the example found in the help file for _GUICtrlListView_Create I catch $LVN_COLUMNCLICK and use the following code to sort:

$tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
_GUICtrlListView_SimpleSort($hWndListView, $bSort, DllStructGetData($tInfo, "SubItem"))

You have to set $bSort in advance to "False". This variable keeps the sort direction.

Your example script should now look like:

$csv_file = FileOpenDialog("Select CSV file", "C:\Documents and Settings\rishavs\My Documents\My Dropbox\Workspace\Automata\Automata Scripts\Output Log\System Log.csv","csv files (*.csv)",1)
;~ $csv_file = "C:\Documents and Settings\rishavs\My Documents\My Dropbox\Workspace\Automata\Automata Scripts\Output Log\System Log.csv"

#include <GUIConstants.au3>
#include <File.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>

Dim $csvArray
Global $bSort = False                ; Sort direction

;Read CSV to array
_FileReadToArray($csv_file, $csvArray)

;Replace all commas with pipe symbols
For $i = 1 To $csvArray[0]
    $csvArray[$i] = StringReplace($csvArray[$i], ",", "|")
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")        

$LogViewer_gui = GUICreate("System Log Viewer", 1200, 900, -1, -1)

;Use first row as header
$hlistview = GUICtrlCreateListView($csvArray[1], 10, 10, 1180, 880, $LVS_REPORT, $LVS_EX_GRIDLINES )
GUICtrlSetBkColor($hlistview, $GUI_BKCOLOR_LV_ALTERNATE)

_GUICtrlListView_BeginUpdate($hlistview)
;Create all listview items
For $i = 2 To $csvArray[0]
    GUICtrlCreateListViewItem($csvArray[$i], $hlistview)
    GUICtrlSetBkColor(-1, 0xEcEcEc)
Next

For $a = 0 To _GUICtrlListView_GetColumnCount($hlistview)
    _GUICtrlListView_SetColumnWidth($hlistview, $a, $LVSCW_AUTOSIZE_USEHEADER)
Next

_GUICtrlListView_EndUpdate($hlistview)

GUISetState()

Do
    $msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
;~  Local $tBuffer
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_COLUMNCLICK ; A column was clicked
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    _GUICtrlListView_SimpleSort($hWndListView, $bSort, DllStructGetData($tInfo, "SubItem"))
                    ; No return value
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Thanks for the reply Water.

I also got it to work by trial and error. realized that i was missing the _GUICtrlListView_RegisterSortCallBack function.

$csv_file = FileOpenDialog("Select CSV file", "C:\Documents and Settings\rishavs\My Documents\My Dropbox\Workspace\Automata\Automata Scripts\Output Log\System Log.csv", "csv files (*.csv)", 1)
;~ $csv_file = "C:\Documents and Settings\rishavs\My Documents\My Dropbox\Workspace\Automata\Automata Scripts\Output Log\System Log.csv"

#include <GUIConstants.au3>
#include <File.au3>
#include <GuiListView.au3>


Dim $csvArray

;Read CSV to array
_FileReadToArray($csv_file, $csvArray)

;Replace all commas with pipe symbols
For $i = 1 To $csvArray[0]
    $csvArray[$i] = StringReplace($csvArray[$i], ",", "|")
Next

$LogViewer_gui = GUICreate("System Log Viewer", 1200, 950, -1, -1)

$LogViewer_button = GUICtrlCreateButton("Refresh", 550, 910, 100)

;Use first row as header
$listview = GUICtrlCreateListView($csvArray[1], 10, 10, 1180, 880)
_GUICtrlListView_SetExtendedListViewStyle($listview, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_DOUBLEBUFFER))
_GUICtrlListView_RegisterSortCallBack($listview)
GUICtrlSetBkColor($listview, $GUI_BKCOLOR_LV_ALTERNATE)

_GUICtrlListView_BeginUpdate($listview)

;Create all listview items
For $i = 2 To $csvArray[0]
    GUICtrlCreateListViewItem($csvArray[$i], $listview)
    GUICtrlSetBkColor(-1, 0xEcEcEc)
Next

For $a = 0 To _GUICtrlListView_GetColumnCount($listview)
    _GUICtrlListView_SetColumnWidth($listview, $a, $LVSCW_AUTOSIZE_USEHEADER)
Next

_GUICtrlListView_EndUpdate($listview)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GUICtrlListView_UnRegisterSortCallBack($listview)
            ExitLoop
        Case $listview
            _GUICtrlListView_SortItems($listview, GUICtrlGetState($listview))

        Case $LogViewer_button
            _GUICtrlListView_DeleteAllItems($listview)

            _GUICtrlListView_BeginUpdate($listview)

            ;Create all listview items
            For $i = 2 To $csvArray[0]
                GUICtrlCreateListViewItem($csvArray[$i], $listview)
                GUICtrlSetBkColor(-1, 0xEcEcEc)
            Next

            For $a = 0 To _GUICtrlListView_GetColumnCount($listview)
                _GUICtrlListView_SetColumnWidth($listview, $a, $LVSCW_AUTOSIZE_USEHEADER)
            Next

            _GUICtrlListView_EndUpdate($listview)

    EndSwitch
WEnd

The only problem now is that sorting takes 1-2 seconds while i was hoping for it to be instanteneous.

Share this post


Link to post
Share on other sites

The only problem now is that sorting takes 1-2 seconds while i was hoping for it to be instanteneous.

You and me both. Wait until you get a listview of 65,000 items - it takes over an hour to sort. :D If you find the answer to quicker sorting, post it up please. I'm sure there are more than a few of us waiting for that one.

Share this post


Link to post
Share on other sites

You and me both. Wait until you get a listview of 65,000 items - it takes over an hour to sort. :D If you find the answer to quicker sorting, post it up please. I'm sure there are more than a few of us waiting for that one.

I expect you will get a big improvement simply by using _GUICtrlListView_BeginUpdate before you start sorting and _GUICtrlListView_EndUpdate after sorting.

You could also try copying to an array, sorting the array and copying back which I would expect to be faster.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

I expect you will get a big improvement simply by using _GUICtrlListView_BeginUpdate before you start sorting and _GUICtrlListView_EndUpdate after sorting.

You could also try copying to an array, sorting the array and copying back which I would expect to be faster.

I'll look into those functions thanks Martin.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0