IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Simplification de boucles FOR avec concaténation ? [Toutes versions]


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Par défaut Simplification de boucles FOR avec concaténation ?
    Bonjour,

    J'ai débuté le codage sous VBA depuis pas longtemps, et je rencontre actuellement pour plusieurs de mes codes un problème récurrent.
    Lorsque je fais une boucle FOR quelconque, mais répétitive: je sui obligé d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    For i = 1 to 15
      Table1= blabla
    Next
     
    For i = 1 to 15
      Table2 = blibli
    Next
     
    etc...
    ou encore
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
       For Ne = 2 To 40
        ReDim TabC(3, 1): N°T = N°T + 1
        Select Case Ne
         Case Is = 2:  Result2 Cible, Np, TabC
         Case Is = 3:  Result3 Cible, Np, TabC
         Case Is = 4:  Result4 Cible, Np, TabC
         Case Is = 5:  Result5 Cible, Np, TabC
         Case Is = 6:  Result6 Cible, Np, TabC
         Case Is = 7:  Result7 Cible, Np, TabC
         Case Is = 8:  Result8 Cible, Np, TabC
         Case Is = 9:  Result9 Cible, Np, TabC
         Case Is = 10:  Result10 Cible, Np, TabC
         Case Is = 11:  Result11 Cible, Np, TabC
         Case Is = 12:  Result12 Cible, Np, TabC
         Case Is = 13:  Result13 Cible, Np, TabC
         Case Is = 14:  Result14 Cible, Np, TabC
         Case Is = 15:  Result15 Cible, Np, TabC
         Case Is = 16:  Result16 Cible, Np, TabC
         Case Is = 17:  Result17 Cible, Np, TabC
         Case Is = 18:  Result18 Cible, Np, TabC
         Case Is = 19:  Result19 Cible, Np, TabC
         Case Is = 20:  Result20 Cible, Np, TabC
         Case Is = 21:  Result21 Cible, Np, TabC
         Case Is = 22:  Result22 Cible, Np, TabC
         Case Is = 23:  Result23 Cible, Np, TabC
         Case Is = 24:  Result24 Cible, Np, TabC
         Case Is = 25:  Result25 Cible, Np, TabC
         Case Is = 26:  Result26 Cible, Np, TabC
         Case Is = 27:  Result27 Cible, Np, TabC
         Case Is = 28:  Result28 Cible, Np, TabC
         Case Is = 29:  Result29 Cible, Np, TabC
         Case Is = 30:  Result30 Cible, Np, TabC
         Case Is = 31:  Result31 Cible, Np, TabC
         Case Is = 32:  Result32 Cible, Np, TabC
         Case Is = 33:  Result33 Cible, Np, TabC
         Case Is = 34:  Result34 Cible, Np, TabC
         Case Is = 35:  Result35 Cible, Np, TabC
         Case Is = 36:  Result36 Cible, Np, TabC
         Case Is = 37:  Result37 Cible, Np, TabC
         Case Is = 38:  Result38 Cible, Np, TabC
         Case Is = 39:  Result39 Cible, Np, TabC
         Case Is = 40:  Result40 Cible, Np, TabC
        End Select
    Next
    J'ai plein de codes qui semblent "redondants" dans le même genre.
    J'essaie donc de simplifier pour le dernier exemple par exemple, avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    For Ne = 2 to 40
        ReDim TabC(3, 1): N°T = N°T + 1
        Select Case Ne
           Case Is = Ne:  ("Result" & Ne) Cible, Np, TabC
        End Select
    Next
    Il fait bien la concaténation, mais ne reconnait pas le nom généré Result26 (par exemple) comme étant une variable, mais comme une simple String (vide en l'occurence).
    ... et pas de bol misterVBA connait pas la fonction magique INDIRECT()

    Mes recherches sur google n'ont donné que des cas liés aux noms de feuilles, ou choper une valeur via une adresse(Range(Range())), ce qui n'est pas du tout le cas ici...

    En résumé, comment convertir une chaîne string en référence (d'un objet déjà existant) ? (dans mes codes, les objets sont en général des tableaux de type Variant/Variant)

    Merci d'avance pour vos réponses.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 130
    Par défaut
    Salut Masamunai et le forum
    Tu comme ci et si ça ne marche pas, tu fais comme ça
    Et si tu ne comprends pas, alors explique clairement ce que tu veux, pas la manière que tu utilises, mais le but. On ne peux simplifier une macro, il faut savoir ce qu'elle doit faire. La méthode utilisée n'est intéressante que pour éviter de l'avoir en réponse.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     For Ne = 2 To 40
        ReDim TabC(3, 1): N°T = N°T + 1
        Select Case Ne
         Case Is = 2:  Result2 Cible, Np, TabC
    Je ne suis pas suis de ce que tu veux faire : Redim est une instruction pour redimensionner un tableau de variable, ici TabC, mais tu ne le redimensionnes pas, puisque ses dimensions sont en "dur" (3 et 1).
    Select Case est intéressant pour assurer un certain nombre de test, mais si tu ne veux que tester une seule valeur, un simple If suffit.
    A+

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Par défaut
    A ben désolé si je n'ai pas été clair malgré le titre du topic et 2 exemples... mais merci pour ta réponse.

    Mon but est simple en fait:

    je cherche à simplifier/optimiser mes codes, et là la 1ère chose que je remarque sont les répétitions, lesquelles sautent pourtant aux yeux :S

    Dans le 1er exemple c'était les "Tablei" , est il possible de ne faire qu'une seule boucle "nommant" chaque tableau Tablei avec le bon integer i ?

    Dans le 2e exemple, on voit une liste de 40 "Case is", mais on remarque que les appels de procédures "Resulti" ont le même indice que les "Case i" (et cet indice = Ne c'est cool ^^), là encore est-il possible de faire une boucle pour simplifier tout ça ?

    Le problème est qu'à chaque fois que j'essaie d'écrire une boucle du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    For i = 2 to 40
      For j= 1 to 15
         "Table" & i = calcul compliqué fonction de j
      End For
    End For
    ...pour le 1er exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    For Ne = 2 to 40
       déclarations blabla...
       ("Result" & Ne) Cible, Np, TabC
    End For
    ... pour le 2e exemple (j'avoue je n'avais pas pensé que je pouvais encore + simplifier en virant l'instruction Case)

    Ce serait plus simple, non?

    Mais dans les 2 exemples, j'obtiens des erreurs d'incompatibilité de type ou d'objet "inconnu", alors que les Tablei et les procs Resulti sont déjà construites, définies etc... (les codes initiaux marchent d'ailleurs). Voilà pourquoi je comprends pas très bien alors que la concaténation de ces noms semble se faire correctement mais apparemment VBA est pas foutu de savoir que -par exemple- pour i=7, ("Result" & i)=Result7 corresponds à un appel à la procédure nommée Result7, ou encore que "Table" & i = Table7 corresponds au tableau de nom Table7, etc...

    Je viens de passer l'après-midi a tenter avec une variable intermédiaire déclarée en Variant, avec .Object.Name, avec .Find, ... aucune méthode ne pige un nom concaténé >< je suis à court d'idées là ;;

    EDIT: je précise qu'il n'y a aucun private, ce sont des codes vraiment basiques.
    EDIT2: s'il y a vraiment besoin, je peux toujours poster les fichiers correspondants à ces 2 bouts de code (m'a pas semblé nécessaire vu qu'il ne s'agit qu'une histoire de syntaxe toute bête mais fort énervante pour un débutant comme moi)

  4. #4
    Expert confirmé
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    4 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 124
    Par défaut
    Salut
    Ce qui est claire a tes yeux par ce que tu as le nez collé sur ton problème, ne l'ai pas forcement pour nous qui te lisons.
    Ceci etant dis

    Pour ton 1er problème
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Sub test1_Masamunai()
    Dim Table(1, 14) As Single 'crée 2 tableau de single (de 0 à 1) contenant chacun 15 valeur (de 0 à 14)
    Dim i As Integer, j As Integer
     
    For i = 0 To 1 'Boucle table
        For j = 0 To 14 'Boucle valeur de "table i"
            Table(i, j) = 14 / (j + 1)
        Next
    Next
    End Sub
    A++
    Qwaz

    Oulala wala j'avais pas tout lu....

    mais apparemment VBA est pas foutu de savoir que -par exemple- pour i=7, ("Result" & i)=Result7 corresponds à un appel à la procédure nommée Result7
    Lol, donc inutil d'insulter vb, car a mon avis peu de langage interpreterait du text comme etant une procedure ..; et j'oserais dire heureusement car ce serait un sacré bordel, il faudrait faire attention a tous moment a ne pas créer une chaine qui est le meme nom qu'une procedure

    En somme si tu as ce type de problème ça n'est pas lier a un problème venant du langage, mais a un problème lier a la construction de tes procédures

    Tu dois rendre ta procédure polyvalente afin qu'elle gère tous les cas lié a un numéro Ne. Montre nous l'intérieur de ces multiple procédure qui on certainement toutes le même code.

    A++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Par défaut
    Oula je n'avais pas vu votre réponse super rapide Qwazerty.

    Ok ci-joint les 2 fichiers contenant le + de "répétitions" dont je cherche à simplifier.
    Les 2 traitent la même chose: générer des permutations avec SommeMatching, et on été développées en partenariat avec le forum VeriTi.net et plus spécialement Marco57.
    Le 1er est ma dernière version, tandis que le 2e est celui de Marco qui comme vous le verrez semble bien + "pro" :p
    Bref là n'est pas la question. Je souhaiterait apprendre à éviter les répétitions de codes (qui entraineront peut etre un gain de vitesse d'éxécution), mais je me heurte à ce qui semble être un banal problème de syntaxe... que j'aurais réglé sans problème avec la fonction INDIRECT() sous Excel, mais sous VBA ben.... .
    Vous trouverez donc dans ces 2 fichiers, outre les 2 exemples précités, plein d'autres répétitions "lourdes" à lire.

    En espérant que cela vous aide à y voir plus clair. (désolé si j'ai trop simplifié le post d'origine)

  6. #6
    Expert confirmé
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    4 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 124
    Par défaut
    Re
    Pour le debut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    Private Sub Worksheet_Change(ByVal Target As Range) ' Marco57 de VeriTi.net, et R.Morineau, Mars2010
    'la ligne suivante declare les dest de 1 a 14 en type variant et seulement Dest15 en range
    'Dim Dest1, Dest2, Dest3, Dest4, Dest5, Dest6, Dest7, Dest8, Dest9, Dest10, Dest11, Dest12, Dest13, Dest14, Dest15 As Range
    'il faut repeter as ... en vb
    'Dim Dest1 As Range, Dest2 As Range, Dest3 As Range, Dest4 As Range, Dest5 As Range, Dest6 As Range, Dest7 As Range, Dest8 As Range, Dest9 As Range, Dest10 As Range, Dest11 As Range, Dest12 As Range, Dest13 As Range, Dest14 As Range, Dest15 As Range
    'Mais comme expliqué dans mon autre message il faut faire des tableaux, ici un tableau de range
    Dim DestRange(14) As Range 'a mettre a la place de la declaration des 15 Dest
    Dim xDest As Integer
     
    Dim Col As New Collection, Cible%, NbM%, cNbM%, Diff%, NbR
    Dim x%, i%, x0%, x1%, x2%, x3%, x4%, x5%, x6%, x7%, x8%, x9%, x10%, x11%, x12%, x13%, x14%, N%, R%
    ReDim Table2(2, 0), Table3(2, 0), Table4(2, 0), Table5(2, 0), Table6(2, 0), Table7(2, 0), Table8(2, 0), Table9(2, 0), Table10(2, 0), Table11(2, 0), Table12(2, 0), Table13(2, 0), Table14(2, 0), Table15(2, 0)
    'Idem 1ere remarque
    Dim x0min, x1min, x2min, x3min, x4min, x5min, x6min, x7min, x8min, x9min, x10min, x11min, x12min, x13min, x14min As Integer
     
      If Not Intersect(Target, Union([Data], [NbMembres], [SomCible])) Is Nothing Then
       If Intersect(Target, Union([Data], [NbMembres], [SomCible])).Cells.Count = 1 Then
        Cible = [SomCible].Value
        NbM = [NbMembres].Value
        For x = 1 To [Data].Cells.Count
          Col.Add [Data].Cells(x), CStr(x)
          If [Data].Cells(x) > 0 Then
            N = x - 1 'Nbre maxi correspondant à la dernière donnée non-nulle
            R = R + 1 'Nbre réel de données non nulles (sans celles nulles avant N)
          End If
        Next x
        If Not 2 <= Col.Count <= 9 Then
         MsgBox "Le Nombre de Probabilité(s) Différente(s) de Zéro n'est pas correct": Exit Sub
        End If
        If 1 > NbM Or NbM > 15 Then
         MsgBox "Le Nombre de Membres doit être un Entier entre 1 et 15 (inclus)": Exit Sub
        End If
     
        While Fact(R + i) / (Fact(i) * Fact(R)) < 65000 And i <= NbM 'Protection anti-saturation
            cNbM = i 'Nbre de membres max/uplet corrigé
            i = i + 1
        Wend
     
        For xDest = 1 To 14
            Set DestRange(xDest) = Range("Dest" & xDest & "Uplets").Cells
        Next
        'remplace tous les set
        'Set Dest2 = [Dest2Uplets].Cells
        'Set Dest3 = [Dest3Uplets].Cells
        'Set Dest4 = [Dest4Uplets].Cells
        'Set Dest5 = [Dest5Uplets].Cells
        'Set Dest6 = [Dest6Uplets].Cells
        'Set Dest7 = [Dest7Uplets].Cells
        'Set Dest8 = [Dest8Uplets].Cells
        'Set Dest9 = [Dest9Uplets].Cells
        'Set Dest10 = [Dest10Uplets].Cells
        'Set Dest11 = [Dest11Uplets].Cells
        'Set Dest12 = [Dest12Uplets].Cells
        'Set Dest13 = [Dest13Uplets].Cells
        'Set Dest14 = [Dest14Uplets].Cells
        'Set Dest15 = [Dest15Uplets].Cells
        [Results].Cells.ClearContents
    Pour le reste du code j'ai besoin d'un moment pour le comprendre un minimum, mais il me semble qu'il faille appeler récursivement une procédure

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Boucle for et concaténation
    Par mulbek dans le forum Langage
    Réponses: 4
    Dernier message: 13/12/2010, 13h38
  2. Boucle for avec saut
    Par michel71 dans le forum Delphi
    Réponses: 3
    Dernier message: 25/02/2007, 16h16
  3. boucle for avec condition
    Par Daniel Magron dans le forum Delphi
    Réponses: 4
    Dernier message: 22/01/2007, 16h18
  4. Réponses: 2
    Dernier message: 28/08/2006, 18h17
  5. [VB6] boucle for avec liste de valeur defini
    Par Morpheus2144 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 06/04/2006, 18h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo