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.
-
Créez une nouvelle table avec un seul champ de texte, avec le nom de champ DataList .
-
Enregistrez la table avec le nom lvTables (lv signifie ListView).
-
Ouvrez la table en mode Feuille de données.
-
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.
-
Créez et ouvrez un nouveau formulaire en mode Création.
-
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 .
-
Modifier son étiquette enfant Caption valeur aux Tableaux .
-
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.
-
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.
-
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 .
-
Redimensionnez les deux contrôles comme indiqué sur l'image de formulaire de démonstration ci-dessus.
-
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.
-
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 .
-
Cliquez avec le bouton droit sur le contrôle ListView, mettez en surbrillance l'objet ListViewCtrl et sélectionnez Propriétés .
-
Modifiez les paramètres de propriété pour qu'ils correspondent aux paramètres de Général Image de l'onglet ci-dessous.
-
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 :
-
Le texte de ListItem (première colonne) la valeur du paramètre est le nom de l'employé et classé par ordre alphabétique.
-
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.
-
Nous prenons le Texte Valeur (Nom de l'employé) du premier ListItem et recherchez le nom dans le tableau.
-
Lorsque l'enregistrement est trouvé, le numéro d'index du ListItem actuel est mis à jour (remplacé) dans le champ ID de la table.
-
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.
- Tutoriel de contrôle ActiveX ListView-01.
- Tutoriel de contrôle ListView-02.
- Affectation d'images à des éléments ListView.
- Événements de tri par glisser-déposer de contrôle ListView
- Contrôle ListView avec MS-Access TreeView
- TreeView/ListView contrôle les événements glisser-déposer