XL 2010 Passer de Dico à Array avec Split

cp4

XLDnaute Barbatruc
Bonsoir:),

J'ai eu beau chercher je ne suis pas parvenu à trouver une réponse.
J'ai utilisé un dictionnaire pour faire la somme pour chaque personne (nom, prénom dans les colonnes différentes).
Jusque là, pas de problème. Maintenant, je voudrais repasser vers un autre tableau pour séparer les noms, prénoms et le montants.
Je crois savoir que la fonction split est tout indiquée à mon problème. Mais, j'avoue que je suis perdu.
VB:
For i = 1 To UBound(Tb)
d(Tb(i, 2) & "|" & Tb(i, 3)) = d(Tb(i, 2) & "|" & Tb(i, 3)) + Tb(i, 16)
Next i

En vous remerciant par avance.
 
Solution
Moi je faisais comme ça :
VB:
Sub EssaiDranreb()
   Dim TDon(), LDon As Long, TRés(), LRés As Long, Clé As String, Dic As New dictionary
   TDon = ActiveSheet.[A1].CurrentRegion.Value
   ReDim TRés(1 To UBound(TDon, 1), 1 To 3)
   For LDon = 1 To UBound(TDon, 1)
      Clé = TDon(LDon, 2) & "|" & TDon(LDon, 3)
      If Dic.exists(Clé) Then
         LRés = Dic(Clé)
         TRés(LRés, 3) = TRés(LRés, 3) + TDon(LDon, 16)
      Else
         LRés = Dic.Count + 1: Dic(Clé) = LRés
         TRés(LRés, 1) = TDon(LDon, 2)
         TRés(LRés, 2) = TDon(LDon, 3)
         TRés(LRés, 3) = TDon(LDon, 16)
         End If
      Next LDon
   ActiveSheet.[V1].Resize(Dic.Count, 3) = TRés
   End Sub

Staple1600

XLDnaute Barbatruc
Re

Résultat: 7 secondes et des poussières
Ce m'a donné le temps de pondre ceci ;)
VB:
Sub InitStaple()
Dim r As Range
Set r = Range("A2:P100000")
Application.ScreenUpdating = False
r = _
Array("=row()-1", "=""Toto-"" & RANDBETWEEN(1,10000)", "=SUBSTITUTE(RC[-1],""o"",CHOOSE(RANDBETWEEN(1,3),""u"",""i"",""a""))", Empty, Empty, Empty, Empty, Empty, Empty, Empty, Empty, Empty, Empty, Empty, Empty, "=RANDBETWEEN(1,10000)/100")
r = r.Value
End Sub
;)
Ou cette variante
VB:
Sub InitStaple_II()
Dim r As Range: Set r = Range("A2:D100000")
Application.ScreenUpdating = False
r = Array("=row()-1", "=""Toto-"" & RANDBETWEEN(1,10000)", "=SUBSTITUTE(RC[-1],""o"",CHOOSE(RANDBETWEEN(1,3),""u"",""i"",""a""))", "=RANDBETWEEN(1,10000)/100")
r = r.Value
Columns("D:O").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
End Sub
 
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
Ce m'a donné le temps de pondre ceci

