Zum Inhalt springen

[VBA unter Access 2000] Listview 6, Sortierung + Forecolor


JayN

Empfohlene Beiträge

Hallo zusammen,

ich habe folgendes Problem.

Ich benutze in meiner kleinen Datenbankanwendung unter Access 2000 die Listview 6.

Abhängig von einem Status werden die einzelnen Zeilen mit Forecolor verschieden eingefärbt:

Sub Faerbung()

Dim i, j As Integer

Dim status As Integer

Dim si As ListSubItem


    For i = 1 To lstMitgliederX.ListItems.Count

        status = lstMitgliederX.ListItems(i).ListSubItems(9)

        If status > 63 Then

            For j = 1 To 8

                Set si = lstMitgliederX.ListItems(i).ListSubItems(j)

                si.ForeColor = RGB(255, 0, 0)

                Set si = Nothing

            Next j

        End If

        If status > 3 And status < 64 Then

            For j = 1 To 8

                Set si = lstMitgliederX.ListItems(i).ListSubItems(j)

                si.ForeColor = RGB(0, 0, 255)

                Set si = Nothing

            Next j

        End If

        If status < 3 Then

            For j = 1 To 8

                Set si = lstMitgliederX.ListItems(i).ListSubItems(j)

                si.ForeColor = RGB(0, 0, 0)

                Set si = Nothing

            Next j

        End If

    Next i

End Sub
Für die Sortierung nach Spalten benutze ich das Modul dieses Modul:
' ------------ STANDARDMODUL ListViewSort.bas ------------

' --------------------------------------------------------

' Copyright (c) 2002 by Mathias Schiffer, AixSoft Software

Will jetzt erstmal nicht den ganzen Code posten, evtl. ist das ja bekannt.

Mein Problem ist folgendes:

Wenn nun die Zeilen verschieden gefärbt sind ist erstmal alles OK, solange ich nicht sortiere.

Klicke ich nun jedoch einen Spaltenkopf an, wird die Sortierung wertmäßig richtig durchgeführt, jedoch wird die Forecolor-Formatierung nicht mitsortiert.

Soll heißen, im Ursprung ist die Zeile 10 rot gefärbt. Sortiere ich jetzt nach einer Spalte, bleibt diese Zeile rot gefärbt, obwohl der Datensatz nun woanders steht und ein ganz anderer Datensatz an dieser Stelle auftaucht.

Kann man das irgendwie fixen?

Für eure Hilfe wäre ich sehr dankbar.

Gruß

JayN

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ruf doch einfach nach dem Sortieren nochmal Faerbung auf. Du solltest aber noch eine Behandlung für den Fall status = 3 einbauen.

Auf die Idee bin ich auch schon gekommen, funktioniert aber nicht. Es scheint so, als ob er nach einem festen Index vorgeht, der bei der Sortierung nicht berücksichtigt wird.

Einen status = 3 kann es nicht geben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Auf die Idee bin ich auch schon gekommen, funktioniert aber nicht.
Was heißt "funktioniert aber nicht"?

Es scheint so, als ob er nach einem festen Index vorgeht, der bei der Sortierung nicht berücksichtigt wird.
Wer ist "er"? Wie die Liste sortiert ist, sollte egal sein, weil die Farbe aus dem Wert des Subitem 9 bestimmt wird.

Einen status = 3 kann es nicht geben.
Kennst du den Spruch mit den sich übergebenden Pferden? ;)
Link zu diesem Kommentar
Auf anderen Seiten teilen

Was heißt "funktioniert aber nicht"?

Es ändert sich nichts an der Färbung.

Wer ist "er"? Wie die Liste sortiert ist, sollte egal sein, weil die Farbe aus dem Wert des Subitem 9 bestimmt wird.

Interessante Frage. Wer ist "er"... der Anwendungstroll... ;) Na ja, es war die Listview gemeint, denke ich... :)

Wenn ich zur Laufzeit, nach der Sortierung, die Items abfrage, so steht an der 10ten Stelle immer noch das Items, was da vor der Sortierung stand. Die sind im Objekt so indiziert.

Wie die Sortierung dabei genau funktioniert, weiß ich nicht.

Kennst du den Spruch mit den sich übergebenden Pferden? ;)

Klar. Aber ich bin Programmierer und kein Pfuscher. ;)

Es gibt insgesamt 3 Stati-Gruppen.

Gruppe 1: 1 oder 2

Gruppe 2: 4, 8, 16 oder 32

Gruppe 3: 64

Aus diesen Werten wird der Gesamtstatus ermittelt. Und da kann es keine 3 geben... :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich zur Laufzeit, nach der Sortierung, die Items abfrage, so steht an der 10ten Stelle immer noch das Items, was da vor der Sortierung stand. Die sind im Objekt so indiziert.

Wie die Sortierung dabei genau funktioniert, weiß ich nicht.

Kann es sein, dass du Subitem 9 einfach nicht mitsortierst? Mir fällt auch auf, dass du Subitem 9 nicht färbst.

Es gibt insgesamt 3 Stati-Gruppen.

Gruppe 1: 1 oder 2

Gruppe 2: 4, 8, 16 oder 32

Gruppe 3: 64

Das sieht eher nach Flags aus. Sicher, dass die nicht kombinierbar sind? Ansonsten wäre es unsinnig, nicht aufeinanderfolgende Werte zu benutzen.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Kann es sein, dass du Subitem 9 einfach nicht mitsortierst? Mir fällt auch auf, dass du Subitem 9 nicht färbst.

Subitem 9 ist mit einer Breite 0 eingebunden, ist also quasi versteckt und dient nur zur Hilfe. Ob das Dingen nun sortiert wird, muss ich überprüfen. Aber wie gesagt. Wenn ich nach der Sortierung die Faerbung anstarte und zur Laufzeit die Items durchgehe, so steht an der zehnten Stelle des gleiche Item, wie vor der Sortierung.

Das sieht eher nach Flags aus. Sicher, dass die nicht kombinierbar sind? Ansonsten wäre es unsinnig, nicht aufeinanderfolgende Werte zu benutzen.

Unsinnig? Nee, gar nicht unsinnig.

Stell Dir mal vor, es wären aufeinanderfolgende Werte.

Gruppe 1: 1 oder 2

Gruppe 2: 3,4,5 oder 6

Gruppe 3: 7

Wenn nun ein Status von 5 rauskommt, wie schlüssele ich den wieder auf? Ist es 1 und 4 oder 2 und 5? :confused:

Lass uns nicht über den Inhalt, sondern über das eigentliche Problem nachdenken... :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich nach der Sortierung die Faerbung anstarte und zur Laufzeit die Items durchgehe, so steht an der zehnten Stelle des gleiche Item, wie vor der Sortierung.
Deswegen vermute ich, das es nicht mitsortiert wird.

Unsinnig? Nee, gar nicht unsinnig.

Stell Dir mal vor, es wären aufeinanderfolgende Werte.

Gruppe 1: 1 oder 2

Gruppe 2: 3,4,5 oder 6

Gruppe 3: 7

Wenn nun ein Status von 5 rauskommt, wie schlüssele ich den wieder auf? Ist es 1 und 4 oder 2 und 5? :confused:

Also sind die Werte kombinierbar, aber aus jeder Gruppe kann nur ein Wert auftauchen? Dann brauchst du nicht alle Wert als Flags zu implementieren, es reicht, wenn du jede Gruppe gegen die anderen Gruppen abgrenzt.

Gruppe 1: 0 oder 1

Gruppe 2: 0, 2, 4 oder 6

Gruppe 3: 8

Aber das ist nur eine Platzoptimierung.

Lass uns nicht über den Inhalt, sondern über das eigentliche Problem nachdenken... :)
Entschuldige, dass ich versuche, logische Fehler in deinem Programm aufzudecken.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Deswegen vermute ich, das es nicht mitsortiert wird.

Wenn ich die anderen Subitems des Items durchgehe, so sind da auch immer noch die gleichen Werte drin.

Nochmal zur Verdeutlichung, aber etwas abgekürzt:

USER ORT STATUS(versteckt)

JNeudorf Bielefeld 65

Klotzkopp Essen 9

Wenn ich jetzt nach User DESC sortiere, so bleibt die erste Zeile rot. Wenn in Faerbung() des erste Item (nach der Sortierung) abgefragt wird, so ist lstMitgliederX.ListItems(1).SubItems(1) = "JNeudorf".

Bei der Sortierung wähle ich keine Spalten explizit aus, ich gehe also davon aus, dass die ganze Listview sortiert wird.

Also sind die Werte kombinierbar, aber aus jeder Gruppe kann nur ein Wert auftauchen? Dann brauchst du nicht alle Wert als Flags zu implementieren, es reicht, wenn du jede Gruppe gegen die anderen Gruppen abgrenzt.

Gruppe 1: 0 oder 1

Gruppe 2: 0, 2, 4 oder 6

Gruppe 3: 8

Aber das ist nur eine Platzoptimierung.

Sieht schon besser aus, aber noch nicht richtig... die Null in der zweiten Gruppe darf nicht auftauchen.

