Access
 sql >> Base de données >  >> RDS >> Access

Événements de tri par glisser-déposer du contrôle ListView

Réorganisation des lignes de données dans le contrôle ListView.

Dans l'épisode précédent de ce didacticiel, nous avons appris à réorganiser les colonnes en activant cette fonctionnalité :AllowColumnReorder option sur la feuille de propriétés. Mais, déplacer une ligne se fait en la faisant glisser et en la plaçant sur une autre ligne. Pour réorganiser les lignes de contrôle ListView, l'action ListItem Drag and Drop nécessite l'activation de cette fonctionnalité sur la feuille de propriétés. Mais cela seul ne fonctionnera pas, nécessite le code VBA pour réorganiser l'article dans l'ordre requis.

Créons un exemple de formulaire d'accès avec des contrôles et un code VBA dans notre base de données pour cet exercice. L'exemple d'image du formulaire avec les contrôles ListBox et ListView est donné ci-dessous.

Nous avons créé une liste de tables et de requêtes (pas de requêtes d'action) dans la zone de liste. La sélection de l'un des éléments de la liste affichera les enregistrements instantanément sur le contrôle ListView, tels que nous les voyons dans la vue Feuille de données.

La tâche de conception.

  1. Créez une nouvelle table avec un seul champ de texte, avec le nom de champ DataList .

  2. Enregistrez la table avec le nom lvTables (lv signifie ListView).

  3. Ouvrez la table en mode Feuille de données.

  4. Ajoutez quelques noms de table et sélectionnez les noms de requête de votre base de données dans la table. J'ai importé des tables de l'exemple de base de données Northwind pour ma liste.

    Remarque : La pièce jointe Le champ n'est pas valide dans ListView Control. Créez des requêtes de sélection pour les tables avec un champ de pièce jointe et sélectionnez tous les champs sauf le champ de pièce jointe.

  5. Créez et ouvrez un nouveau formulaire en mode Création.

  6. Insérez un contrôle ListBox sur le formulaire, affichez la feuille de propriétés et modifiez son nom valeur de la propriété à List0 .

  7. Modifier son étiquette enfant Caption valeur aux Tableaux .

  8. Affichez la feuille de propriétés du contrôle ListBox et définissez la source de ligne valeur de la propriété aux lvTables nom.

  9. Vérifiez si le Type de source de ligne est défini sur Table/Requête et si la valeur de la propriété Colonne liée est 1. Si différent, modifiez-le.

  10. Insérez un contrôle ListView à partir de la liste des contrôles ActiveX et modifiez sa valeur de propriété de nom en ListView1 .

  11. Redimensionnez les deux contrôles comme indiqué sur l'image de formulaire de démonstration ci-dessus.

  12. Insérez une étiquette au-dessus des contrôles et remplacez ses valeurs de propriété Name et Caption par Heading. La valeur Caption sera modifiée à partir du code vba lorsqu'une table ou une requête est sélectionnée dans la ListBox.

  13. Créez un bouton de commande sous les contrôles et modifiez la valeur de sa propriété Name en cmdClose et la valeur de la propriété Caption sur Fermer .

  14. Cliquez avec le bouton droit sur le contrôle ListView, mettez en surbrillance l'objet ListViewCtrl et sélectionnez Propriétés .

  15. Modifiez les paramètres de propriété pour qu'ils correspondent aux paramètres de Général Image de l'onglet ci-dessous.

  16. Image de la feuille de propriétés du contrôle ListView - La vue de l'onglet Général est donnée ci-dessous :

    Certaines de ces options ont déjà été définies dans les sessions précédentes. Ici, nous avons besoin des options suivantes pour notre action Drag Drop :

    • OLEDragAutomatique - 1

    • Manuel OLEDrop - 1

    • FullRowSelect - Vrai

    • HotTracking - Vrai

Assurez-vous que les paramètres ci-dessus correspondent à votre feuille de propriétés, puis enregistrez le formulaire.

Affichez le module VBA du formulaire.

Le code VBA du module de formulaire.

Copiez et collez le code VBA suivant dans le module, en écrasant les lignes de code existantes, le cas échéant :

Option Compare Database
Option Explicit

Dim lvwList As MSComctlLib.ListView
Dim strTable As String
Dim db As DAO.Database
Dim rst As DAO.Recordset

Private Sub Form_Load()
    Set lvwList = Me.ListView1.Object

End Sub


Private Sub Form_Unload(Cancel As Integer)
On Error GoTo Form_Unload_Err
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim flag As Boolean
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)
flag = False
For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) _
       And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

