ListView Control se charge très lentement
-
03-07-2019 - |
Question
Quel est le moyen le plus rapide de remplir ListView à partir d’une requête lorsque celle-ci contient plus de 15 000 listes avec 9 sous-éléments. cela me prend environ 6 minutes pour charger.
Voici ce que j'ai écrit pour remplir le contrôle ListView.
Set rs = db.OpenRecordset(strSQL, dbOpenForwardOnly, dbReadOnly)
With Me.listViewData
.View = lvwReport
.GridLines = True
.FullRowSelect = True
.ListItems.Clear
.ColumnHeaders.Clear
End With
'Set up column headers
With Me.listViewData.ColumnHeaders
.Add , , "Client", 1440, lvwColumnLeft
.Add , , "Contact", 2160, lvwColumnLeft
.Add , , "Quote #", 720, lvwColumnCenter
.Add , , "Date", 1140, lvwColumnLeft
.Add , , "GrandTotal", 1440, lvwColumnRight
.Add , , "Weighted Value", 1440, lvwColumnRight
.Add , , "Chance %", 500, lvwColumnRight
.Add , , "Sales Cycle", 1140, lvwColumnRight
.Add , , "Won Orders", 1000, lvwColumnRight
.Add , , "SalesRep", 1000, lvwColumnRight
End With
While Not rs.EOF
Set lstItem = Me.listViewData.ListItems.Add()
lstItem.Text = Nz(rs!Name, "")
lstItem.SubItems(1) = Nz(rs!Company, "")
lstItem.SubItems(2) = Nz(rs!QuoteNumber, "")
lstItem.SubItems(3) = Nz(rs!OrderDate, "")
lstItem.SubItems(4) = Nz(Format(rs!GrandTotal, "Currency"), "0.00")
lstItem.SubItems(5) = Nz(Format(rs!GrandTotal * rs!Customfield1 / 100, "Currency"), "")
lstItem.SubItems(6) = Nz(rs!Customfield1, "")
lstItem.SubItems(7) = Nz(rs!Date1, "none")
lstItem.SubItems(8) = Nz(rs!Detail, "")
lstItem.SubItems(9) = Nz(rs!CustomT1, Nz(rs!UserID, ""))
For I = 1 To Me.listViewData.ColumnHeaders.Count - 1
Set sb = lstItem.ListSubItems(I)
If rs!Customfield1 = 100 Or Not IsNull(rs!List) Then
sb.ForeColor = vbBlue
lstItem.ForeColor = vbBlue
ElseIf rs!Cancelled = -1 Then
sb.ForeColor = vbRed
lstItem.ForeColor = vbRed
Else
sb.ForeColor = vbBlack
lstItem.ForeColor = vbBlack
End If
DoEvents
Next
rs.MoveNext
Wend
La solution 2
Je peux penser à quelques choses:
While ... Wend est un mécanisme de boucle plus lent. utiliser pour ... Suivant. Pour ... Next est plus rapide - même si vous devez exécuter une autre commande pour obtenir RecordCount. Voici ce que j'utilise:
With rs
If .RecordCount > 0 Then
'-- MoveLast...MoveFirst will update the .RecordCount; depending on the type of DAO Recordset, RecordCount might only return "1" when there are more than that.
.MoveLast
.MoveFirst
For lngCounter = 1 To .RecordCount
'-- Code to add ListItems here
.MoveNext
Next lngCounter
End If
.Close
End With
Utiliser avec ... Terminer avec pour ajouter vos sous-éléments:
With Me.listViewData.ListItems.Add
.Text = Nz(rs!Name, "")
.SubItems(1) = Nz(rs!Company, "")
.SubItems(2) = Nz(rs!QuoteNumber, "")
.SubItems(3) = Nz(rs!OrderDate, "")
.SubItems(4) = Nz(Format(rs!GrandTotal, "Currency"), "0.00")
.SubItems(5) = Nz(Format(rs!GrandTotal * rs!Customfield1 / 100, "Currency"), "")
.SubItems(6) = Nz(rs!Customfield1, "")
.SubItems(7) = Nz(rs!Date1, "none")
.SubItems(8) = Nz(rs!Detail, "")
.SubItems(9) = Nz(rs!CustomT1, Nz(rs!UserID, ""))
End With
Enroulez le code de population dans:
DoCmd.Echo False
'-- Populate code
DoCmd.Echo True
J'espère que ça aide!
Autres conseils
La première chose à faire est de vous débarrasser de "doevents". C'est un vrai tueur de performance.
Devez-vous charger dynamiquement la listview? Pourquoi ne pas le lier directement à une source de données?
Vérifiez les méthodes du contrôle Listview pour des informations telles que beginupdate / endupdate ou définissez refresh sur false (si possible). Cela signifie que l'interface utilisateur n'essaiera pas d'actualiser l'écran après l'ajout de chaque élément, ce qui le rendra beaucoup plus rapide.
Le contrôle Listview est conçu pour prendre un grand nombre d’éléments, ce qui devrait être possible avec un peu de fouille.