c.haslam Posted June 5, 2018 Share Posted June 5, 2018 (edited) My script lists all files in a path, showing filename, extension, size, and path. While filename, extension and path should use a string-sort, size should sort numerically. (Size is comma-separated). Looking at the examples in the Help, I see how to sort all columns using the same sort sequence, but how can I have one sort sequence for one and column, and a different one for the others? I have searched the forum, but I still have no clear idea to how to do it. In the Help, I have been particularly looking at the examples for _GuiListView_SortItems(). My script follows. expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiListView.au3> #include "MsgBoxUDF\MsgBoxUDF.au3" ; Thanks to Melba23 Opt('MustDeclareVars',1) Global Enum $kFnam,$kExt,$kSize,$kDateTime,$kPath If UBound($cmdline)=1 Then MsgBox($MB_ICONINFORMATION,'Information','One parameter, a path, is required') Exit 1 EndIf If Not FileExists($cmdline[1]) Then _MsgBox($MB_ICONERROR,'Error','Parameter 1, "'&$cmdline[1]&'", must be a drive or directory') Exit 1 EndIf Local $sPath = $cmdline[1] If StringRight($sPath,1)='\' Then $sPath = StringTrimRight($sPath,1) EndIf main($sPath) Func main($sPath) Local $FormFF = GUICreate($sPath,@DesktopWidth/2,@DesktopHeight-57,1,-1) Local $idListview = _GUICtrlListView_Create($FormFF,"",8,8,@DesktopWidth/2-16,@DesktopHeight-150) _GUICtrlListView_InsertColumn($idListview, 0, "Filename", 400) _GUICtrlListView_InsertColumn($idListview, 1, "Ext", 50) _GUICtrlListView_InsertColumn($idListview, 2, "Size",70) _GUICtrlListView_InsertColumn($idListview, 3, 'Date time',100) _GUICtrlListView_InsertColumn($idListview, 4, "Path", 385) _GUICtrlListView_JustifyColumn($idListview, $kSize,1) ; right align Local $idLbl = GUICtrlCreateLabel('',20,@DesktopHeight-135,@DesktopWidth/2-20,20) Local $btnRemove = GUICtrlCreateButton("Remove", 20,@DesktopHeight-110,60,30) Local $btnClose = GUICtrlCreateButton("Close", @DesktopWidth/2-100,@DesktopHeight-110,50,25) GUISetState(@SW_SHOW) _GUICtrlListView_SetExtendedListViewStyle($idListview,BitOR($LVS_EX_CHECKBOXES,$LVS_EX_GRIDLINES)) Local $nTotBytes=0 PopulateListView($idListview,$idLbl,$cmdLine[1], $nTotBytes) For $i = $kFnam To $kPath _GUICtrlListView_SetColumnWidth($idListview,$i,$LVSCW_AUTOSIZE) Next Local $t = AddThousandsSeparator(_GUICtrlListView_GetItemCount($idListview))&' files ('& _ AddThousandsSeparator($nTotBytes)&' bytes)' GUICtrlSetData($idLbl,$t) Local $nMsg While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE,$btnClose ExitLoop Case $btnRemove Local $bDel=False,$filspc If _MsgBoxEx($MB_YESNO + $MB_DEFBUTTON2 + $MB_ICONQUESTION,"","Remove checked files from backup?", _ 0,WinGetHandle('')) Then For $i = _GUICtrlListView_GetItemCount($idListview)-1 To 0 Step -1 If _GUICtrlListView_GetItemChecked($idListview,$i) Then $nTotBytes -= StringReplace(_GUICtrlListView_GetItemText($idListview,$i,$kSize),',','') $filspc = _GUICtrlListView_GetItemText($idListview,$i,$kPath) $filspc &= '\'&_GUICtrlListView_GetItemText($idListview,$i,$kFnam) $t = _GUICtrlListView_GetItemText($idListview,$i,$kExt) If $t<>'' Then $filspc &= '.'&$t EndIf ;~ FileDelete($filspc) ; for now!! $bDel = True _GUICtrlListView_DeleteItem($idListview,$i) EndIf Next If $bDel Then Local $q = _GUICtrlListView_GetItemCount($idListview) GUICtrlSetData($idLbl,AddThousandsSeparator($q)&' files ('&AddThousandsSeparator($nTotBytes)&' bytes)') If $q=0 Then GUICtrlSetState($btnRemove,$GUI_DISABLE) EndIf EndIf EndIf EndSwitch WEnd GUIDelete($FormFF) EndFunc Func PopulateListView($idListview,$idLbl,$sPath, ByRef $nTotBytes) Local $sFnamExt,$sAtts,$sDirs='',$p,$sFnam,$sExt,$a1,$nSize,$t,$nItem Local $iSrch = FileFindFirstFile($sPath&'\*.*') If $iSrch=-1 Then Return EndIf While True $sFnamExt = FileFindNextFile($iSrch) If @error Then ExitLoop EndIf $sAtts = FileGetAttrib($sPath&'\'&$sFnamExt) If StringInStr($sAtts,'D') Then $sDirs &= '?'&$sPath&'\'&$sFnamExt Else $p = StringInStr($sFnamExt,'.',0,-1) ; last If $p=0 Then $sFnam = $sFnamExt $sExt = '' Else $sFnam = StringLeft($sFnamExt,$p-1) $sExt = StringTrimLeft($sFnamExt,$p) EndIf $nItem = _GUICtrlListView_GetItemCount($idListview) _GUICtrlListView_AddItem($idListview,$sFnam) _GUICtrlListView_AddSubItem($idListview,$nItem,$sExt,$kExt) $nSize = FileGetSize($sPath&'\'&$sFnamExt) _GUICtrlListView_AddSubItem($idListview,$nItem,AddThousandsSeparator($nsize),$kSize) $nTotBytes += $nSize $a1 = FileGetTime($sPath&'\'&$sFnamExt,$FT_MODIFIED,$FT_ARRAY) $t = $a1[0]&'-'&$a1[1]&'-'&$a1[2]&' '&$a1[3]&':'&$a1[4] _GUICtrlListView_AddSubItem($idListview,$nItem,$t,$kDateTime) _GUICtrlListView_AddSubItem($idListview,$nItem,$sPath,$kPath) EndIf WEnd FileClose($iSrch) GUICtrlSetData($idLbl,AddThousandsSeparator($nTotBytes)&' bytes') If $sDirs<>'' Then $sDirs = StringTrimLeft($sDirs,1) $a1 = StringSplit($sDirs,'?',0+2) ; char,0-based For $i = 0 To UBound($a1)-1 PopulateListView($idListview,$idLbl,$a1[$i], $nTotBytes) Next EndIf EndFunc Func AddThousandsSeparator($n) Local $s = String($n) Local $sRet='' For $i = StringLen($s) To 1 Step -3 $sRet = StringMid($s,$i-2,3)&','&$sRet Next $sRet = StringTrimRight($sRet,1) If $i<>0 Then $sRet = StringLeft($s,3+$i)&$sRet EndIf Return $sRet EndFunc Edited June 5, 2018 by c.haslam Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
AutoBert Posted June 5, 2018 Share Posted June 5, 2018 Try this one from the help: expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiImageList.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> Global $g_idListView Example() Func Example() Local $hImage, $aIcons[3] = [0, 3, 6] Local $iExWindowStyle = BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE) Local $iExListViewStyle = BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_GRIDLINES, $LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER) GUICreate("ListView Sort", 300, 200) $g_idListView = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180, -1, $iExWindowStyle) _GUICtrlListView_SetExtendedListViewStyle($g_idListView, $iExListViewStyle) ; Load images $hImage = _GUIImageList_Create(18, 18, 5, 3) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -7) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -12) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -3) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -4) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -5) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -6) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -9) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -10) _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -11) _GUICtrlListView_SetImageList($g_idListView, $hImage, 1) _AddRow($g_idListView, "ABC|000666|10.05.2004", $aIcons) _AddRow($g_idListView, "DEF|444|11.05.2005", $aIcons, 1) _AddRow($g_idListView, "CDE|555|12.05.2004", $aIcons, 2) GUISetState(@SW_SHOW) _GUICtrlListView_RegisterSortCallBack($g_idListView) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $g_idListView ; Kick off the sort callback _GUICtrlListView_SortItems($g_idListView, GUICtrlGetState($g_idListView)) EndSwitch WEnd _GUICtrlListView_UnRegisterSortCallBack($g_idListView) GUIDelete() EndFunc ;==>Example Func _AddRow($hWnd, $sItem, $aIcons, $iPlus = 0) Local $aItem = StringSplit($sItem, "|") Local $iIndex = _GUICtrlListView_AddItem($hWnd, $aItem[1], $aIcons[0] + $iPlus, _GUICtrlListView_GetItemCount($hWnd) + 9999) _GUICtrlListView_SetColumnWidth($hWnd, 0, $LVSCW_AUTOSIZE_USEHEADER) For $x = 2 To $aItem[0] _GUICtrlListView_AddSubItem($hWnd, $iIndex, $aItem[$x], $x - 1, $aIcons[$x - 1] + $iPlus) _GUICtrlListView_SetColumnWidth($hWnd, $x - 1, $LVSCW_AUTOSIZE) Next EndFunc ;==>_AddRow Link to comment Share on other sites More sharing options...
c.haslam Posted June 6, 2018 Author Share Posted June 6, 2018 I do not see how this example uses a different sort sequence for each column. Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
mikell Posted June 6, 2018 Share Posted June 6, 2018 Adding a thousands separator makes sorting difficult The easiest solution is to create a 0-width fifth column to put sizes non thousand separated, so when you click the col 2 header the sorting is done on col 5 using _GUICtrlListView_SimpleSort expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <FileConstants.au3> ;#include "MsgBoxUDF\MsgBoxUDF.au3" ; Thanks to Melba23 ;Opt('MustDeclareVars',1) Global Enum $kFnam,$kExt,$kSize,$kDateTime,$kPath,$kSize2 Global $listview Local $sPath = @desktopdir If StringRight($sPath,1)='\' Then $sPath = StringTrimRight($sPath,1) EndIf main($sPath) Func main($sPath) Local $FormFF = GUICreate($sPath,@DesktopWidth/2,@DesktopHeight-57,1,-1) $listview = GUICtrlCreateListView("",8,8,@DesktopWidth/2-16,@DesktopHeight-150) $idListview = GUICtrlGetHandle($listview) ; Local $idListview = _GUICtrlListView_Create($FormFF,"",8,8,@DesktopWidth/2-16,@DesktopHeight-150) _GUICtrlListView_InsertColumn($idListview, 0, "Filename", 400) _GUICtrlListView_InsertColumn($idListview, 1, "Ext", 50) _GUICtrlListView_InsertColumn($idListview, 2, "Size",70) _GUICtrlListView_InsertColumn($idListview, 3, 'Date time',100) _GUICtrlListView_InsertColumn($idListview, 4, "Path", 385) _GUICtrlListView_InsertColumn($idListview, 5, "size2", 0) _GUICtrlListView_JustifyColumn($idListview, $kSize,1) ; right align Local $idLbl = GUICtrlCreateLabel('',20,@DesktopHeight-135,@DesktopWidth/2-20,20) Local $btnRemove = GUICtrlCreateButton("Remove", 20,@DesktopHeight-110,60,30) Local $btnClose = GUICtrlCreateButton("Close", @DesktopWidth/2-100,@DesktopHeight-110,50,25) GUISetState(@SW_SHOW) _GUICtrlListView_SetExtendedListViewStyle($idListview,BitOR($LVS_EX_CHECKBOXES,$LVS_EX_GRIDLINES)) Local $nTotBytes=0 PopulateListView($idListview,$idLbl,@desktopdir, $nTotBytes) For $i = $kFnam To $kPath _GUICtrlListView_SetColumnWidth($idListview,$i,$LVSCW_AUTOSIZE) Next Local $t = AddThousandsSeparator(_GUICtrlListView_GetItemCount($idListview))&' files ('& _ AddThousandsSeparator($nTotBytes)&' bytes)' GUICtrlSetData($idLbl,$t) Local $nMsg While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE,$btnClose ExitLoop Case $listview $col = GUICtrlGetState($listview) If $col = 2 Then _GUICtrlListView_SimpleSort($listview, True, 5) #cs Case $btnRemove Local $bDel=False,$filspc If _MsgBoxEx($MB_YESNO + $MB_DEFBUTTON2 + $MB_ICONQUESTION,"","Remove checked files from backup?", _ 0,WinGetHandle('')) Then For $i = _GUICtrlListView_GetItemCount($idListview)-1 To 0 Step -1 If _GUICtrlListView_GetItemChecked($idListview,$i) Then $nTotBytes -= StringReplace(_GUICtrlListView_GetItemText($idListview,$i,$kSize),',','') $filspc = _GUICtrlListView_GetItemText($idListview,$i,$kPath) $filspc &= '\'&_GUICtrlListView_GetItemText($idListview,$i,$kFnam) $t = _GUICtrlListView_GetItemText($idListview,$i,$kExt) If $t<>'' Then $filspc &= '.'&$t EndIf ;~ FileDelete($filspc) ; for now!! $bDel = True _GUICtrlListView_DeleteItem($idListview,$i) EndIf Next If $bDel Then Local $q = _GUICtrlListView_GetItemCount($idListview) GUICtrlSetData($idLbl,AddThousandsSeparator($q)&' files ('&AddThousandsSeparator($nTotBytes)&' bytes)') If $q=0 Then GUICtrlSetState($btnRemove,$GUI_DISABLE) EndIf EndIf EndIf #ce EndSwitch WEnd GUIDelete($FormFF) EndFunc Func PopulateListView($idListview,$idLbl,$sPath, ByRef $nTotBytes) Local $sFnamExt,$sAtts,$sDirs='',$p,$sFnam,$sExt,$a1,$nSize,$t,$nItem Local $iSrch = FileFindFirstFile($sPath&'\*.*') If $iSrch=-1 Then Return EndIf While True $sFnamExt = FileFindNextFile($iSrch) If @error Then ExitLoop EndIf $sAtts = FileGetAttrib($sPath&'\'&$sFnamExt) If StringInStr($sAtts,'D') Then $sDirs &= '?'&$sPath&'\'&$sFnamExt Else $p = StringInStr($sFnamExt,'.',0,-1) ; last If $p=0 Then $sFnam = $sFnamExt $sExt = '' Else $sFnam = StringLeft($sFnamExt,$p-1) $sExt = StringTrimLeft($sFnamExt,$p) EndIf $nItem = _GUICtrlListView_GetItemCount($idListview) _GUICtrlListView_AddItem($idListview,$sFnam) _GUICtrlListView_AddSubItem($idListview,$nItem,$sExt,$kExt) $nSize = FileGetSize($sPath&'\'&$sFnamExt) _GUICtrlListView_AddSubItem($idListview,$nItem,AddThousandsSeparator($nsize),$kSize) $nTotBytes += $nSize $a1 = FileGetTime($sPath&'\'&$sFnamExt,$FT_MODIFIED,0) $t = $a1[0]&'-'&$a1[1]&'-'&$a1[2]&' '&$a1[3]&':'&$a1[4] _GUICtrlListView_AddSubItem($idListview,$nItem,$t,$kDateTime) _GUICtrlListView_AddSubItem($idListview,$nItem,$sPath,$kPath) _GUICtrlListView_AddSubItem($idListview,$nItem,$nsize,$kSize2) EndIf WEnd FileClose($iSrch) GUICtrlSetData($idLbl,AddThousandsSeparator($nTotBytes)&' bytes') #cs If $sDirs<>'' Then $sDirs = StringTrimLeft($sDirs,1) $a1 = StringSplit($sDirs,'?',0+2) ; char,0-based For $i = 0 To UBound($a1)-1 PopulateListView($idListview,$idLbl,$a1[$i], $nTotBytes) Next EndIf #ce EndFunc Func AddThousandsSeparator($n) Local $s = String($n) Local $sRet='' For $i = StringLen($s) To 1 Step -3 $sRet = StringMid($s,$i-2,3)&','&$sRet Next $sRet = StringTrimRight($sRet,1) If $i<>0 Then $sRet = StringLeft($s,3+$i)&$sRet EndIf Return $sRet EndFunc Link to comment Share on other sites More sharing options...
c.haslam Posted June 6, 2018 Author Share Posted June 6, 2018 (edited) Your idea is clever! I hadn't thought of it. I am not yet seeing how to get numeric sorting for the fifth column but string sorting for text columns. Edit1: OK: SimpleSort automatically sorts numerically if the data in a column is integer, else string-wise. BTW parameter 2 of SimpleSort is ByRef, so: If $col=2 Then $col = 5 EndIf _GUICtrlListView_SimpleSort($listview, $g_vSortSense,$col) Edit 2: $g_vSortSense will need to be a 1-d array, e.g. $a1SortSenses[6] to track sort sense of each column (except $kSize). I see that SimpleSort calls _ArraySort() to do the sorting. I had hoped that Windows would do it: would be much faster. Edited June 6, 2018 by c.haslam Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
c.haslam Posted June 7, 2018 Author Share Posted June 7, 2018 Many thanks for the help. Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now