cloudofxyz Posted October 11, 2013 Share Posted October 11, 2013 Hi everybody, I am new in this forum. Just would like to ask solution of my problem. Let say if I have made a GUI with Listview in it and I have a button to click which will sort the items of listview. Description of listview : It contains 4 columns.(name, gender, type, score) Let say the items are: Abc Male Adult 85 Asd Male Teenage 97 Cde Female Teenage 80 DEF Male Adult 90 Ghi Female Kid 50 Jkl Male Kid 70 Mno Female Teenage 60 Sorting will base on this: First, it will sort by gender (male first, followed by female) Next, it will sort by type (adult first, followed by teenage and last is kid) Next, it will sort by score. End result will be like this : DEF Male Adult 90 Abc Male Adult 85 Asd Male Teenage 97 Jkl Male Kid 70 Cde Female Teenage 80 Mno Female Teenage 60 Ghi Female Kid 50 I've Been trying to solve it using array, but still no result of my many hours trying. Any solution guys? Btw, hope u all could understand what I tried to achieve. Link to comment Share on other sites More sharing options...
jaberwacky Posted October 11, 2013 Share Posted October 11, 2013 Sort it in sections. Sort all of the items by gender. Then by type. Finally sort those by their scores. The males are put into their own array. Then put all of the adult males into their own array. Same for kids, etc. Then sort those by their scores. Do the same for females. At the end, combine all of the arrays into one. Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
cloudofxyz Posted October 11, 2013 Author Share Posted October 11, 2013 (edited) Thank you jaberwocky6669 for the fast reply.Sorry that I can not really understand your explanation. And also I forgot to mention something that user can input their data.Following is sample of the script :expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <EditConstants.au3> Global $msg, $mainGUI ,$hListView Global $edit1,$edit2,$edit3,$edit4 Global $addButton,$mainButton,$column1,$column2,$column3,$column4 Opt('MustDeclareVars', 1) Example1() Func Example1() Global $msg, $mainGUI ,$hListView Global $edit1,$edit2,$edit3,$edit4 Global $addButton,$mainButton,$column1,$column2,$column3,$column4 $mainGUI = GUICreate("Test LV auto sort",340,400) $addButton = GUICtrlCreateButton("ADD DATA", 100, 280, 140, 40) $mainButton = GUICtrlCreateButton("Sort It", 100, 340, 140, 40) $hListView = GUICtrlCreateListView("Name|Gender|Type|Score", 10, 12, 318, 230,BitOR($LVS_EDITLABELS,$LVS_SINGLESEL),BitOR($LVS_EX_FULLROWSELECT,$LVS_EX_GRIDLINES)) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT)) $edit1 = GUICtrlCreateEdit("",12,250,100,20, $ES_RIGHT) $edit2 = GUICtrlCreateEdit("",114,250,80,20, $ES_RIGHT) $edit3 = GUICtrlCreateEdit("",196,250,80,20, $ES_RIGHT) $edit4 = GUICtrlCreateEdit("",278,250,48,20, $ES_RIGHT) $column1 = _GUICtrlListView_SetColumn($hListView ,0,"Name",100,2) $column2 = _GUICtrlListView_SetColumn($hListView ,1,"Gender",80,2) $column3 = _GUICtrlListView_SetColumn($hListView ,2,"Type",80,2) $column4 = _GUICtrlListView_SetColumn($hListView ,3,"Score",50,2) GUICtrlCreateListViewItem("ABC|Male|Adult|85", $hListView) GUICtrlCreateListViewItem("ASD|Male|Teenage|97", $hListView) GUICtrlCreateListViewItem("CDE|Female|Teenage|80", $hListView) GUICtrlCreateListViewItem("DEF|Male|Adult|90", $hListView) GUICtrlCreateListViewItem("GHI|Female|Kid|50", $hListView) GUICtrlCreateListViewItem("JKL|Male|Kid|70", $hListView) GUICtrlCreateListViewItem("MNO|Female|Teenage|60", $hListView) GUISetState() While 1 $msg = GUIGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case $msg = $addButton Call("adddata") Case $msg = $mainButton Call("sort") EndSelect WEnd GUIDelete() EndFunc Func adddata() GUICtrlCreateListViewItem(GUICtrlRead($edit1) &"|" &GUICtrlRead($edit2) &"|" &GUICtrlRead($edit3) &"|" &GUICtrlRead($edit4), $hListView) EndFunc Func sort() ;Still confusion in here EndFuncNow, a problem will occurs if some users entered another type of data:Example :User 1 entered :JFK | Unknown | Adult | 85Hhh | Unknown |Teenage | 86User 2 entered :Ggg | Male | No data | 90Jjjj | male | No data | 50Lkm | Female | No data | 60User 3 entered :Asz | NIL | kid | 70Jjjj | NIL | Adult | 50Fjjj | NIL | Adult | 60User 4 entered :Lkm | Male | No history | 40Ers |Male |No history | 89Users ARE ALLOWED to enter any type of data, except the score is number.So that the final result is like this:Ggg | Male | No data | 90Jjjj | male | No data | 50Lkm | Male | No history | 89Ers | Male | No history | 40Lkm | Female | No data | 60Fjjj | NIL | Adult | 60Jjjj | NIL | Adult | 50Asz | NIL | kid | 70JFK | Unknown | Adult | 85Hhh | Unknown |Teenage | 86Which means, I could not prepare an array for the gender nor type as I don't know what an user might inputed (NIL / no history / unknown / N/A / etc...) or I COULD ?If only has someting like this :_GUICtrlListView_SimpleSort($hListView, $B_DESCENDING, #column index, #starting subitem index, #end subitem index)Many thanks in advance Edited October 11, 2013 by Melba23 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 11, 2013 Moderators Share Posted October 11, 2013 cloudofxyz,When you post code please use Code tags - see here how to do it. Then you get a scrolling box and syntax colouring as you can see above now I have added the tags. Next, rather than let your users enter anything at all, why not limit their choices for certain elements by using a combo? Than you will have a defined set of values that you will find in the "Gender" and "Age group" elements which will greatly simplify matters. As to sorting - I would pull all the data from the ListView into an array. You can then do the sorting in the array (_ArraySort allows you to sort on subitems and in a specific range) or split the array as required, sort each section and then recreate the main array for reloading into the ListView. I will see if I can come up with something later today to show the principle. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
cloudofxyz Posted October 11, 2013 Author Share Posted October 11, 2013 Thanks melba23 for the tips of using of code tags. And help me to code tagged it for me A limitation would be great, but I prefer users able to enter data when they not sure yet what the complete data is, but they've known partial of data. Eg. Not sure either male or female, but for sure it is an adult with 80 points. After reading carefully the suggestion from jaberwocky6669 and your explanation, Now I understand what is solution using those arrays. Thanks for both of you. Btw, may I know which command can be used for reloading that main (2D) array back to Listview? ( sorry , seldom using array ) Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 11, 2013 Moderators Share Posted October 11, 2013 (edited) cloudofxyz,You can have an "Unknown" in a combo - I will look at the data insertion aspect later. Here is some code to sort the data as you wish - the _ArrayDisplay dialogs show how it is progressing as is runs:expandcollapse popup#include <Array.au3> Global $aData[][] = [ _ ["Ggg", "Male", "Teenage", 90], _ ["Jjjj", "Male", "Unknown", 50], _ ["Lkm", "Male", "Adult", 89], _ ["Ers", "Male", "Unknown", 55], _ ["Lkm", "Female", "Unknown", 60], _ ["Fjjj", "Unknown", "Kid", 60], _ ["Jppp", "Unknown", "Adult", 50], _ ["Asz", "Female", "Kid", 70], _ ["JFK", "Unknown", "Adult", 85], _ ["Hhh", "Female", "Teenage", 86]] $iTopIndex = UBound($aData) - 1 ; First change the element titles to get the correct sort order For $i = 0 To UBound($aData) - 1 ; Gender If $aData[$i][1] = "Male" Then $aData[$i][1] = "1-Male" ElseIf $aData[$i][1] = "Female" Then $aData[$i][1] = "2-Female" Else $aData[$i][1] = "3-Unknown" EndIf ; Age If $aData[$i][2] = "Adult" Then $aData[$i][2] = "1-Adult" ElseIf $aData[$i][2] = "Teenage" Then $aData[$i][2] = "2-Teenage" ElseIf $aData[$i][2] = "Kid" Then $aData[$i][2] = "3-Kid" Else $aData[$i][2] = "4-Unknown" EndIf Next ; First sort on gender _ArraySort($aData, 0, 0, 0, 1) _ArrayDisplay($aData, "Gender") ; Just for display ; Now look for 3 gender options and sort the 3 sections on age $iFemale_Start = _ArrayScan(0, $iTopIndex, "1-Male") If $iFemale_Start > 1 Then ; Sorting 0 to 0 means the whole array which we do not want _ArraySort($aData, 0, 0, $iFemale_Start - 1, 2) EndIf $iUnknown_Start = _ArrayScan($iFemale_Start, $iTopIndex, "2-Female") If $iUnknown_Start > 1 Then _ArraySort($aData, 0, $iFemale_Start, $iUnknown_Start - 1, 2) EndIf _ArraySort($aData, 0, $iUnknown_Start, 0, 2) _ArrayDisplay($aData, "Age") ; Just for display ; Now we sort on the scores $iMale_Teen_Start = _ArrayScan(0, $iTopIndex, "1-Male", "1-Adult") If $iMale_Teen_Start > 1 Then _ArraySort($aData, 1, 0, $iMale_Teen_Start - 1, 3) EndIf $iMale_Kid_Start = _ArrayScan($iMale_Teen_Start, $iTopIndex, "1-Male", "2-Teenage") If $iMale_Kid_Start > 1 Then _ArraySort($aData, 1, $iMale_Teen_Start, $iMale_Kid_Start - 1, 3) EndIf $iMale_Unknown_Start = _ArrayScan($iMale_Kid_Start, $iTopIndex, "1-Male", "3-Kid") If $iMale_Unknown_Start > 1 Then _ArraySort($aData, 1, $iMale_Kid_Start, $iMale_Unknown_Start - 1, 3) EndIf $iFemale_Adult_Start = _ArrayScan($iMale_Unknown_Start, $iTopIndex, "1-Male", "4-Unknown") If $iFemale_Adult_Start > 1 Then _ArraySort($aData, 1, $iMale_Unknown_Start, $iFemale_Adult_Start - 1, 3) EndIf _ArrayDisplay($aData, "Males fully sorted") ; Just for display $iFemale_Teen_Start = _ArrayScan($iFemale_Adult_Start, $iTopIndex, "2-Female", "1-Adult") If $iFemale_Teen_Start > 1 Then _ArraySort($aData, 1, $iFemale_Adult_Start, $iFemale_Teen_Start - 1, 3) EndIf $iFemale_Kid_Start = _ArrayScan($iFemale_Teen_Start, $iTopIndex, "2-Female", "2-Teenage") If $iFemale_Kid_Start > 1 Then _ArraySort($aData, 1, $iFemale_Teen_Start, $iFemale_Kid_Start - 1, 3) EndIf $iFemale_Unknown_Start = _ArrayScan($iFemale_Kid_Start, $iTopIndex, "2-Female", "3-Kid") If $iFemale_Unknown_Start > 1 Then _ArraySort($aData, 1, $iFemale_Kid_Start, $iFemale_Unknown_Start - 1, 3) EndIf $iUnknown_Adult_Start = _ArrayScan($iFemale_Unknown_Start, $iTopIndex, "2-Female", "4-Unknown") If $iUnknown_Adult_Start > 1 Then _ArraySort($aData, 1, $iFemale_Unknown_Start, $iUnknown_Adult_Start - 1, 3) EndIf _ArrayDisplay($aData, "Females fully sorted") ; Just for display $iUnknown_Teen_Start = _ArrayScan($iUnknown_Adult_Start, $iTopIndex, "3-Unknown", "1-Adult") If $iUnknown_Teen_Start > 1 Then _ArraySort($aData, 1, $iUnknown_Adult_Start, $iUnknown_Teen_Start - 1, 3) EndIf $iUnknown_Kid_Start = _ArrayScan($iUnknown_Teen_Start, $iTopIndex, "3-Unknown", "2-Teenage") If $iUnknown_Kid_Start > 1 Then _ArraySort($aData, 1, $iUnknown_Teen_Start, $iUnknown_Kid_Start - 1, 3) EndIf $iUnknown_Unknown_Start = _ArrayScan($iUnknown_Kid_Start, $iTopIndex, "3-Unknown", "3-Kid") If $iUnknown_Unknown_Start > 1 Then _ArraySort($aData, 1, $iUnknown_Kid_Start, $iUnknown_Unknown_Start - 1, 3) EndIf _ArraySort($aData, 1, $iUnknown_Unknown_Start, 0, 3) _ArrayDisplay($aData, "Unknowns fully sorted") ; Just for display ; Now reset the element titles For $i = 0 To UBound($aData) - 1 ; Gender If $aData[$i][1] = "1-Male" Then $aData[$i][1] = "Male" ElseIf $aData[$i][1] = "2-Female" Then $aData[$i][1] = "Female" Else $aData[$i][1] = "Unknown" EndIf ; Age If $aData[$i][2] = "1-Adult" Then $aData[$i][2] = "Adult" ElseIf $aData[$i][2] = "2-Teenage" Then $aData[$i][2] = "Teenage" ElseIf $aData[$i][2] = "3-Kid" Then $aData[$i][2] = "Kid" Else $aData[$i][2] = "Unknown" EndIf Next _ArrayDisplay($aData, "Final sorted array") Func _ArrayScan($iStartIndex, $iEndIndex, $sGender, $sAge = "") If $sAge Then ConsoleWrite($sGender & " - " & $sAge & @CRLF) For $i = $iStartIndex To $iEndIndex If $sAge Then If Not ($aData[$i][1] = $sGender And $aData[$i][2] = $sAge) Then ExitLoop Else If $aData[$i][1] <> $sGender Then ExitLoop EndIf Next Return $i EndFuncI hope the code is clear, but please do ask if you have any questions. M23 Edited October 11, 2013 by Melba23 Added function Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
cloudofxyz Posted October 11, 2013 Author Share Posted October 11, 2013 (edited) Thanks Melba23. Btw, what is udf for _ArrayScan ? And also how about command to load it back to the Listview? Edited October 11, 2013 by cloudofxyz Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 11, 2013 Moderators Share Posted October 11, 2013 (edited) cloudofxyz,Sorry, I missed the _ArrayScan function when I pasted the code - it is there now. If you look at the GUILIstViewEx UDF in my sig it has several functions for getting the data from ListViews and reloading them. Feel free to modify any of that code to fit your specific case. M23Edit:And here is my suggestion for the user input section of your code - now you can only have the specific values used in the sort function: $edit1 = GUICtrlCreateEdit("", 12, 250, 100, 20, $ES_RIGHT) $edit2 = GUICtrlCreateCombo("", 114, 250, 80, 20) GUICtrlSetData($edit2, "Male|Female|Unknown", "Unknown") $edit3 = GUICtrlCreateCombo("", 196, 250, 80, 20) GUICtrlSetData($edit3, "Adult|Teenage|Kid|Unknown", "Unknown") $edit4 = GUICtrlCreateEdit("", 278, 250, 48, 20, $ES_RIGHT) Edited October 11, 2013 by Melba23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
cloudofxyz Posted October 12, 2013 Author Share Posted October 12, 2013 Melba23, The array sorting is tried and works perfectly. I've just downloaded your UDF and read how to use it. However, think it would take me a while before I figure it out how to reload it to Listview. Anyway, I will post it once I figured it out. Thanks for your time. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 12, 2013 Moderators Share Posted October 12, 2013 cloudofxyz,Excellent! I am thinking about producing a generic sort function to do the same thing - you feed it an array and the details of the sort criteria and it returns a sorted array. I will let you know how I get on. And please ask if you have any questions about the read and reload functions within the UDF. Remember that you do not need all the code - just enough to do the job. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
cloudofxyz Posted October 13, 2013 Author Share Posted October 13, 2013 Melba23, I tried to use your udf with the function of _GUIListviewEx_ReWriteLV, but since there is no example of using it (I can't find it in example 1,example 2, example 3, and example 4), I still having difficulties in implementing it. Sorry, I am quite poor in this array thing. If you have free time, could you please give me an example of using it? Thank you. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 13, 2013 Moderators Share Posted October 13, 2013 cloudofxyz,I said I would look into a stand-alone function to sort arrays on several levels - and here it is:expandcollapse popup#include <Array.au3> Global $aArray[][] = [ _ ["Ggg", "Male", "Teenage", 90], _ ["Jjjj", "Male", "Unknown", 50], _ ["Lkm", "Male", "Adult", 89], _ ["Ers", "Male", "Unknown", 55], _ ["Lkm", "Female", "Unknown", 60], _ ["Fjjj", "Unknown", "Kid", 60], _ ["Jppp", "Unknown", "Adult", 50], _ ["Asz", "Female", "Kid", 70], _ ["JFK", "Unknown", "Adult", 85], _ ["Hhh", "Female", "Teenage", 86]] ; Sort requirement: ; Column then either 0/1 (Ascending/Descending) or string with required order (anything else comes after these) Global $aSortData[3][2] = [ _ [1, "Male,Female"], _ [2, "Adult,Teenage,Kid"], _ [3, 1]] _ArrayDisplay($aArray, "Unsorted") _ArrayMultiSort($aArray, $aSortData) ; Sort the array as required by the $aSortData parameters _ArrayDisplay($aArray, "Sorted") ; ================================================================================== Func _ArrayMultiSort(ByRef $aArray, $aSortData, $iStart = 0, $iEnd = 0) ; Set default End value If $iEnd = 0 Then $iEnd = UBound($aArray) - 1 EndIf ; Sort first column __AMS_SortChunk($aArray, $aSortData, 0, $aSortData[0][0], $iStart, $iEnd) ; Now sort other columns For $iSortData_Row = 1 To UBound($aSortData) - 1 ; Determine column to sort $iCurrCol = $aSortData[$iSortData_Row][0] ; Create arrays to hold data from previous columns Local $aBaseValue[$iSortData_Row] ; Set base values For $i = 0 To $iSortData_Row - 1 $aBaseValue[$i] = $aArray[$iStart][$aSortData[$i][0]] Next ; Set start of this chunk $iChunk_Start = $iStart ; Now work down through array For $iRow = $iStart + 1 To $iEnd ; Match each column For $k = 0 To $iSortData_Row - 1 $iMatchCol = $aSortData[$k][0] ; See if value in each has changed If $aArray[$iRow][$iMatchCol] <> $aBaseValue[$k] Then ; If so and row has advanced If $iChunk_Start < $iRow -1 Then ; Sort this chunk __AMS_SortChunk($aArray, $aSortData, $iSortData_Row, $iCurrCol, $iChunk_Start, $iRow - 1) EndIf ; Set new base value $aBaseValue[$k] = $aArray[$iRow][$iMatchCol] ; Set new chunk start $iChunk_Start = $iRow EndIf Next Next ; Sort final section If $iChunk_Start < $iRow -1 Then __AMS_SortChunk($aArray, $aSortData, $iSortData_Row, $iCurrCol, $iChunk_Start, $iRow - 1) EndIf Next EndFunc Func __AMS_SortChunk(ByRef $aArray, $aSortData, $iRow, $iColumn, $iChunkStart, $iChunkEnd) ; Set default sort direction $iSortDirn = 0 ; Need to prefix elements? If IsString($aSortData[$iRow][1]) Then ; Split elements $aSortOrder = StringSplit($aSortData[$iRow][1], ",") ; Add prefix to each element For $i = $iChunkStart To $iChunkEnd For $j = 1 To $aSortOrder[0] If $aArray[$i][$iColumn] = $aSortOrder[$j] Then $aArray[$i][$iColumn] = StringFormat("%02i-", $j) & $aArray[$i][$iColumn] ExitLoop EndIf Next ; Deal with anything that does not match If $j > $aSortOrder[0] Then $aArray[$i][$iColumn] = StringFormat("%02i-", $j) & $aArray[$i][$iColumn] EndIf Next Else ; Set required sort direction if no list $iSortDirn = $aSortData[$iRow][1] EndIf ; Sort the chunk _ArraySort($aArray, $iSortDirn, $iChunkStart, $iChunkEnd, $iColumn) ; Remove any prefixes If IsString($aSortData[$iRow][1]) Then For $i = $iChunkStart To $iChunkEnd $aArray[$i][$iColumn] = StringTrimLeft($aArray[$i][$iColumn], 3) Next EndIf EndFuncI will try and produce an example of getting the data from a ListView and reloading it now. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Moderators Solution Melba23 Posted October 13, 2013 Moderators Solution Share Posted October 13, 2013 cloudofxyz,And here it is - a fully working script (for me at least): expandcollapse popup#include <GUIConstantsEx.au3> #include <Constants.au3> #include <GuiListView.au3> #include <Array.au3> #include <EditConstants.au3> Global $aArray[][] = [ _ ["Ggg", "Male", "Teenage", 90], _ ["Jjjj", "Male", "Unknown", 50], _ ["Lkm", "Male", "Adult", 89], _ ["Ers", "Male", "Unknown", 55], _ ["Lkm", "Female", "Unknown", 60], _ ["Fjjj", "Unknown", "Kid", 60], _ ["Jppp", "Unknown", "Adult", 50], _ ["Asz", "Female", "Kid", 70], _ ["JFK", "Unknown", "Adult", 85], _ ["Hhh", "Female", "Teenage", 86]] ; Sort requirement: ; Column then either 0/1 (Ascending/Descending) or string with required order (anything else comes after these) Global $aSortData[3][2] = [ _ [1, "Male,Female"], _ [2, "Adult,Teenage,Kid"], _ [3, 1]] ; Create GUI $hGUI = GUICreate("Test", 500, 500) GUISetBkColor(0xC4C4C4) $cLV = GUICtrlCreateListView("Name|Gender|Type|Score", 10, 10, 480, 400, $LVS_SINGLESEL, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) For $i = 0 To 3 _GUICtrlListView_SetColumnWidth($cLV, $i, 115) Next _LoadArrayToLV($cLV, $aArray) $cEdit_Name = GUICtrlCreateEdit("", 10, 420, 110, 20, $ES_RIGHT) $cCombo_Gender = GUICtrlCreateCombo("", 125, 420, 110, 20) GUICtrlSetData($cCombo_Gender, "Male|Female|Unknown", "Unknown") $cCombo_Type = GUICtrlCreateCombo("", 240, 420, 110, 20) GUICtrlSetData($cCombo_Type, "Adult|Teenage|Kid|Unknown", "Unknown") $cEdit_Score = GUICtrlCreateEdit("", 355, 420, 110, 20, BitOr($ES_RIGHT, $ES_NUMBER)) $cAddData = GUICtrlCreateButton("Add", 10, 450, 80, 30) $cSortData = GUICtrlCreateButton("Sort", 410, 450, 80, 30) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $cAddData If GUICtrlRead($cEdit_Name) = "" Or GUICtrlRead($cEdit_Score) = "" Then MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, "Error", "Please complete all fields") Else $sData = GUICtrlRead($cEdit_Name) & "|" & GUICtrlRead($cCombo_Gender) & "|" & GUICtrlRead($cCombo_Type) & "|" & GUICtrlRead($cEdit_Score) GUICtrlCreateListViewItem($sData, $cLV) EndIf Case $cSortData $aArray = _ReadLVToArray($cLV) _ArrayMultiSort($aArray, $aSortData) _LoadArrayToLV($cLV, $aArray) EndSwitch WEnd Func _ReadLVToArray($cLV) Local $aLVArray = "", $aRow ; Get the ListView handle Local $hLV = GUICtrlGetHandle($cLV) ; Get ListView row count Local $iRows = _GUICtrlListView_GetItemCount($hLV) ; Get ListView column count Local $iCols = _GUICtrlListView_GetColumnCount($hLV) ; Create 2D array to hold ListView content Local $aLVArray[$iRows][$iCols] ; Read ListView content into array For $i = 0 To $iRows - 1 ; Read the row content $aRow = _GUICtrlListView_GetItemTextArray($hLV, $i) For $j = 1 To $aRow[0] ; Add to the ListView content array $aLVArray[$i][$j - 1] = $aRow[$j] Next Next ; Return array or empty string Return $aLVArray EndFunc Func _LoadArrayToLV($cLV, $aArray) Local $sLine ; Get the ListView handle Local $hLV = GUICtrlGetHandle($cLV) ; Delete existing items For $i = _GUICtrlListView_GetItemCount($hLV) - 1 To 0 Step -1 GUICtrlDelete(_GUICtrlListView_GetItemParam($hLV, $i)) Next ; Refill items from array For $i = 0 To UBound($aArray) - 1 ; Create item text $sLine = "" For $j = 0 To UBound($aArray, 2) - 1 $sLine &= $aArray[$i][$j] & "|" Next ; Create item GUICtrlCreateListViewItem(StringTrimRight($sLine, 1), $cLV) Next EndFunc Func _ArrayMultiSort(ByRef $aArray, $aSortData, $iStart = 0, $iEnd = 0) ; Set default End value If $iEnd = 0 Then $iEnd = UBound($aArray) - 1 EndIf ; Sort first column __AMS_SortChunk($aArray, $aSortData, 0, $aSortData[0][0], $iStart, $iEnd) ; Now sort other columns For $iSortData_Row = 1 To UBound($aSortData) - 1 ; Determine column to sort $iCurrCol = $aSortData[$iSortData_Row][0] ; Create arrays to hold data from previous columns Local $aBaseValue[$iSortData_Row] ; Set base values For $i = 0 To $iSortData_Row - 1 $aBaseValue[$i] = $aArray[$iStart][$aSortData[$i][0]] Next ; Set start of this chunk $iChunk_Start = $iStart ; Now work down through array For $iRow = $iStart + 1 To $iEnd ; Match each column For $k = 0 To $iSortData_Row - 1 $iMatchCol = $aSortData[$k][0] ; See if value in each has changed If $aArray[$iRow][$iMatchCol] <> $aBaseValue[$k] Then ; If so and row has advanced If $iChunk_Start < $iRow -1 Then ; Sort this chunk __AMS_SortChunk($aArray, $aSortData, $iSortData_Row, $iCurrCol, $iChunk_Start, $iRow - 1) EndIf ; Set new base value $aBaseValue[$k] = $aArray[$iRow][$iMatchCol] ; Set new chunk start $iChunk_Start = $iRow EndIf Next Next ; Sort final section If $iChunk_Start < $iRow -1 Then __AMS_SortChunk($aArray, $aSortData, $iSortData_Row, $iCurrCol, $iChunk_Start, $iRow - 1) EndIf Next EndFunc Func __AMS_SortChunk(ByRef $aArray, $aSortData, $iRow, $iColumn, $iChunkStart, $iChunkEnd) ; Set default sort direction $iSortDirn = 0 ; Need to prefix elements? If IsString($aSortData[$iRow][1]) Then ; Split elements $aSortOrder = StringSplit($aSortData[$iRow][1], ",") ; Add prefix to each element For $i = $iChunkStart To $iChunkEnd For $j = 1 To $aSortOrder[0] If $aArray[$i][$iColumn] = $aSortOrder[$j] Then $aArray[$i][$iColumn] = StringFormat("%02i-", $j) & $aArray[$i][$iColumn] ExitLoop EndIf Next ; Deal with anything that does not match If $j > $aSortOrder[0] Then $aArray[$i][$iColumn] = StringFormat("%02i-", $j) & $aArray[$i][$iColumn] EndIf Next Else ; Set required sort direction if no list $iSortDirn = $aSortData[$iRow][1] EndIf ; Sort the chunk _ArraySort($aArray, $iSortDirn, $iChunkStart, $iChunkEnd, $iColumn) ; Remove any prefixes If IsString($aSortData[$iRow][1]) Then For $i = $iChunkStart To $iChunkEnd $aArray[$i][$iColumn] = StringTrimLeft($aArray[$i][$iColumn], 3) Next EndIf EndFuncPlease ask if you have any questions. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
cloudofxyz Posted October 14, 2013 Author Share Posted October 14, 2013 (edited) Melba32, Great Job ! I really like that stand alone function to sort the arrays on several levels Yesterday, I also spend my several hours to figure out the code to load the array into the listview. I just cannot believe myself that i've missed 4 lines of code only to load it back to listview. They are :_GUICtrlListView_DeleteAllItems($hListView) For $i = 0 To $totaldata-1 GUICtrlCreateListViewItem($aData[$i][0] &"|" &$aData[$i][1] &"|" &$aData[$i][2] &"|" &$aData[$i][3], $hListView) Next However, I have no internet connection to reply to this topic. And now, I just used the public PC for internet. Soon as I have the Internet connection back, I will re-post the fully working script of my version also. So..this topic is SOLVED. Big Thanks to Melba32. Edit : As I promised. This is my version of fully working script :expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiListView.au3> #Include <string.au3> #include <EditConstants.au3> #include <Array.au3> Global $msg, $mainGUI ,$hListView Global $edit1,$edit2,$edit3,$edit4 Global $addButton,$mainButton,$column1,$column2,$column3,$column4 Global $stringobtained ,$array1,$totaldata Global $iTopIndex,$iFemale_Start,$iUnknown_Start,$iMale_Teen_Start,$iMale_Kid_Start,$iMale_Unknown_Start,$iFemale_Adult_Start,$iFemale_Teen_Start Global $iFemale_Kid_Start,$iFemale_Unknown_Start,$iUnknown_Adult_Start,$iUnknown_Teen_Start,$iUnknown_Kid_Start,$iUnknown_Unknown_Start,$aData Opt('MustDeclareVars', 1) Example1() Func Example1() $mainGUI = GUICreate("Test LV auto sort",340,400) $addButton = GUICtrlCreateButton("ADD DATA", 100, 280, 140, 40) $mainButton = GUICtrlCreateButton("Sort It", 100, 340, 140, 40) $hListView = GUICtrlCreateListView("Name|Gender|Type|Score", 10, 12, 318, 230,BitOR($LVS_EDITLABELS,$LVS_SINGLESEL),BitOR($LVS_EX_FULLROWSELECT,$LVS_EX_GRIDLINES)) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT)) $edit1 = GUICtrlCreateEdit("",12,250,100,20, $ES_RIGHT) $edit2 = GUICtrlCreateCombo("",114,250,80,20, $ES_RIGHT) GUICtrlSetData(-1, "Male|Female|Unknown","Unknown") $edit3 = GUICtrlCreateCombo("",196,250,80,20, $ES_RIGHT) GUICtrlSetData(-1, "Adult|Teenage|Kid|Unknown","Unknown") $edit4 = GUICtrlCreateEdit("",278,250,48,20, $ES_RIGHT) $column1 = _GUICtrlListView_SetColumn($hListView ,0,"Name",100,2) $column2 = _GUICtrlListView_SetColumn($hListView ,1,"Gender",80,2) $column3 = _GUICtrlListView_SetColumn($hListView ,2,"Type",80,2) $column4 = _GUICtrlListView_SetColumn($hListView ,3,"Score",50,2) GUICtrlCreateListViewItem("Ggg|Male|Teenage|90", $hListView) GUICtrlCreateListViewItem("Jjjj|Male|Unknown|50", $hListView) GUICtrlCreateListViewItem("Lkm|Male|Adult|89", $hListView) GUICtrlCreateListViewItem("Ers|Male|Unknown|55", $hListView) GUICtrlCreateListViewItem("Lkm|Female|Unknown|60", $hListView) GUICtrlCreateListViewItem("Fjjj|Unknown|Kid|60", $hListView) GUICtrlCreateListViewItem("Jppp|Unknown|Adult|50", $hListView) GUICtrlCreateListViewItem("Asz|Female|Kid|70", $hListView) GUICtrlCreateListViewItem("JFK|Unknown|Adult|85", $hListView) GUICtrlCreateListViewItem("Hhh|Female|Teenage|86", $hListView) GUISetState() While 1 $msg = GUIGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case $msg = $addButton Call("adddata") Case $msg = $mainButton Call("sort") EndSelect WEnd GUIDelete() EndFunc Func adddata() GUICtrlCreateListViewItem(GUICtrlRead($edit1) &"|" &GUICtrlRead($edit2) &"|" &GUICtrlRead($edit3) &"|" &GUICtrlRead($edit4), $hListView) EndFunc Func sort() Dim $aData[1][4] $totaldata = _GUICtrlListView_GetItemCount($hListView) For $j= 0 To $totaldata-1 $stringobtained = _GUICtrlListView_GetItemTextString($hListView, $j) $array1 = _StringExplode($stringobtained, "|", 0) ReDim $aData[UBound($aData) +1][4] $aData[UBound($aData) -1][0] = $array1[0] $aData[UBound($aData) -1][1] = $array1[1] $aData[UBound($aData) -1][2] = $array1[2] $aData[UBound($aData) -1][3] = $array1[3] + 0 ; 0 is to validate as number Next _ArrayDelete($aData, 0) $iTopIndex = UBound($aData) - 1 ; First change the element titles to get the correct sort order For $i = 0 To UBound($aData) - 1 ; Gender If $aData[$i][1] = "Male" Then $aData[$i][1] = "1-Male" ElseIf $aData[$i][1] = "Female" Then $aData[$i][1] = "2-Female" Else $aData[$i][1] = "3-Unknown" EndIf ; Age If $aData[$i][2] = "Adult" Then $aData[$i][2] = "1-Adult" ElseIf $aData[$i][2] = "Teenage" Then $aData[$i][2] = "2-Teenage" ElseIf $aData[$i][2] = "Kid" Then $aData[$i][2] = "3-Kid" Else $aData[$i][2] = "4-Unknown" EndIf Next ; First sort on gender _ArraySort($aData, 0, 0, 0, 1) ;~ _ArrayDisplay($aData, "Gender Sorted") ; Just for display ; Now look for 3 gender options and sort the 3 sections on age $iFemale_Start = _ArrayScan(0, $iTopIndex, "1-Male") If $iFemale_Start > 1 Then ; Sorting 0 to 0 means the whole array which we do not want _ArraySort($aData, 0, 0, $iFemale_Start - 1, 2) EndIf $iUnknown_Start = _ArrayScan($iFemale_Start, $iTopIndex, "2-Female") If $iUnknown_Start > 1 Then _ArraySort($aData, 0, $iFemale_Start, $iUnknown_Start - 1, 2) EndIf _ArraySort($aData, 0, $iUnknown_Start, 0, 2) ;~ _ArrayDisplay($aData, "Age Sorted") ; Just for display ; Now we sort on the scores $iMale_Teen_Start = _ArrayScan(0, $iTopIndex, "1-Male", "1-Adult") If $iMale_Teen_Start > 1 Then _ArraySort($aData, 1, 0, $iMale_Teen_Start - 1, 3) EndIf $iMale_Kid_Start = _ArrayScan($iMale_Teen_Start, $iTopIndex, "1-Male", "2-Teenage") If $iMale_Kid_Start > 1 Then _ArraySort($aData, 1, $iMale_Teen_Start, $iMale_Kid_Start - 1, 3) EndIf $iMale_Unknown_Start = _ArrayScan($iMale_Kid_Start, $iTopIndex, "1-Male", "3-Kid") If $iMale_Unknown_Start > 1 Then _ArraySort($aData, 1, $iMale_Kid_Start, $iMale_Unknown_Start - 1, 3) EndIf $iFemale_Adult_Start = _ArrayScan($iMale_Unknown_Start, $iTopIndex, "1-Male", "4-Unknown") If $iFemale_Adult_Start > 1 Then _ArraySort($aData, 1, $iMale_Unknown_Start, $iFemale_Adult_Start - 1, 3) EndIf ;~ _ArrayDisplay($aData, "Males fully sorted") ; Just for display $iFemale_Teen_Start = _ArrayScan($iFemale_Adult_Start, $iTopIndex, "2-Female", "1-Adult") If $iFemale_Teen_Start > 1 Then _ArraySort($aData, 1, $iFemale_Adult_Start, $iFemale_Teen_Start - 1, 3) EndIf $iFemale_Kid_Start = _ArrayScan($iFemale_Teen_Start, $iTopIndex, "2-Female", "2-Teenage") If $iFemale_Kid_Start > 1 Then _ArraySort($aData, 1, $iFemale_Teen_Start, $iFemale_Kid_Start - 1, 3) EndIf $iFemale_Unknown_Start = _ArrayScan($iFemale_Kid_Start, $iTopIndex, "2-Female", "3-Kid") If $iFemale_Unknown_Start > 1 Then _ArraySort($aData, 1, $iFemale_Kid_Start, $iFemale_Unknown_Start - 1, 3) EndIf $iUnknown_Adult_Start = _ArrayScan($iFemale_Unknown_Start, $iTopIndex, "2-Female", "4-Unknown") If $iUnknown_Adult_Start > 1 Then _ArraySort($aData, 1, $iFemale_Unknown_Start, $iUnknown_Adult_Start - 1, 3) EndIf ;~ _ArrayDisplay($aData, "Females fully sorted") ; Just for display $iUnknown_Teen_Start = _ArrayScan($iUnknown_Adult_Start, $iTopIndex, "3-Unknown", "1-Adult") If $iUnknown_Teen_Start > 1 Then _ArraySort($aData, 1, $iUnknown_Adult_Start, $iUnknown_Teen_Start - 1, 3) EndIf $iUnknown_Kid_Start = _ArrayScan($iUnknown_Teen_Start, $iTopIndex, "3-Unknown", "2-Teenage") If $iUnknown_Kid_Start > 1 Then _ArraySort($aData, 1, $iUnknown_Teen_Start, $iUnknown_Kid_Start - 1, 3) EndIf $iUnknown_Unknown_Start = _ArrayScan($iUnknown_Kid_Start, $iTopIndex, "3-Unknown", "3-Kid") If $iUnknown_Unknown_Start > 1 Then _ArraySort($aData, 1, $iUnknown_Kid_Start, $iUnknown_Unknown_Start - 1, 3) EndIf _ArraySort($aData, 1, $iUnknown_Unknown_Start, 0, 3) ;~ _ArrayDisplay($aData, "Unknowns fully sorted") ; Just for display ; Now reset the element titles For $i = 0 To UBound($aData) - 1 ; Gender If $aData[$i][1] = "1-Male" Then $aData[$i][1] = "Male" ElseIf $aData[$i][1] = "2-Female" Then $aData[$i][1] = "Female" Else $aData[$i][1] = "Unknown" EndIf ; Age If $aData[$i][2] = "1-Adult" Then $aData[$i][2] = "Adult" ElseIf $aData[$i][2] = "2-Teenage" Then $aData[$i][2] = "Teenage" ElseIf $aData[$i][2] = "3-Kid" Then $aData[$i][2] = "Kid" Else $aData[$i][2] = "Unknown" EndIf Next ;~ _ArrayDisplay($aData, "Final sorted array") ; Just for display _GUICtrlListView_DeleteAllItems($hListView) For $i = 0 To $totaldata-1 GUICtrlCreateListViewItem($aData[$i][0] &"|" &$aData[$i][1] &"|" &$aData[$i][2] &"|" &$aData[$i][3], $hListView) Next EndFunc Func _ArrayScan($iStartIndex, $iEndIndex, $sGender, $sAge = "") ;~ If $sAge Then ConsoleWrite($sGender & " - " & $sAge & @CRLF) ;for console writing only For $i = $iStartIndex To $iEndIndex If $sAge Then If Not ($aData[$i][1] = $sGender And $aData[$i][2] = $sAge) Then ExitLoop Else If $aData[$i][1] <> $sGender Then ExitLoop EndIf Next Return $i EndFunc Edited October 16, 2013 by cloudofxyz 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