Form_Unload_Exit:
Exit Sub

Form_Unload_Err:
MsgBox Err & " : " & Err.Description, , "Form_Unload()"
Resume Form_Unload_Exit

End Sub

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control
' sorts the data of that column. On the first Click on the Column
'will sort in Ascending Order, second Click will sort in Descending
With Me.ListView1
    ' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
' Set Sorted to True to sort the list.
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 
    .Sorted = True
End With

End Sub

Private Sub List0_Click()

strTable = List0.Value

Call LoadListView(strTable)

End Sub

Private Sub LoadListView(ByVal s_Datasource As String)
On Error GoTo LoadListView_Err
    Dim j As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim strHeading As String
    
    strHeading = UCase(s_Datasource)
    With Me.Heading
        .caption = strHeading
        .FontName = "Courier New"
        .FontSize = 20
        .FontItalic = True
        .FontBold = True
    End With
    
   'Initialize ListView Control
    lvwList.ColumnHeaders.Clear
    lvwList.ListItems.Clear
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(s_Datasource, dbOpenSnapshot)
       
    'Initialize ListView & Column Headers Property Values
     With lvwList
        .Font.Size = 10
        .Font.Name = "Verdana"
        .Font.Bold = False
        .GridLines = True
    End With
    
    With lvwList
        'Syntax: .ColumnHeaders.Add Index, Key, Text, Width in Pixels, Alignment, Icon
       For j = 0 To rst.Fields.Count - 1
        .ColumnHeaders.Add , , rst.Fields(j).Name, IIf(j = 0, 3000, 1400), 0
       Next
    End With
   Dim I As Long
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
    'Syntax: lvwList.ListItems.Add Index, Key, Text, Icon, SmallIcon
        Set tmpLItem = lvwList.ListItems.Add(, , rst.Fields(0).Value) 'Name column
        
         'Syntax: tmpLItem.ListSubItems.Add Index, Key, Text, ReportIcon, ToolTipText
          With tmpLItem
                For j = 1 To rst.Fields.Count - 1
                    .ListSubItems.Add , , Nz(rst.Fields(j).Value, "")
                Next
          End With
        rst.MoveNext
    Loop
    rst.Close
    
    With lvwList
        If .ListItems.Count > 0 Then
            .ListItems(1).Selected = True
        End If
    End With
  
    Set db = Nothing
    Set rst = Nothing
    
LoadListView_Exit:
Exit Sub

LoadListView_Err:
MsgBox Err & " : " & Err.Description, , "LoadListView()"
Resume LoadListView_Exit
End Sub


Private Sub ListView1_OLEDragOver(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)

End Sub

Private Sub ListView1_OLEDragDrop(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dropped
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being readded to the list
Dim lvwTarget As ListItem
'Subitem reference in dropped item
Dim lvwSub As ListSubItem
'Drop position
Dim intTgtIndex As Integer
Dim j As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

'Ignore overlapping drag or drop Item actions
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

'Save the droped position Index Number
intTgtIndex = lvwDrop.Index
'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'For j = intTgtIndex To ListItems.Count
    
'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

'Destroy all objects
Set lvwTarget = Nothing
Set lvwDrag = Nothing
Set lvwDrop = Nothing
Set lvwList.DropHighlight = Nothing

End Sub

Private Sub cmdClose_Click()
    DoCmd.Close acForm, Me.Name
End Sub

Vous connaissez le code VBA ci-dessus, à l'exception des sous-routines nouvellement ajoutées :ListView1_OLEDragOver(), ListView1_OLEDragDrop(), Form_Unload(), et le ListView1_ColumnClik() procédures. Les deux premières procédures nous aideront à faire glisser un élément (ligne) et à le déposer sur un autre élément pour l'insérer dans un nouvel emplacement. Les procédures Form_Unload() et ListView1_ColumnClick() vont trier les Items.

Les images suivantes montrent l'action Glisser-Déposer dans les séquences de son exécution

La première image ci-dessous montre la séquence d'action de glisser-déposer. Le ListItem, avec EmployeeID 7, est glissé par l'utilisateur et déposé sur le ListItem avec ID 3.

La deuxième image montre le déplacement de ListItem dans l'ordre inverse.

Lorsque le pointeur de la souris se déplace sur une ligne avec l'élément glissé, entre les lignes source et cible, se mettra en surbrillance l'une après l'autre en montant.

L'action glisser-déposer dans les images.

La ligne avec l'ID d'employé 7 est déposée sur l'élément avec l'ID d'employé 3 ci-dessus.

L'analyse par segment de code VBA.

Une sélection d'éléments dans la ListBox, la procédure événementielle List0_Click() s'exécute et charge les enregistrements dans le contrôle ListView.

Private Sub List0_Click()
Dim strTable As String

strTable = List0.Value

  Call LoadListView(strTable)

End Sub

Le nom de table/requête sélectionné est enregistré dans strTable variable de chaîne. La LoadListView() La sous-routine s'exécute avec la variable strTable comme paramètre. Nous avons parcouru ce code plus d'une fois lors de sessions précédentes, et vous pouvez visiter ces pages en utilisant les liens fournis au bas de cette page pour plus de détails. Vous trouverez peut-être quelques modifications mineures que j'ai apportées à ce code.

Nous n'avons pas utilisé le contrôle ImageList dans cet épisode, l'Icon, SmallIcon Valeurs des paramètres dans la méthode ListItems.Add() et ReportIcon, TooltipText les valeurs des paramètres dans la méthode ListSubItems.Add() ne sont pas non plus utilisées.

Regardons ce qui se passe dans le ListView1_OLEDragOver() et ListView1_OLEDragDrop() Segments de code VBA.

La procédure ListView1_OLEDragOver().

Private Sub ListView1_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)
End Sub 