Entschuldige, dass ich versuche, logische Fehler in deinem Programm aufzudecken.

Kein Problem... ;) und außerdem ist es kein Fehler... sondern wie Du schon sagtest, höchstens eine Optimierung. Ich habe im Entwurf halt die Stati mit 2er-Potenzen belegt, um ganz sicher zu gehen, dass es keine Überschneidungen geben kann. Damals war es noch nicht klar, wie genau sich die Stati in Gruppen aufteilen würden. Und nachdem ich dann die Verarbeitung erstellt habe, hatte ich nicht den Drang die Stati sofort zu optimieren.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich jetzt nach User DESC sortiere, so bleibt die erste Zeile rot. Wenn in Faerbung() des erste Item (nach der Sortierung) abgefragt wird, so ist lstMitgliederX.ListItems(1).SubItems(1) = "JNeudorf".
Das heißt, an den Werten, die dir die ListItems-Collection liefert, ändert sich gar nichts?

Bei der Sortierung wähle ich keine Spalten explizit aus, ich gehe also davon aus, dass die ganze Listview sortiert wird.
Ich habe mir die Sortierfunktion mal in der MSDN Library angesehen. Da werden die direkten WinAPI-Nachrichten benutzt, damit werden ohnehin nur komplette Items vertauscht. Daran kann es also nicht liegen.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Das heißt, an den Werten, die dir die ListItems-Collection liefert, ändert sich gar nichts?

Ich habe mir die Sortierfunktion mal in der MSDN Library angesehen. Da werden die direkten WinAPI-Nachrichten benutzt, damit werden ohnehin nur komplette Items vertauscht. Daran kann es also nicht liegen.

Das versuche ich Dir die ganze Zeit mitzuteilen... :)

An den Werten ändert sich bei der o.g. Zugriffsart gar nichts. Ich weiß jetzt nicht, ob ich da irgendwie die Sortierung mitberücksichtigen kann.

Wenn es weiterhilft, kann ich das Sortierungsmodul hier posten.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe mir die Sortierfunktion mal in der MSDN Library angesehen. Da werden die direkten WinAPI-Nachrichten benutzt, damit werden ohnehin nur komplette Items vertauscht. Daran kann es also nicht liegen.

Legt die Sortierung evtl. irgendwo eine temporäre Collection oder ähnliches an? Denn irgendwie muss die Reihenfolge ja festgehalten werden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn es weiterhilft, kann ich das Sortierungsmodul hier posten.
Nicht nötig, das gibt's ja im Web.

Legt die Sortierung evtl. irgendwo eine temporäre Collection oder ähnliches an? Denn irgendwie muss die Reihenfolge ja festgehalten werden.
Die Sortierfunktion arbeitet direkt mit Windows-Messages auf dem Steuerelement, und benutzt für die Sortierung ItemData-Werte, die offenbar von VB dort angelegt werden. Normalerweise sind die alle Null, und es ist daher nicht möglich, aus diesem Wert auf den Index des Eintrags zu schließen, aber so geht die Funktion vor.

Es könnte sein, dass VBA die Collection nicht aktualisiert. Ob und wie man so eine Aktualisierung triggern könnte, weiß ich leider nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Eine Möglichkeit, die ich sehe, ist eine andere Sortierung der Listview und zwar im SQL-Statement, das vor dem Befüllen generiert wird. Das hätte jedoch bei jedem Klick eine neue Befüllung der ListView zur Folge und wäre nicht performant. Kommt also eher nicht in Frage.

Irgendwelche anderen Lösungsansätze?

Link zu diesem Kommentar
Auf anderen Seiten teilen

ich hab ein listview unter vb 6, für das ich eine sortier funktion usw geschrieben hab;

wenn ich mal zeit hab, schick ich dir das per pm;

mein listview ist zwar nicht direkt eingefärbt, aber ich zeige bilder an, und färbe die schrift einer zeile ein;

wenns geht, musst du das halt noch ein bisl umschreiben

Link zu diesem Kommentar
Auf anderen Seiten teilen

ich sortiere meine listview folgendermasen:

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)

    ListView1.SortKey = ColumnHeader.Index - 1

    If ListView1.SortOrder = lvwAscending Then

        ListView1.SortOrder = lvwDescending

    Else

        ListView1.SortOrder = lvwAscending

    End If

    ListView1.Sorted = True

End Sub
damit klappt das auch bei mir ganz gut ansonsten verwende mal dieses modul: Modul:
Option Explicit


Private Const LVM_FIRST       As Long = &H1000&

Private Const LVM_SORTITEMS   As Long = LVM_FIRST + 48&

Private Const LVM_FINDITEM    As Long = LVM_FIRST + 13&

Private Const LVM_GETITEMTEXT As Long = LVM_FIRST + 45&

Private Const LVFI_PARAM      As Long = &H1&

Private Const LVIF_TEXT       As Long = &H1&


Public Enum ListSortOrderConstants

    lvwAscending = 0&

    lvwDescending = 1&

End Enum


Private Type LVWSORT

    hWndListView As Long

    SortKey As Long

    SortOrder As ListSortOrderConstants

End Type


Private Type POINTAPI

    x As Long

    y As Long

End Type


Private Type LV_FINDINFO

    flags As Long

    psz As String

    lParam As Long

    pt As POINTAPI

    vkDirection As Long

End Type


Private Type LV_ITEM

    mask As Long

    iItem As Long

    iSubItem As Long

    state As Long

    stateMask As Long

    pszText As Long

    cchTextMax As Long

    iImage As Long

    lParam As Long

    iIndent As Long

End Type


Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _

                                                                            ByVal Message As Long, _

                                                                            ByVal wParam As Long, _

                                                                            ByVal lParam As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, _

                                                                     ByRef Source As Any, _

                                                                     ByVal Length As Long)


Public Sub SortListView(ByVal hWndListView As Long, _

                        ByVal SortKey As Long, _

                        Optional ByVal SortOrder As ListSortOrderConstants = lvwAscending)


Dim udtLVWSORT As LVWSORT


  With udtLVWSORT

    .hWndListView = hWndListView

    .SortKey = SortKey

    .SortOrder = SortOrder

  End With


  SendMessageLong hWndListView, _

                  LVM_SORTITEMS, _

                  VarPtr(udtLVWSORT), _

                   AddressOf CompareFunc

End Sub


Private Function CompareFunc(ByVal lParam1 As Long, _

                             ByVal lParam2 As Long, _

                             ByVal lParamSort As Long) As Long


    Dim ListViewSort            As LVWSORT

    Dim sEntry1                 As String

    Dim sEntry2                 As String

    Dim vCompare1               As Variant

    Dim vCompare2               As Variant


    CopyMemory ListViewSort, _

               ByVal lParamSort, _

               Len(ListViewSort)


    sEntry1 = LvwGetText(ListViewSort, lParam1)

    sEntry2 = LvwGetText(ListViewSort, lParam2)


    If sEntry1 = sEntry2 Then

      Exit Function

    End If


    CompareFunc = CompareStrings(sEntry1, sEntry2, ListViewSort.SortOrder)

End Function


Private Function LvwGetText(ByRef ListViewSort As LVWSORT, _

                            ByVal lParam As Long) As String


    Dim udtFindInfo             As LV_FINDINFO

    Dim udtLVItem               As LV_ITEM

    Dim lngIndex                As Long

    Dim baBuffer(512)           As Byte

    Dim lngLength               As Long


  With udtFindInfo

    .flags = LVFI_PARAM

    .lParam = lParam

  End With

  lngIndex = SendMessageLong(ListViewSort.hWndListView, _

                             LVM_FINDITEM, -1, _

                             VarPtr(udtFindInfo))


  With udtLVItem

    .mask = LVIF_TEXT

    .iSubItem = ListViewSort.SortKey

    .pszText = VarPtr(baBuffer(0))

    .cchTextMax = UBound(baBuffer) + 1

  End With

  lngLength = SendMessageLong(ListViewSort.hWndListView, _

                              LVM_GETITEMTEXT, lngIndex, _

                              VarPtr(udtLVItem))


  If lngLength > 0 Then

    LvwGetText = Left$(StrConv(baBuffer, vbUnicode), lngLength)

  End If

End Function


Private Function CompareStrings(ByRef sEntry1 As String, _

                                ByRef sEntry2 As String, _

                                ByVal SortOrder As ListSortOrderConstants) As Long


    If SortOrder = lvwAscending Then

        If sEntry1 < sEntry2 Then

            CompareStrings = -1

        Else

            CompareStrings = 1

        End If

    Else

        If sEntry1 > sEntry2 Then

            CompareStrings = -1

        Else

            CompareStrings = 1

        End If

    End If


End Function

Form:
'Sortierung bei Klick auf Kopfzeile

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)

    If ColumnHeader.Text = MsColHeader And MbAsc = True Then

        SortListView ListView1.hWnd, ColumnHeader.Index - 1, lvwDescending

        MbAsc = False

    Else

        SortListView ListView1.hWnd, ColumnHeader.Index - 1, lvwAscending

        MbAsc = True

    End If

    MsColHeader = ColumnHeader.Text

End Sub

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...