Formules Min-Moyenne-Max en VBA
Bonjour le forum et bon dimanche,
Pour le besoin d'alléger mon fichier, j'ai commencé a mettre un substitut de formules Excel en VBA, j'ai déjà gagné quelques Ko et je dois continuer sur une feuille qui ralentit sensiblement l'exécution de macro car elle semble trop sollicité.
J'ai un tableau structuré ( TabDonnees) avec des prix de produits par mois de janvier a décembre (10 Colonnes)
je cherche a mettre les Formules MIN, MOYENNE, MAX, sous forme de valeurs et non incrémenter la formule dans les cellules. Grace a mon bouton de commande (CommandButton1) de l'UserFome1. le code se trouverait dans un module. je dois me servir du tableau structuré pour écrire les codes pour ne pas avoir de lignes vides dans le tableau Excel.
Avant de poster cette demande , j'ai passé quelques heures a faire et défaire et encore faire faire et défaire, essayé l'enregistreur de macro, je n'y parvient pas! l'écriture du code avec le tableau structuré me pose des soucis.
Merci beaucoup a tout ceux qui pourront me donner un petit coups de pouce.
J'ai laissé les formules Excel sur les 1er lignes (colonne N, O, P) du tableau pour référence a ma demande
MIN dans la colonne N ("TabDonnees[Meilleur Prix]")
MOYENNE dans la colonne O ("TabDonnees[Moyenne]")
MAX dans la colonne P ("TabDonnees[Prix le plus haut]")
je vous souhaites un bon dimanche et merci comme toujours pour votre précieuse aide.
Bonjour,
Merci pour ta réponse, je cherche vraiment la solution en code VBA, je dois avouer que je ne connais absolument rien a Power Query, (je devrais certainement m'y pencher bientôt)
J'ai peur d'incrémenter quelque chose dans le fichier sans savoir comment ca fonctionne.
Merci quand même
Et aussi, je dois passer par mon bouton de commande pour déclencher le code qui mettra a jour toutes les cellules de la colonne N,O,P du tableau structuré.
merci encore et bon dimanche également
bonjour, 3 propositions, de plus en plus en mémoire ... (mais en temps d'éxécution, nulle différence)
Sub Teste1()
Dim aOut, c, t, i, k
t = Timer
Set c = Sheets("feuil1").ListObjects(1).DataBodyRange 'vos données
ReDim aOut(1 To c.Rows.Count, 1 To 3) 'dimensioner matrice pour les résultats
k = c.Columns.Count - 3 'nombre de colonnes avec des données
For i = 1 To c.Rows.Count 'boucle les lignes
aOut(i, 1) = WorksheetFunction.Min(c(i, 1).Resize(, k)) 'meilleur prix
aOut(i, 2) = WorksheetFunction.Average(c(i, 1).Resize(, k)) 'moyenne
aOut(i, 3) = WorksheetFunction.Max(c(i, 1).Resize(, k)) 'max prix
Next
c.Cells(1, k + 1).Resize(UBound(aOut), UBound(aOut, 2)).Value = aOut 'coller les résultat
MsgBox Format(Timer - t, "0.00\s")
End Sub
Sub Teste2()
Dim aOut, c, t, i, k, aa
t = Timer
Set c = Sheets("feuil1").ListObjects(1).DataBodyRange 'vos données
ReDim aOut(1 To c.Rows.Count, 1 To 3) 'dimensioner matrice pour les résultats
k = c.Columns.Count - 3 'nombre de colonnes avec des données
For i = 1 To c.Rows.Count
aa = c.Cells(i, 1).Resize(, k).Value
aOut(i, 1) = WorksheetFunction.Min(aa) 'meilleur prix
aOut(i, 2) = WorksheetFunction.Average(aa) 'moyenne
aOut(i, 3) = WorksheetFunction.Max(aa) 'max prix
Next
c.Cells(1, k + 1).Resize(UBound(aOut), UBound(aOut, 2)).Value = aOut 'coller les résultat
MsgBox Format(Timer - t, "0.00\s")
End Sub
Sub Teste3()
Dim aOut, c, t, i, k, aA, j, aB
t = Timer
Set c = Sheets("feuil1").ListObjects(1).DataBodyRange 'vos données
ReDim aOut(1 To c.Rows.Count, 1 To 3) 'dimensioner matrice pour les résultats
k = c.Columns.Count - 3 'nombre de colonnes avec des données
aB = c.Value
ReDim aA(1 To k)
For i = 1 To c.Rows.Count
For j = 1 To k: aA(j) = aB(i, j): Next
aOut(i, 1) = WorksheetFunction.Min(aA) 'meilleur prix
aOut(i, 2) = WorksheetFunction.Average(aA) 'moyenne
aOut(i, 3) = WorksheetFunction.Max(aA) 'max prix
Next
c.Cells(1, k + 1).Resize(UBound(aOut), UBound(aOut, 2)).Value = aOut 'coller les résultat
MsgBox Format(Timer - t, "0.00\s")
End SubBonsoir Bart,
merci infiniment pour ce code, j'ai chois le Teste1 et avec le fichier que j'ai mis comme exemple c'est vraiment ce que je cherche, je joue avec depuis quelques minutes maintenant et tout fonctionne vraiment bien a quelques détails que je voudrais vous faire part si vous êtes d'accord.
- quand il n'y a pas de montant ou un si il y a un caractère du style #REF entre le mois de janvier et décembre ca bogue
le plus important (j'aurais du le mentionner, on est jamais assez trop précis) c'est que j'ai 20 autres colonnes a gauche du mois de janvier donc quand j'ai essayé de transposer votre code dans mon fichier, ca ne fonctionne pas. je pense que le code prend toutes les données a partir de la 1er colonne.
J'ai bien essayé de changer (mes données) dans la 1er ligne du code mais sans succès
pouvez vous m'aider a configurer votre code, je ne le comprend pas entièrement.
merci énormément
Finalement a force de jouer dedans , vois ce que j'ai trouvé et qui a l'air de fonctionner. ce n'est peut-être pas la bonne façon d'écrire mais mes faibles connaissances ne me permettent pas de m'y prendre autrement.
Sub Teste1()
Dim aOut, t, i, k
t = Timer
Dim c As Range
With Sheets("Feuil1")
Set c = .Range(.Cells(4, 21), .Cells(.UsedRange.Rows.Count, .Cells(4, Columns.Count).End(xlToLeft).Column))
ReDim aOut(1 To c.Rows.Count, 1 To 3) 'dimensioner matrice pour les résultats
k = c.Columns.Count - 3 'nombre de colonnes avec des données
For i = 1 To c.Rows.Count 'boucle les lignes
aOut(i, 1) = WorksheetFunction.Min(c(i, 1).Resize(, k)) 'meilleur prix
aOut(i, 2) = WorksheetFunction.Average(c(i, 1).Resize(, k)) 'moyenne
aOut(i, 3) = WorksheetFunction.Max(c(i, 1).Resize(, k)) 'max prix
Next
c.Cells(1, k + 1).Resize(UBound(aOut), UBound(aOut, 2)).Value = aOut 'coller les résultat
MsgBox Format(Timer - t, "0.00\s")
End With
End Sub
Par contre si possible de me dire quand une ligne est vide de janvier a décembre ou encore il y a une #REF de pouvoir malgré tout continuer le code sans qu'il se bloque.
- il y a aussi le code pour la moyenne qui se bloque quand je n'ai qu'eu seul prix entre janvier et décembre.
merci infiniment pour votre aide, et de vous êtes pencher sur mon petit soucis
cousin,
C'est bien correct, je comprends que certaines choses te dérange mais je fais avec les moyens du bord et surtout tu ne sais pas ou je suis rendu avec mon fichier.
je fais avec le temps que j'ai et crois moi je n'en ai pas beaucoup a consacrer . Pour la moquerie, j'en ai pas besoin non plus !
sur ce bonne soirée
Pour ceux que ca pourrait intéressé, le code ne bloque plus avec l'insertion ses deux ligne de plus.
bonne fin de dimanche et merci beaucoup pour ton aide Bard
Sub PrixMinMoyenneMax()
Dim aOut, t, i, k
t = Timer
Dim c As Range
With Sheets("Base_Données")
Set c = .Range(.Cells(4, 21), .Cells(.UsedRange.Rows.Count, .Cells(4, Columns.Count).End(xlToLeft).Column))
ReDim aOut(1 To c.Rows.Count, 1 To 3) 'dimensioner matrice pour les résultats
k = c.Columns.Count - 3 'nombre de colonnes avec des données
On Error Resume Next
For i = 1 To c.Rows.Count 'boucle les lignes
aOut(i, 1) = WorksheetFunction.Min(c(i, 1).Resize(, k)) 'meilleur prix
aOut(i, 2) = WorksheetFunction.Average(c(i, 1).Resize(, k)) 'moyenne
aOut(i, 3) = WorksheetFunction.Max(c(i, 1).Resize(, k)) 'max prix
Next
c.Cells(1, k + 1).Resize(UBound(aOut), UBound(aOut, 2)).Value = aOut 'coller les résultat
MsgBox Format(Timer - t, "0.00\s")
On Error GoTo 0
End With
End Sub
re,
worksheetfunction.aggregate --> https://learn.microsoft.com/fr-fr/office/vba/api/excel.worksheetfunction.aggregate
Sub Teste1()
Dim aOut, c, t, i, k, x
t = Timer
Set c = Range("TabDonnees[[Prix_Jan]:[Prix Dec]]") 'les données (=prix) de ces mois sans l'entête
ReDim aOut(1 To c.Rows.Count, 1 To 4) 'dimensioner matrice pour les résultats
k = c.Columns.Count 'nombre de colonnes de cette plage
For i = 1 To c.Rows.Count 'boucle les lignes
Set c1 = c(i, 1).Resize(, k) 'une ligne de cette plage (Jan->Dec)
If WorksheetFunction.Count(c1) > 0 Then 'min 1 cellule avec données "numériques"
'explication aggregate : https://learn.microsoft.com/fr-fr/office/vba/api/excel.worksheetfunction.aggregate
aOut(i, 1) = WorksheetFunction.Aggregate(5, 6, c1) 'meilleur prix (sans erreurs)
aOut(i, 2) = WorksheetFunction.Aggregate(1, 6, c1) 'moyenne (sans erreurs)
aOut(i, 3) = WorksheetFunction.Aggregate(4, 6, c1) 'max prix (sans erreurs)
aOut(i, 4) = WorksheetFunction.Aggregate(2, 6, c1) 'nombre de données numeriques
End If
Next
Range("TabDonnees[Meilleur]").Resize(UBound(aOut), UBound(aOut, 2)).Value = aOut 'coller le résultat à partir de la colonne "Meilleur"
MsgBox Format(Timer - t, "0.00\s")
End Sub
Un très grand Merci . En plus bien expliqué, ca fonctionne super bien. Je vais m'amuser un peu avec ce nouveau code.
en vous souhaitant une belle soirée