Cette procédure s'exécute automatiquement lorsque vous essayez de cliquer et de maintenir sur une ligne, commencez à faire glisser et déplacez-vous sur d'autres lignes sur le chemin vers la ligne cible. L'action de glisser se déplace sur une autre ligne, elle sera mise en surbrillance.

Le ListView1.HitTest(x, y) La fonction lit les coordonnées x, y qui déterminent la position de la ligne sur le contrôle ListView et met cette ligne en surbrillance. Ce processus se poursuit lorsque vous êtes sur d'autres lignes jusqu'à ce que vous le déposiez sur la ligne cible en relâchant le bouton de la souris. L'action de dépôt déclenche le ListView1_OLEDragDrop() procédure et exécute les procédures de changement de ligne source.

La procédure ListView1_OLEDragDrop.

Private Sub ListView1_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem 'Drop position index Dim intTgtIndex As Integer Set lvwDrop = lvwList.HitTest(x, y) 'save the source item Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item 'Ignore overlapping drag or drop Item actions If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If 'Save the droped position Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True 'Destroy all objects Set lvwTarget = Nothing Set lvwDrag = Nothing Set lvwDrop = Nothing Set lvwList.DropHighlight = Nothing End Sub

Examinons cette procédure partie par partie et comprenons ce qui s'y passe. Le segment de code suivant déclare les variables d'objet nécessaires pour gérer l'action de glisser-déposer :

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Reference of the Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem
'Drop position index
Dim intTgtIndex As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

Les trois premiers objets temporaires ListItem déclarent avec des noms différents.

Le lvwDrag L'objet ListItem contiendra la copie de la ligne que nous choisissons de faire glisser vers un nouvel emplacement.

Le lvwDrop ListItem Object enregistrera la référence de la ligne sur laquelle nous déposons l'élément de liste glissé.

Lors du changement d'action ListItems, nous supprimerons l'élément Source de son emplacement d'origine, puis le créerons à l'emplacement cible, avec le numéro d'index ListItem source. Les références de ce nouveau ListItem sont enregistrées dans le lvwTarget Variable d'objet ListItem.

Le lvwSub Variable déclarée en tant que variable objet de séquencement dans le For . . .Suivant Boucle. Cette boucle nécessite de séquencer les ListSubItems, (à partir de la 2e colonne) un par un, à partir de l'objet lvwDrag. Même si nous avons supprimé le ListItem d'origine, nous en avons enregistré une copie dans l'objet ListItem lvwDrag.

Le numéro d'index lvwDrop ListItem est enregistré dans intTgtIndex variable.

Le lvwList.HitTest(x, y) La fonction lit les coordonnées x, y du contrôle ListView et identifie le ListItem cible où nous avons déposé le ListItem source et en fait une copie dans lvwDrop Object.

Nous allons d'abord sélectionner un ListItem avant de le faire glisser vers la nouvelle position.

Le lvwList.SelectedItem La propriété sera définie sur True. Avec l'aide de ce statut de propriété, nous faisons une copie du ListItem sélectionné dans le lvwDrag Objet ListItem. Le segment de code suivant valide à la fois les objets ListItem source et cible.

