Traitement Efficace des Données
Glissez pour afficher le menu
Jusqu'à présent, tout a été traité cellule par cellule — suffisant pour cinq commandes, extrêmement lent pour cinquante mille. La solution consiste à ne plus manipuler la feuille cellule par cellule, mais à transférer tout le bloc dans un tableau en mémoire, à y effectuer les traitements, puis à le réécrire en une seule opération.
Lecture d'une plage dans un tableau
Dim dataArr As Variant
dataArr = ws.Range("A2:I6").Value ' one read, not 45 individual reads
dataArr est désormais un tableau 2D en mémoire : dataArr(1,1) correspond à ORD1001, dataArr(1,4) à "Laptop Stand", etc. — les tableaux VBA lus depuis une plage sont indexés à partir de 1, et non de 0, ce qui est une source fréquente d'erreur.
Traitement du tableau
S'effectue avec des boucles classiques — mais cette fois, la boucle s'effectue en mémoire, ce qui est des milliers de fois plus rapide que de boucler sur la feuille de calcul :
Dim i As Long
Dim recalculated As Double
For i = 1 To UBound(dataArr, 1)
recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
Debug.Print "Mismatch on row " & i & ": sheet says " & dataArr(i, 8) & _
", recalculated " & Format(recalculated, "0.00")
End If
Next i
Réécriture du tableau
Là encore, une seule opération :
ws.Range("A2:I6").Value = dataArr
Éviter Select et Activate
Les macros enregistrées s'appuient fortement sur ces commandes (Range("A1").Select puis Selection.Font.Bold = True), mais elles sont inutiles et lentes — chaque .Select force Excel à redessiner l'écran. Référencez directement la plage ou l'objet à la place :
' Avoid:
ws.Range("A1").Select
Selection.Font.Bold = True
' Prefer:
ws.Range("A1").Font.Bold = True
Considérations de performance
Ces aspects deviennent importants dès que vos données dépassent quelques centaines de lignes :
Application.ScreenUpdating = False ' stop redrawing while the macro runs
Application.Calculation = xlCalculationManual ' pause recalculation
Application.EnableEvents = False ' suppress other macros triggering mid-run
' ... your fast array-based code here ...
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Toujours restaurer ces paramètres à la fin — et encapsuler la restauration dans une gestion d'erreur pour éviter qu'un plantage en cours d'exécution ne laisse Excel avec l'affichage désactivé.
Exemple pratique : le vérificateur d'intégrité des commandes
Ce chapitre aboutit à ceci :
Option Explicit
Sub VerifyOrderTotals()
Dim ws As Worksheet
Dim dataArr As Variant
Dim lastRow As Long
Dim i As Long
Dim recalculated As Double
Dim issues As String
Set ws = ThisWorkbook.Worksheets("Orders")
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Application.ScreenUpdating = False
dataArr = ws.Range("A2:I" & lastRow).Value
issues = ""
For i = 1 To UBound(dataArr, 1)
recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
issues = issues & dataArr(i, 1) & ": sheet=" & dataArr(i, 8) & _
", expected=" & Format(recalculated, "0.00") & vbNewLine
End If
Next i
Application.ScreenUpdating = True
If issues = "" Then
MsgBox "All " & UBound(dataArr, 1) & " order totals check out."
Else
MsgBox "Discrepancies found:" & vbNewLine & issues
End If
End Sub
Exécutez ce code sur la table d'exemple et il devrait indiquer que les cinq totaux sont corrects — essayez de modifier le Total de ORD1002 dans la feuille avec une valeur erronée puis relancez pour voir l'alerte s'afficher.
Tâche
- Copier
VerifyOrderTotalsdans votre classeur et l'exécuter sur les cinq commandes d'exemple. - Modifier manuellement le
Totald'une commande sur la feuille (saisir une valeur manifestement incorrecte) puis relancer — vérifier que l'écart est bien signalé avec le bonOrder ID. - Ajouter dix lignes supplémentaires de commandes fictives sous la ligne 6, et vérifier que la macro fonctionne toujours sans modification du code — c'est l'intérêt de
lastRowet du traitement par tableau.
Assistant facultatif si vous préférez générer les dix lignes supplémentaires en code plutôt que de les saisir manuellement :
Sub AddTestOrders()
Dim ws As Worksheet
Dim i As Long
Dim r As Long
Set ws = ThisWorkbook.Worksheets("Orders")
r = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1
For i = 1 To 10
ws.Cells(r, 1).Value = "ORD" & (1005 + i)
ws.Cells(r, 2).Value = Date
ws.Cells(r, 3).Value = "Test Customer " & i
ws.Cells(r, 4).Value = "Sample Product"
ws.Cells(r, 5).Value = i
ws.Cells(r, 6).Value = 20 + i
ws.Cells(r, 7).Value = 0.05
ws.Cells(r, 8).Value = i * (20 + i) * (1 - 0.05)
ws.Cells(r, 9).Value = "Pending"
r = r + 1
Next i
End Sub
1. Copier VerifyOrderTotals
- Saisir la procédure
Subexactement comme présentée dans la section 3.5 dans le module de votre classeur — aucune modification nécessaire pour l’instant. - Exécuter une fois sur les cinq lignes d’origine et vérifier que vous obtenez « All 5 order totals check out. »
2. Modifier volontairement un Total
- Choisir la cellule Total de n’importe quelle commande et saisir un nombre manifestement incorrect directement dans la feuille (pas via le code).
- Relancer la même procédure
Sub— le message d’erreur doit indiquer précisément l’ID de la commande concernée, ainsi que la valeur présente dans la feuille et celle recalculée par la macro. - Corriger la cellule ensuite si vous souhaitez une feuille propre pour l’étape suivante.
3. Ajouter dix lignes supplémentaires
- Saisir simplement de nouvelles données de commande directement dans les lignes 7 à 16 — mêmes neuf colonnes, valeurs plausibles au choix.
- Ne pas toucher à la macro.
lastRowse recalcule à chaque exécution duSub, et la lecture du tableau (ws.Range("A2:I" & lastRow).Value) s’ajuste automatiquement — c’est tout l’intérêt de la démonstration.
Option Explicit
Sub VerifyOrderTotals()
Dim ws As Worksheet
Dim dataArr As Variant
Dim lastRow As Long
Dim i As Long
Dim recalculated As Double
Dim issues As String
Set ws = ThisWorkbook.Worksheets("Orders")
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Application.ScreenUpdating = False
dataArr = ws.Range("A2:I" & lastRow).Value
issues = ""
For i = 1 To UBound(dataArr, 1)
recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
issues = issues & dataArr(i, 1) & ": sheet=" & dataArr(i, 8) & _
", expected=" & Format(recalculated, "0.00") & vbNewLine
End If
Next i
Application.ScreenUpdating = True
If issues = "" Then
MsgBox "All " & UBound(dataArr, 1) & " order totals check out."
Else
MsgBox "Discrepancies found:" & vbNewLine & issues
End If
End Sub
Merci pour vos commentaires !
Demandez à l'IA
Demandez à l'IA
Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion