Tableaux, ubound, moyenne sous contraintes
Bonjour!
D'accord
Re,
J'ai trouvé un code qui marche!! mais il me donne la bonne moyenne une fois sur deux
Et j'ai pour cette remarque:
Oui parce que les éléments de I_PACAGE ont déjà été triés avec le dictionnaire dans la feuille de résultats, et comme l'ordre sera toujours le même alors je veux juste afficher les nouveaux résultats à la suite du tableau!...Car je persiste à penser que tu auras des moyennes dont tu ne sauras plus à quoi elles peuvent correspondre...
Pas eu le temps de regarder...
J'ai toutefois fait rapidement une adaptation de la fin de la macro initiale (j'ai laissée les lignes supprimées en les invalidant comme repère) :
'b = ip.Keys
s = ip.Items
ReDim v(UBound(b) - (UBound(b) < 0), 0)
For i = 0 To UBound(b)
'v(i, 0) = b(i)
v(i, 0) = s(i)(0) / s(i)(1)
Next
Set plage = Worksheets("feuil1").Range("A1").End(xlToRight)(2, 1)
plage.Resize(i - (i = 0)).Value = v
plage.Offset(-1) = "moy. xxx"La dernière ligne est ajoutée pour le cas (qui m'avait semblé dans tes intentions) où tu lances le calcul plusieurs fois après modif du tableau, la recherche de la colonne sefaisant sur la ligne 1, il faut qu'une valeur soit mise dans la cellule si on veut conserver chaque résultat, pour ne pas qu'il écrase le précédent. Donc modifier ce qui est à mettre le cas échéant...
Cordialement.
Bonjour MFerrand!
Tout d'abord un grand merci pour le temps consacré à m'aider! J'ai utilisé la méthode que vous m'avez proposée et ça convient parfaitement!! J'ai juste modifié quelques points car il y avait une erreur d'indice...
J'était sur le point de poster une nouvelle question
Je continue mon travail! Bonne journée!!
Rebonjour!
Décidément il y a toujours une surprise!
v(0) = v(0) + (s(i, 1) * t(i, 1))! La seul différence c'est que les moyennes sont copiées sur une autre feuille...
Option Explicit
Option Base 0
Sub moy_pentes()
Dim dat1 As Range, dat2 As Range, dat3 As Range, plage As Range
Dim i&, b(), s(), v(), t()
Dim ip As Object
With Worksheets("donnees_totales")
Set ip = CreateObject("scripting.dictionary")
Set dat1 = Worksheets("donnees_totales").Range(.Range("C1"), .Range("C1").End(xlDown))
Set dat2 = Worksheets("donnees_totales").Range(.Range("M1"), .Range("M1").End(xlDown))
Set dat3 = Worksheets("donnees_totales").Range(.Range("K1"), .Range("K1").End(xlDown))
b = dat1.Value
s = dat2.Value
t = dat3.Value
For i = 2 To UBound(b)
If Not IsEmpty(b(i, 1)) And Not IsEmpty(s(i, 1)) And IsNumeric(s(i, 1)) Then
If ip.Exists(b(i, 1)) Then
v = ip(b(i, 1))
v(0) = v(0) + (s(i, 1) * t(i, 1)): v(1) = v(1) + t(i, 1)
ip(b(i, 1)) = v
Else
ip.Add b(i, 1), Array((s(i, 1) * t(i, 1)), t(i, 1))
End If
End If
Next
'b = ip.Keys
s = ip.Items
ReDim v(UBound(s) - (UBound(s) < 0), 1 To 1)
For i = 0 To UBound(s)
'v(i, 1) = b(i)
v(i, 1) = s(i)(0) / s(i)(1)
Next
Set plage = Worksheets("resultats").Range("A1").End(xlToRight)(2, 2)
plage.Resize(i - (i = 0)).Value = v
plage.Offset(-1) = "moy. pondérée"
End With
End Subça marche quand je mets le code dans un module à part!!
Bonne soirée! A+
Est-ce que t est toujours défini et numérique ? Tu ne le testes pas comme les autres....
Re,
Effectivement mais ça ne marchait toujours pas, et en fait c'est à cause de la base!
Je conseille toujours de ne pas utiliser Option Base 1.
C'est un truc à s'emmêler les pinceaux, et il est plus simple lorsque tu veux baser autrement tu le fasses en dimensionnant :
Dim ou ReDim tablo(1 To 2)
Redim tablo (-10 To 0)...
D'accord c'est noté! Merci pour le conseil!
IL y a une nouvelle opération que j'aimerais mettre en place... Je n'ai pas créer un nouveau poste car pour le moment j'ai besoin d'un conseil ou plutôt d'une réponse à deux questions (et après il me faudra sûrement beaucoup de temps pour faire le tour de ce problème!
Je pense que la "feuil1" de la PJ montre tout de suite ce que je cherche à faire mais s'il le faut je peux mieux expliquer...)
1-Est-ce que c'est possible (je pense que la réponse est oui mais en fait je ne sais pas!...) Sinon quel est le résultat le plus proche que je pourrais chercher?
2- Dois-je utiliser 1 ou 2 dictionnaires?
Je suis déjà entrain d'essayer mais si c'est possible, une réponse à ces deux questions ça va me motiver!
Bonjour,
C'est bien sûr possible puisque tu le démontres déjà manuellement !
L'idée de 2 dictionnaires peut s'avérer intéressante : un dont la clé est l'i-pacage où tu totalises les surfaces qui y correspondent (qui sera le dénominateur de ton calcul), l'autre dont la clé concatène i-pacage et type (de façon à avoir une correspondance entre les deux) où tu totalises les surfaces par type.
Tu n'as même pas besoin de passer par des tableaux : pour chaque clé du premier (affectée à la première cellule), tu parcours le second, et à chaque élément rattaché, tu extrais le type, tu calcules le % (quotient des valeurs mise en forme) et tu construis progressivement la chaîne à affecter à ta 2e cellule.
Cordialement.
edit : Quoique ta variable d'affectation peut être un tableau, à construire pas à pas avec Redim Preserve, et tu peux l'affecter par :
= Join(tablo, "-")
Merci pour cette réponse rapide!
D'accord remarque intéressante!
C'est un peu ce à quoi je pensais! Et je pense qu'en suivant ce plan ça va le faire!
Merci encore pour tout!!
Merci encore pour tout!!
et bonne soirée!!
Il est 8h20 chez moi...
Lol!Désolé!! J'avais une chance sur deux!!
Bonjour le fil,
Pour ta nouvelle demande, tu peux en effet utiliser un dictionnaire principal associé à un sous-dictionnaire.
Vois ceci :
Option Explicit
Sub test()
Dim a, b(), i As Long, n As Long, w()
Dim x As Double, y As Double, e, v, res As Byte
ReDim w(1 To 3)
With Sheets("Feuil1").Range("a1").CurrentRegion
a = .Value
ReDim b(1 To UBound(a, 1), 1 To 2)
b(1, 1) = a(1, 1): b(1, 2) = a(1, 3)
n = 1
With CreateObject("Scripting.Dictionary")
.CompareMode = 1
For i = 2 To UBound(a, 1)
If Not .exists(a(i, 1)) Then
n = n + 1
w(1) = n: w(2) = a(i, 2)
Set w(3) = _
CreateObject("Scripting.Dictionary")
w(3).CompareMode = 1
w(3)(a(i, 3)) = a(i, 2)
.Item(a(i, 1)) = w
Else
w = .Item(a(i, 1))
If Not w(3).exists(a(i, 3)) Then
w(3)(a(i, 3)) = a(i, 2)
Else
w(3)(a(i, 3)) = w(3)(a(i, 3)) + a(i, 2)
End If
w(2) = w(2) + a(i, 2)
.Item(a(i, 1)) = w
End If
Next
For Each e In .keys
n = .Item(e)(1): x = .Item(e)(2)
'Set w = .Item(e)(3)
b(n, 1) = e
For Each v In .Item(e)(3)
y = .Item(e)(3)(v)
res = CInt(y / x * 100)
If Not IsEmpty(b(n, 2)) Then
b(n, 2) = b(n, 2) & " - " & v & "(" & res & "%)"
Else
b(n, 2) = v & "(" & res & "%)"
End If
Next
Next
End With
Application.ScreenUpdating = False
With .Offset(, .Columns.Count + 1).Resize(n, 2)
.CurrentRegion.Clear
.Value = b
With .CurrentRegion
With .Rows(1)
.Font.Bold = True
.BorderAround Weight:=xlThin
.Interior.ColorIndex = 36
End With
.BorderAround Weight:=xlThin
.Borders(xlInsideVertical).Weight = xlThin
.Font.Name = "calibri"
.Font.Size = 10
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlCenter
.Columns.AutoFit
End With
End With
Application.ScreenUpdating = True
End With
End Subklin89
Bonjour!
Ce code marche comme sur des bits!