Vérifications de validation sur l'action glisser-déposer.

'Ignore overlapping drag or drop Item actions, 
'OR drag and drop happens on the same ListItem.
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing)  Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

Le segment de code ci-dessus valide l'action de glisser-déposer. Si ces actions ne commencent ou ne se terminent pas sur un élément valide, les objets lvwDrop ou lvwDrag ou les deux seront vides. Ou un autre mouvement invalide peut se produire lorsque l'utilisateur déplace une ligne vers le haut ou vers le bas, mais peut changer d'avis et la déposer sur la même ligne. La détection de ces types de faux mouvements mettra fin au programme.

Si le test ci-dessus s'avère valide, le programme continuera à exécuter la procédure suivante pour réorganiser les lignes.

'Save the dropped position ListItem Index Number
intTgtIndex = lvwDrop.Index

'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

Les neuf lignes ci-dessus d'actions de code exécutables (les autres lignes sont des commentaires) sont assez simples.

Le intTgtIndex =lvwDrop.Index L'instruction enregistre le numéro d'index de la cible ListItem dans intTgtIndex variable.

Comme nous avons déjà enregistré le listItem de la ligne source dans l'objet temporaire lvwDrag, l'étape suivante consiste à supprimer le ListItem source du contrôle ListView. La procédure ListItems.Remove() est appelé, avec l'instruction lvwList.ListItems.Remove lvwDrag.Index .

En bref, l'action Drag Drop consiste à supprimer un ListItem de son emplacement d'origine et à le recréer à l'emplacement cible avec le numéro d'index de ligne cible.

L'instruction Set lvwTarget =lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) crée le nouveau ListItem avec son numéro d'index d'emplacement cible intTgtIndex et le Text valeur de Source ListItem enregistrée dans l'objet lvwDrag plus tôt.

Lors de la création du ListItem pour la première fois, nous n'avons utilisé que ces deux valeurs, l'index et le Text valeurs des paramètres. Nous n'avons pas utilisé les autres options de paramètre Key, Icon, et Petite Icône sinon, nous devons également inclure ces valeurs de paramètres à partir de l'objet lvwDrag.

Conformément à notre exemple de glisser-déposer des images ci-dessus, nous avons déplacé le 7ème ListItem et l'avons déposé sur le 3ème ListItem. Après cela, nous avons supprimé le 7ème élément (ou ListItem source) du contrôle ListView. Création d'un nouveau ListItem avec le numéro d'index cible 3.

Maintenant, il y a deux éléments avec le même numéro d'index 3, celui existant avec le numéro d'index 3 et le nouveau que nous avons créé avec le numéro d'index 3. Toutes les autres informations sont tirées de l'objet lvwDrag (ou du 7ème ListItem enregistré dans lvwDrag Objet plus tôt).

Le système incrémente automatiquement le ListItem 3 existant jusqu'aux numéros de séquence suivants 3,4,5 . . . à 4,5,6 . . . et les déplace vers l'avant pour donner de l'espace à l'élément entrant à insérer entre les deux.

L'impact de supprimer une ligne et de la créer ailleurs.

Supposons que nous effectuons ce mouvement dans l'ordre inverse, comme faire glisser ListItem numéro 3 d'en haut et le déposer sur l'élément numéro 7, que se passe-t-il ?

Naturellement, nous supprimerons le 3ème élément et tenterons de créer un nouvel élément avec le numéro d'index 7 dans le nouvel emplacement. Lorsque le numéro d'article 3 est supprimé, l'article numéro 4 se déplacera vers le haut ou 4,5,6,7,8,9 deviendra 3,4,5,6,7,8 (pour faire tous les articles dans l'ordre) ou le plus tôt l'élément avec le numéro d'index 7 deviendra 6.

Lorsque nous créons le nouvel article avec le numéro d'index 7, le 7,8 existant redevient 8,9. Lorsque nous observons le mouvement des lignes pendant la suppression et la création de lignes, le premier exemple déplace la ligne cible vers le bas pour faire place à l'élément entrant. Dans le deuxième exemple expliqué (déplacement de 3 à 7), la ligne de destination se déplacera vers le haut.

Remarque : Regarder tla valeur de l'identifiant des employés pour son placement comme un indice pour que ListItem se déplace vers le bas ou vers le haut lorsque nous réorganisons ListItem.

