listview kan ikke sortere \"numerisk\" af sig selv, den sorterer \"alfabetisk\" og i \"alfabetisk\" kommer 2 efter 1 derfor kommer 20001 efter 1944 nemmeste løsning er at du laver foranstillede nuller så alle tal har samme længde.
Det kunne måske løses ved at du indsætter værdien i som index\'et (kan det lade sig gøre ?) og så sætter sortkey til >0
SortKey Returns or sets a value that determines how the ListItem objects in a ListView control are sorted.
The parts of the SortKey property syntax are described in the following table.
Part Description object An object expression that evaluates to a ListView control. integer An integer specifying the sort Key, as described in Settings.
Settings The SortKey property settings are described in the following table.
Setting Description 0 Sort using the ListItem object\'s Text property. > 1 Sort using the subitem whose collection Index is specified here.
Remarks The Sorted property must be set to True before the change takes place.
ListViews are controls everyone loves to hate. This demo shows a good number of tricks you can use to make your life with ListViews easier. Sort dates and numbers instead of just text (and at a pace 10-20x faster than the KB method!), reorder the columns, toggle extended styles, use checkboxes on each item, the list goes on. As always with benchmarks, make sure that you time the sorts using an EXE rather than from within the IDE. Important Note: Sorting a listview using the API (as two of the three methods here demonstrate) breaks the synchronization between the ListView object\'s ListItems collection and what\'s being displayed in the listview window. In other words, when you query VB\'s wrapped collection, the order of items returned will not match what\'s displayed. The only way to work around this \"issue\" is to go entirely to the API for all listview operations or live with VB\'s lame sorting options. Warning: The fastest sort (the \"IListItem Hack\") is included for educational purposes only! If you\'re crazy enough to use that code in your application, you will deserve it when Microsoft breaks you. And don\'t doubt that they will!
For i = 1 To UBound(numbers) - 1 For j = 1 To UBound(numbers) - 1 If numbers(j) > numbers(j + 1) Then temp = numbers(j) numbers(j) = numbers(j + 1) numbers(j + 1) = temp End If Next Next
int function Partition (Array A, int Lb, int Ub); begin select a pivot from A[Lb]...A[Ub]; reorder A[Lb]...A[Ub] such that: all values to the left of the pivot are <= pivot all values to the right of the pivot are >= pivot return pivot position; end;
procedure QuickSort (Array A, int Lb, int Ub); begin if Lb < Ub then M = Partition (A, Lb, Ub); QuickSort (A, Lb, M - 1); QuickSort (A, M + 1, Ub); end;
Private Function Partition(ByRef A() As Variant, ByVal Lb As Long, ByVal Ub As Long) _ As Long Dim t As Variant Dim pivot As Variant Dim i As Long Dim j As Long Dim p As Long
\' partition array[lb..ub]
\' select pivot and exchange with 1st element p = Lb + (Ub - Lb) \\ 2 pivot = A(p) A(p) = A(Lb)
\' sort Lb+1 .. Ub based on pivot i = Lb + 1 j = Ub Do Do While i < j If pivot <= A(i) Then Exit Do i = i + 1 Loop Do While j >= i If A(j) <= pivot Then Exit Do j = j - 1 Loop If i >= j Then Exit Do t = A(i) A(i) = A(j) A(j) = t j = j - 1 i = i + 1 Loop
\' pivot belongs in a(j) A(Lb) = A(j) A(j) = pivot Partition = j End Function
Public Sub QuickSort(ByRef A() As Variant, ByVal Lb As Long, ByVal Ub As Long) Dim m As Long
\' sort array A(lb..ub)
Do While Lb < Ub \' quickly sort short lists If (Ub - Lb <= 12) Then Call InsertSort(A, Lb, Ub) Exit Sub End If
\' partition into two segments m = Partition(A, Lb, Ub)
\' sort the smallest partition to minimize stack requirements If m - Lb <= Ub - m Then Call QuickSort(A, Lb, m - 1) Lb = m + 1 Else Call QuickSort(A, m + 1, Ub) Ub = m - 1 End If Loop End Sub
Public Sub QSort(ByRef A() As Variant, ByVal Lb As Long, ByVal Ub As Long) Dim lbStack(32) As Long Dim ubStack(32) As Long Dim sp As Long \' stack pointer Dim lbx As Long \' current lower-bound Dim ubx As Long \' current upper-bound Dim m As Long Dim p As Long \' index to pivot Dim i As Long Dim j As Long Dim t As Variant \' temp used for exchanges
lbStack(0) = Lb ubStack(0) = Ub sp = 0 Do While sp >= 0 lbx = lbStack(sp) ubx = ubStack(sp)
Do While (lbx < ubx)
\' select pivot and exchange with 1st element p = lbx + (ubx - lbx) \\ 2
\' exchange lbx, p t = A(lbx) A(lbx) = A(p) A(p) = t
\' partition into two segments i = lbx + 1 j = ubx Do Do While i < j If A(lbx) <= A(i) Then Exit Do i = i + 1 Loop
Do While j >= i If A(j) <= A(lbx) Then Exit Do j = j - 1 Loop
If i >= j Then Exit Do
\' exchange i, j t = A(i) A(i) = A(j) A(j) = t
j = j - 1 i = i + 1 Loop
\' pivot belongs in A[j] \' exchange lbx, j t = A(lbx) A(lbx) = A(j) A(j) = t
m = j
\' keep processing smallest segment, and stack largest If m - lbx <= ubx - m Then If m + 1 < ubx Then lbStack(sp) = m + 1 ubStack(sp) = ubx sp = sp + 1 End If ubx = m - 1 Else If m - 1 > lbx Then lbStack(sp) = lbx ubStack(sp) = m - 1 sp = sp + 1 End If lbx = m + 1 End If Loop sp = sp - 1 Loop End Sub
jelzin, når du nu er så godt i gang, kunne du så ikke tænke dig at smide et eksmpel på et stykke kode af hvor/hvordan man kalder den sortering istedetfor den som listview ellers bruger?
jeg har ikke helt styr på listview og gad godt gemme dine guldkorn til hvis nu jeg engang får brug for dem :-)
Som det er nævnt, så er problemet, at ListView sorterer alfa-numerisk. Det kan lade sig gøre at sortere efter tal, datoer eller hvad ellers man vil, men det kræver, at du foretager sorteringen via API.
Der findes en message LVM_SORTITEMS = (LVM_FIRST + 48), som skal sendes til listview\'et. Den tager en parameter med, som er adressen på den funktion, som skal foretage sammenligningen mellem to elementer. Den skal erklæres som
Public Function ListView_CompareValues(ByVal lParam1 As Long, ByVal lParam2 As Long, ByVal hInfo As Long) As ListViewSortResults
Public Enum ListViewSortResults lvsrPreceed = -1& lvsrEqual = 0& lvsrFollow = 1& End Enum
SortInfo er en struktur, jeg bruger i sorteringen til at angive sorteringsinfo:
Public Type ListViewSortItemInfo hWnd As Long lDataType As VbVarType lSortOrder As ListSortOrderConstants lColumnHeaderIndex As Long lLastSortableIndex As Long End Type
Min Compare-funktion ser således ud:
Public Function ListView_CompareValues(ByVal lParam1 As Long, ByVal lParam2 As Long, ByVal hInfo As Long) As ListViewSortResults Dim Idx1 As Long, Idx2 As Long Dim SortInfo As ListViewSortItemInfo CopyMemory ByVal SortInfo, ByVal hInfo, Len(SortInfo)
If Idx1 > .lLastSortableIndex Or Idx2 > .lLastSortableIndex Then If Idx1 > .lLastSortableIndex And Idx2 > .lLastSortableIndex Then ListView_CompareValues = lvsrPreceed ElseIf Idx1 <= .lLastSortableIndex And Idx2 > .lLastSortableIndex Then ListView_CompareValues = lvsrPreceed ElseIf Idx1 > .lLastSortableIndex And Idx2 <= .lLastSortableIndex Then ListView_CompareValues = lvsrFollow End If Else Select Case .lDataType Case vbDate ListView_CompareValues = CompareDate(ListView_GetItemDate(.hWnd, lParam1, .lColumnHeaderIndex), _ ListView_GetItemDate(.hWnd, lParam2, .lColumnHeaderIndex), _ .lSortOrder) Case vbLong, vbInteger, vbByte ListView_CompareValues = CompareLong(ListView_GetItemValueLong(.hWnd, lParam1, .lColumnHeaderIndex), _ ListView_GetItemValueLong(.hWnd, lParam2, .lColumnHeaderIndex), _ .lSortOrder) Case vbDouble, vbSingle ListView_CompareValues = CompareDouble(ListView_GetItemValueDouble(.hWnd, lParam1, .lColumnHeaderIndex), _ ListView_GetItemValueDouble(.hWnd, lParam2, .lColumnHeaderIndex), _ .lSortOrder) Case vbCurrency ListView_CompareValues = CompareCurrency(ListView_GetItemValueCurrency(.hWnd, lParam1, .lColumnHeaderIndex), _ ListView_GetItemValueCurrency(.hWnd, lParam2, .lColumnHeaderIndex), _ .lSortOrder) Case vbString ListView_CompareValues = CompareString(ListView_GetItemString(.hWnd, lParam1, .lColumnHeaderIndex), _ ListView_GetItemString(.hWnd, lParam2, .lColumnHeaderIndex), _ .lSortOrder) End Select End If End With End Function
De enkelte CompareXxxx sørger for at sammenligne de datatyper, de får over og returnere den returværdi, der skal tilbage fra ListView_CompareValues.
Funktionerne ListView_GetItemXxxx sørger for at hente værdien fra et (sub)item og konvertere til den datatype, der skal sorteres efter.
Hvis du vil bruge API til sortering, skal du være opmærksom på, at du ikke kan bruge almindelig sortering på ListView. Desuden kan du ikke bruge rækkefølgen i ListItems collection, da den ikke vedligeholdes internt.
Det er let nok du skal bare sætte en ekstra kollonnerne som en snyde kollonne med Width egenskaben til 0. Derved kan den ikke ses. F.eks. ListWiev1.ColumHeaders.Add 1, ,\"Kundenummer\", 0
Det er en god ide at bruge den første som snydekollonne kollonne da den ikke kan højrestilles. Når du så soterer bruger du bare den kollonne som du ikke kan se.
For det første kræver din løsning, at du forinden afgør længden af det længste kundenummer (evt. max længde).
For det andet, min løsning giver mulighed for at sortere på valgfri datatype i valgfri kolonne - eks. dato i en kolonne, tal i en anden og tekst i en tredje.
Jeg er rimelig overbevist om at du er kommet med den bedste løsning, MEN jeg vil bede dig være tålmodig idet jeg i øjeblikket kæmper med vigtigere problemer i forbindelse med udviklingen af mit system
eg ved ikke hvad Benny.tordrup fisker for japlex det er kun et 15 points spørgsmål. Hvis du har problemer med hvor mange cifre kundenr. har så sæt 10 nuller i Format funktionen feltet vises jo ikke. med hensyn til at sortr valgfrit i alle kollonner så kræver det kun 5 linniers programering.
Gå til Listview sub og placer makøren midt i Sub. Klik i kombinationsboksen i kode vinduet og vælg ColumnClick. Der oprettes nu en Private Sub ListView1_columnClick(Byval ColumnHeader As MSComctLib.ColumnHeader). ListView1 hvis du ikke har omdøbt Listview til et andet navn.
Skriv i sub\'en: If ListView1.SortOrdre = lvwAscending Then ListView1.SortOrder = lvwDescending Else Listview1.SortOrder = lvwAscending End if
Nu kan du bare trykke på det ønskede Listview1 kollonne hovederne og kollonnen soterer sig først størst mod mindst og trykker man igen så mindst mod størst. Metoden kan også sortere datoer. Hvis du så skjuler kollonnen med de foranstående numre så kan du Starte med at skrive: If ListView1.Sortkey = 2 Then ListView.Sortkey = 1
Prøv at lave et listview, hvor du tilføjer felterne KundeNr, Navn, Saldo og Sidste køb (dato). I Saldokolonnen har du talværdier over og under 0 (inklusive)
Jeg kunne godt tænke mig at se koden til at sortere kolonne et efter numerisk kundenr, kolonne to efter alfanumerisk, kolonne tre efter beløbet og kolonne fire efter dato - alle kolonner enten stigende eller faldende.
benny.tordrup tag dig lige sammen det har jeg jo svarret på du laver bare et snyde felt hvor dit kunnenummer har foranstillet nuller, men som man ikke kan se. har du brug for flere felter som skal soteres efter alfasystemet så må du lave flere snydefelter som man ikke kan se. I så fald så kan du ikke nøjes med If Listview1.Sortkey = 2 Then Listview1.Sortkey = 1 men så må du udvide dine betingelser med Select Case metoden Du kan kun sorterer et felt ad gangen ved at klikke på listview hovedet, men det var jo også det spørgsmålet gik ud på. benny.tordrup din løsning er brubar men den tangere genopfindelsen af den dybe tallerken.
Så prøv din løsning med snydekolonner rundt omkring og samtidig tillade kolonneresizing. Det giver dig mulighed for at få vist snydekolonnerne ved at resize kolonnebredderne.
Og nej, der er ikke et resizeevent på listviewet.
Desuden bliver listviewet langsomt, jo flere kolonner, der er i det sammen med mange rækker. En skjult kolonne per kolonne giver et unødvendigt stort forbrug af ressourcer.
Nu har du et felt som ikke kan ses og et som kan ses.
Det er kun felter som resikerer at blive sorteret alfanummerisk som med fordel kan kopieres til et string felt med foranstillet nuller. tekst og datofelter sorteres fint uden at man laver snydekoder. Så selv om du har en gammel og langsom PC så skulle det ikke være noget problem.
Du tager ikke hensyn til, at du kan få vist kolonne \"Snyd\" ved at resize helt ude i venstre side.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.