Je pense qu'il vaut mieux utiliser au maximum les fonctions natives de VBA plutôt que de passer par des fonctions Excel (dans de rares cas, ce n'est pas vrai).
Ici la version (presque entièrement) en mémoire prend environ 1 sec. (contre environ 3,9 sec. pour l'autre).
 

Pièces jointes

  • cp4- init- v1.xlsm
    18.3 KB · Affichages: 20

Staple1600

XLDnaute Barbatruc
Re

=>mapomme
L'eus-tu pensé sans notre échange en MP? ;)
Echange qui m'aura permis de faire juste un copier/coller pour tester. ;)
VB:
Sub Initmapomme()
Const nbrlig = 100000
Dim i&, c$, Ti
   Ti = Timer
   ReDim t(1 To nbrlig, 1 To 4)
   Randomize
   For i = 1 To UBound(t)
      t(i, 1) = i + 1
      t(i, 2) = "Toto" & (1 + Int(10000 * Rnd))
      Select Case Int(3 * Rnd)
         Case 0: t(i, 3) = Replace(t(i, 2), "o", "a")
         Case 1: t(i, 3) = Replace(t(i, 2), "o", "i")
         Case 2: t(i, 3) = Replace(t(i, 2), "o", "u")
      End Select
      t(i, 4) = Int(10000 * Rnd) / 100#
   Next i
   Application.ScreenUpdating = False
   Cells(2, "a").Resize(nbrlig, 3) = t
   Cells(2, "p").Resize(nbrlig) = Application.Index(t, 0, 4)
   MsgBox Format(Timer - Ti, "0.000\ sec.")
End Sub
Mon Excel tousse.
Je redémarre mon PC et reviens donné le résultat du MsgBox.
 

laurent950

XLDnaute Accro
Bonsoir,
Je pense que l'on peux découper en une seul fois la Keys ?
Voici Mon code :
VB:
Option Explicit
' code nécessite que la référence "Microsoft Scripting Runtime" soit activée
Sub essai2()
Dim Tb() As Variant
    Tb = Range("a1").CurrentRegion
Dim temp As Variant
Dim d As New Scripting.Dictionary
    Set d = New Dictionary
Dim i As Double

For i = LBound(Tb) + 1 To UBound(Tb)
    If d.Exists(Tb(i, 2) & "|" & Tb(i, 3)) Then
        d(Tb(i, 2) & "|" & Tb(i, 3)) = d(Tb(i, 2) & "|" & Tb(i, 3)) + Tb(i, 16) ' d.Keys(0) =  d.Items(0)
    Else
        d(Tb(i, 2) & "|" & Tb(i, 3)) = d(Tb(i, 2) & "|" & Tb(i, 3)) + Tb(i, 16) ' d.Keys(0) =  d.Items(0)
    End If
Next i

' Comment Découper la clef (Split) ?
[V1].Resize(d.Count) = Application.Transpose(d.Keys) ' Comment split en 1 fois (pour 2 colonnes)
[w1].Resize(d.Count) = Application.Transpose(d.Items)
End Sub
 
Dernière édition:

Staple1600

XLDnaute Barbatruc
Re,

•>Laurent950
Tu n'as pas du regarder le code de mapomme
(je me permets de le reposter ici)
Enrichi (BBcode):
Sub tabloSomm()     'mapomme
Dim t, dico As New Dictionary, i&, clef, ii&, j&, Ti

   Ti = Timer
   t = Range("a1").CurrentRegion
  Set dico = CreateObject("scripting.dictionary")
   dico.CompareMode = TextCompare
   For i = 2 To UBound(t)
      clef = Join(Array(t(i, 2), t(i, 3)), "|")
      If Not dico.Exists(clef) Then
         ii = dico.Count + 1
         dico(clef) = ii
         t(ii, 1) = t(i, 2): t(ii, 2) = t(i, 3): t(ii, 3) = t(i, 16)
      Else
         ii = dico(clef)
         t(ii, 3) = t(ii, 3) + t(i, 16)
      End If
   Next i

   ReDim r(1 To dico.Count, 1 To 3)
   For i = 2 To dico.Count + 1
      For j = 1 To 3
         r(i - 1, j) = t(i - 1, j)
      Next j
   Next i
   With Range("r1")
      .CurrentRegion.ClearContents: .Resize(UBound(r), 3) = r: .CurrentRegion.Borders.LineStyle = xlContinuous
   End With
   MsgBox Format(Timer - Ti, "0.000\ sec.")
End Sub
 

patricktoulon

XLDnaute Barbatruc
re
bonjour a tous
de bon matin a la fraîche
et si on économisez encore un peu
a partir du moment ou on réagence le tableau(t) dans la boucle dico
je ne vois aucune raison de le recopier dans un tableau(r)
il suffit simplement de redimensionner [R1]a II lignes et 3 colonnes
VB:
Sub tabloSomm()     'mapomme
Dim t, dico As New Dictionary, i&, clef, ii&, j&, Ti

   Ti = Timer
   t = Range("a1").CurrentRegion
   Set dico = CreateObject("scripting.dictionary")
   dico.CompareMode = TextCompare
   For i = 2 To UBound(t)
      clef = Join(Array(t(i, 2), t(i, 3)), "|")
      If Not dico.Exists(clef) Then
         ii = dico.Count + 1
         dico(clef) = ii
         t(ii, 1) = t(i, 2): t(ii, 2) = t(i, 3): t(ii, 3) = t(i, 16)
      Else
         ii = dico(clef)
         t(ii, 3) = t(ii, 3) + t(i, 16)
      End If
   Next i
   'ReDim r(1 To dico.Count, 1 To 3)
   'For i = 2 To dico.Count + 1
      'For j = 1 To 3
         'r(i - 1, j) = t(i - 1, j)
      'Next j
   'Next i
   With Range("r1")
      .CurrentRegion.ClearContents: .Resize(ii, 3) = t: .CurrentRegion.Borders.LineStyle = xlContinuous
   End With
   MsgBox Format(Timer - Ti, "0.000\ sec.")
End Sub
;)
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonjour à tous, @patricktoulon :)

a partir du moment ou on réagence le tableau(t) dans la boucle dico
je ne vois aucune raison de le recopier dans un tableau(r)

Tout simplement pour répondre à la question du demandeur @cp4 que je salue (l'affichage sur une feuille de calcul n'est pas demandé mais ça fait plus joli). ;)

Je rappelle la question :
Maintenant, je voudrais repasser vers un autre tableau pour séparer les noms, prénoms et le montants.
ou encore:
je voudrais construire un tableau (array)
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
RE
bonjour @mapomme
si ça n'est pas dérangeant l'utilisation d'un range tempo comme c'est le cas ici
ben après transfert dans le r1 resize --> t=r1.currentregion.value

voir même pourquoi l'ors des transfert dans t ne pas le faire dans un au tableau
les 2 boucles supplémentaires après serait toujours inutiles
2 tour de 28904 lignes sur 3 colonnes dans cet exemple au moment ou je l'ai essayé c'est pas rien

mais je le redis c'est vraiment pas mal ce coup du dico avec index dans item
 

mapomme

XLDnaute Barbatruc
Supporter XLD
voir même pourquoi l'ors des transfert dans t ne pas le faire dans un au tableau

La question est d'avoir le résultat dans un array avec le nombre de lignes juste nécessaire. Pour cela, il faudrait déterminer à l'avance le nombre de lignes résultats avant le traitement des lignes de t.
Je n'ai pas encore trouvé de solution élégante en utilisant uniquement les fonctions natives de VBA.
 

Discussions similaires

Statistiques des forums

Discussions
312 305
Messages
2 087 084
Membres
103 459
dernier inscrit
Arnocal