J'ai mentionné ListItem partout dans les opérations de glisser-déposer. Le ListItem fait référence à la première colonne de la ligne ListView uniquement. Les autres valeurs de colonne sont ListSubItems ou les éléments enfants de ListItem. Cela signifie que vous ne pourrez faire glisser et déposer que la première colonne. Les autres colonnes ou ListSubItems seront déplacés sous le ListItem avec le code VBA.

Ceci est vrai si vous n'avez pas activé la FullRowSelection sur la feuille de propriétés du contrôle ListView sur le Général Tab.

Si cette option est activée, vous pouvez sélectionner n'importe quelle colonne, mais le système se réfère à l'index ListItem à des fins de réorganisation des lignes. Comparez les deux images ci-dessus avec un autre ensemble de deux exemples d'images, les troisième et quatrième images à partir du haut de cette page.

L'action Glisser-déposer ne fonctionnera pas si les deux valeurs de propriété suivantes ne sont pas définies sur la feuille de propriétés du contrôle ListView sur le Général Tab. :

  • ccOLEDragAutomatic =1
  • ccOLEDropManual =1

Les cinq instructions suivantes déplaceront les ListSubItems, le cas échéant, au ListItem nouvellement créé dans le nouvel emplacement.

Ensuite, le ListItem nouvellement créé est mis en surbrillance.

Ensuite, tous les objets temporaires créés sont effacés de la mémoire.

Remarque : Un autre point important à noter ici est que cet arrangement est temporaire et est perdu lorsque vous fermez le formulaire ou chargez une autre table/requête sur le contrôle ListView.

Si nous voulons que l'ordre modifié de ListItems reste permanent, ou jusqu'à ce que l'ordre soit modifié la prochaine fois, nous devons être en mesure de mettre à jour le numéro d'ordre indexé actuel sur la table elle-même. Nous avons ajouté un nouveau champ entier avec l'ID de nom de champ sur la table des employés.

L'exemple d'écran avec les données Employés réorganisées par ordre alphabétique est donné ci-dessous :

Étant donné que le champ ID des employés est un champ NuméroAuto et lié à d'autres tables connexes, nous avons ajouté un nouveau champ numérique avec le nom de champ ID. Cette valeur de champ est initialement définie manuellement avec les mêmes numéros de séquence à partir de l'ID des employés. Cette valeur de champ sera initialement dans cet ordre. Cependant, les données ListView Rows peuvent changer leur ordre lorsque vous réorganisez les données sur le contrôle ListView en raison d'une action de glisser-déposer.

Regardez le EmployésQ Requête SQL donnée ci-dessous :

SELECT [FirstName] & " " & [LastName] AS EmployeeName, 
Employees.ID, 
Employees.EmployeeID, 
Employees.TitleOfCourtesy, 
Employees.Title, 
Employees.Address, 
Employees.City, 
Employees.Region, 
Employees.PostalCode, 
Employees.Country, 
Employees.HomePhone, 
Employees.Extension, 
Employees.Notes
FROM Employees
ORDER BY Employees.ID;

La requête ci-dessus est utilisée comme source de données pour le contrôle ListView et ils sont triés sur le champ ID. Le champ ID est mis à jour avec l'ordre modifié des numéros d'index sur le contrôle ListView. Le processus de mise à jour s'exécute à partir de Form_Unload() Procédure d'événement lorsque vous fermez le formulaire. Cette méthode garantit que lorsque vous ouvrirez le contrôle ListView la prochaine fois, les données seront dans l'ordre que vous avez réorganisé la dernière fois.

Le Form_Unload() Code VBA de procédure d'événement.

Private Sub Form_Unload(Cancel As Integer)
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)

For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text 'EmployeeName
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp 'replace ID number
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

End Sub

Vérifiez le EmployeeName Valeur du champ dans l'image ci-dessus. Ils sont classés par ordre alphabétique. La nouvelle valeur du champ ID sur la table des employés sera mise à jour avec leur séquence actuelle de numéros d'index ListView Control ListItem.

Si vous notez les points suivants, vous pouvez facilement comprendre ce que nous faisons avec le code ci-dessus :

  1. Le texte de ListItem (première colonne) la valeur du paramètre est le nom de l'employé et classé par ordre alphabétique.

  2. Les éléments de liste sur le contrôle ListView ont des numéros d'index de 1 à 9 dans l'ordre dans lequel ils sont affichés à l'écran, c'est-à-dire que le numéro d'index du premier élément est 1 et le dernier est 9. Les données d'origine sur la valeur du champ ID de la table des employés ne sont pas dans cet ordre.

  3. Nous prenons le Texte Valeur (Nom de l'employé) du premier ListItem et recherchez le nom dans le tableau.

  4. Lorsque l'enregistrement est trouvé, le numéro d'index du ListItem actuel est mis à jour (remplacé) dans le champ ID de la table.

  5. Ce processus a été répété pour tous les enregistrements restants de la table.

Passons en revue le code VBA. Au début, nous vérifions si la table/requête de données source a été chargée dans le contrôle ListView ou non ?

Si la strTable La variable n'est pas initialisée avec le nom de la requête, alors le contrôle ListView est vide. Si tel est le cas, l'utilisateur a ouvert le formulaire et l'a fermé sans sélectionner le nom de la requête pour charger les données dans le contrôle ListView. Le Form_Unload La procédure événementielle est abandonnée à ce stade et ferme le formulaire.

Si le contrôle ListView contient des données, l'étape suivante est exécutée et ouvre la requête de données source EmployeesQ à mettre à jour.

L'étape suivante consiste à parcourir chaque ListItem et à mettre à jour le numéro d'index dans le champ ID de l'enregistrement Employés.

Tout d'abord, le numéro d'index de la ligne actuelle est enregistré dans le tmp variable.

Le premier nom lvwList.ColumnHeader EmployeeName et le nom de l'employé est extrait de ListItem.Text dans une expression dans les Critères variable de chaîne, comme EmployeeName ="Andrew Fuller".

Les premiers critères FindFirst La commande recherche dans la table de données Source pour trouver l'enregistrement portant le nom donné. Lorsque l'enregistrement est trouvé, le numéro d'index ListItem actuel est mis à jour dans le champ ID.

Ce processus est répété pour toutes les lignes du contrôle ListView et une fois terminé, le formulaire est fermé.

La prochaine fois que vous chargerez les enregistrements de cette requête dans le contrôle ListView, ils seront affichés dans le même ordre lorsque vous avez fermé le formulaire la dernière fois.

Remarque :La requête est devenue nécessaire ici pour trier les données sur le champ ID et les afficher dans l'ordre modifié sur le contrôle ListView.

Tout ce travail consistait à enregistrer les données dans le dernier ordre trié afin que la prochaine fois que vous ouvrirez le formulaire, les données du contrôle ListView soient dans cet ordre.

Explorateur Windows comme méthode de tri.

Dans l'Explorateur Windows, vous pouvez trier la liste affichée par ordre croissant ou décroissant en cliquant sur n'importe quel en-tête de colonne. L'en-tête de colonne fonctionnera comme un bouton bascule. Des clics répétés sur l'en-tête de colonne trieront les données de la colonne dans l'ordre croissant/décroissant selon le ListView1_ColumnClick() suivant Procédure d'événement :

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control is
' sorted by the subitems of that column.

With Me.ListView1
' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 ' Set Sorted to True to sort the list.
     .Sorted = True
End With
End Sub

Remarque : Le tri de toutes les données est en mode de comparaison de texte uniquement. Les éléments de liste et ListSubItems Ajouter() troisième paramètre de la méthode, les informations affichées sur le contrôle ListView sont Text taper. Les valeurs de date et numériques sont toutes traitées comme du texte uniquement.

L'Explorateur Windows enregistre le dernier ordre trié des éléments dans le dossier. Lorsque nous ouvrirons à nouveau ce dossier, la liste sera affichée dans l'ordre de tri précédent.

Avec le Form_Unload() Procédure d'événement cette fonctionnalité de l'explorateur Windows devient possible sur la table des employés. Lorsque vous fermez le formulaire après avoir trié sur n'importe quelle colonne, cette séquence de commande indexée sera enregistrée dans la table des employés dans le champ ID. La requête EmployeesQ trie toujours les données sur le champ ID lorsqu'il est ouvert.

La base de données de démonstration est jointe pour le téléchargement. Il existe deux formulaires de démonstration dans la base de données. Le premier formulaire illustre l'ouverture de tables et de requêtes dans le contrôle ListView pour afficher les données en mode feuille de données. Le deuxième formulaire utilise uniquement le EmployeesQ Requête seule pour glisser, déposer, trier et enregistrer le dernier ordre de tri des données pour une utilisation future.



  1. Tutoriel de contrôle ActiveX ListView-01.
  2. Tutoriel de contrôle ListView-02.
  3. Affectation d'images à des éléments ListView.
  4. Événements de tri par glisser-déposer de contrôle ListView
  5. Contrôle ListView avec MS-Access TreeView
  6. TreeView/ListView contrôle les événements glisser-déposer