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 :

Boucle sur les cellules du plage - gestion cellules fusionnées


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut Boucle sur les cellules du plage - gestion cellules fusionnées
    Bonjour à tous,

    J'ai un complément xlam pour de la gestion de texte dans les cellules d'une plage.
    Ce complément très succin permet plusieurs actions sur les cellules de la plage sélectionnée :
    • Passer le sélection en Majuscule
    • Passer la sélection en minuscule
    • Réduire (fonction VB Trim) la sélection
    • Ajouter un suffixe sur la sélection
    • Ajouter un préfixe sur la sélection

    J'ai inclus un fichier XML pour qu'un onglet spécifique soit ajouté au ruban lors de l'activation du complément.

    Le mécanisme des 5 fonctions est quasi identique :
    1. récupération des cellules visibles de la sélection
    2. [InputBox pour saisir le suffixe ou le préfixe]
    3. boucle sur toutes les cellules
    4. action sur chaque cellule



    Je vous présente le code de la fonction AjouterPréfixe et la fonction Callback associée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Sub AjouterPrefixe(ByVal objSelection As Range)
        Dim objCible As Range, objCell As Range, Prefixe
        Application.ScreenUpdating = False
            If objSelection Is Nothing Then GoTo fin
            Prefixe = Application.InputBox(prompt:="Entrez un préfixe", Type:=2)
            If Prefixe = vbNullString Then GoTo fin
                Set objCible = objSelection.SpecialCells(xlCellTypeVisible)
                For Each objCell In objCible.Cells
                    objCell.Value = Prefixe & objCell.Value
                Next
    fin:
        Set objCible = Nothing
        Application.ScreenUpdating = True
    End Sub
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    'Callback for btAddPrefixe.onAction
    Sub btAddPrefix_onAction(control As IRibbonControl)
        Call mfeatures.AjouterPrefixe(Selection)
    End Sub
    Une fonction Callback est placé dans le groupe contenant les boutons du ruban pour le masquer si aucun classeur n'est ouvert.
    La ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If objSelection Is Nothing Then GoTo fin
    n'est donc pas nécessaire car objSelection est toujours la sélection (donc jamais vide sauf si aucun classeur n'est ouvert) mais je préfère la garder.


    Voilà pour le contexte. Vos critiques sont les bienvenues.

    Ma question est la suivante :
    Si la sélection comporte dans cellules fusionnées. En bouclant comme je le fais, je passe plusieurs fois sur la même cellule.
    Comment éviter de passer plusieurs fois sur une cellule fusionnée ?

    Merci d'avance

  2. #2
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 169
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    c'est toujours la galère les cellules fusionnées, on peut toujours s'en sortir mais au prix de mécaniques dignes d'usines à gaz
    il faut travailler sur deux aspects :

    1) repérer que la cellule parcourue fait partie d'une zone fusionnée (contenant plus d'une cellule)
    2) si c'est le cas : on vérifie que la cellule parcourue est la première cellule de la plage fusionnée

    Ceci permet de ne pas retraiter les autres cellules de la plage fusionnée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Sub ioi()
    Dim Cell As Range
        For Each Cell In Selection.Cells
            ' si la cellule fait partie d'une plage fusionnée
            If Cell.MergeArea.Cells.Count > 1 Then
                ' si cette cellule est la première de la plage fusionnée              On travaille sur la plage fusionnée
                If Cell.MergeArea.Cells(1, 1).Address = Cell.Address Then Debug.Print Cell.MergeArea.Address
            Else
                Debug.Print Cell.Address
            End If
        Next Cell
    End Sub

  3. #3
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut
    Bonjour joe,

    Pour la galère des cellules fusionnées, je suis entièrement d'accord. Je n'utilise la fusion que de façon exceptionnelle.
    Le but étant de diffuser le complément, je ne sais comment les utilisateurs utilisent les fusions.

    Merci pour ton retour et ta proposition de code.
    Je ne suis pas familiarisé avec la propriété MergeArea, peux tu me confirmer que le code ci-dessous a le même comportement que ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Sub test()
        Dim c As Range
            For Each c In Selection.Cells
                If c.MergeArea.Cells(1, 1).Address = c.Address Then Debug.Print c.Address
            Next
    End Sub
    Si oui je vais intégrer cette ligne à mes 5 fonctions.

    Petit question un peu bête :
    Laquelle de ces solutions est la plus rapide (temps d'exécution) ?
    • Pas de test est plusieurs fois le même traitement sur la même cellule (mon code du premier post)
    • 1 seul test (mon code dans ce post)
    • 2 tests (ton code)

  4. #4
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 169
    Billets dans le blog
    5
    Par défaut
    Bien sûr que tu peux directement passer par le teste de la première cellule d'une plage fusionnée.

    Je suis un peu tâtillon (au détriment de la vitesse d'exécution) lorsqu'il s'agit de fusions de cellules, toujours dans l'optique que quelqu'un d'autre soit amené à décortiquer mes procédures et les faire évoluer.

    mais par essence, toute cellule possède la propriété MergeArea (qui vaut 1 quand la cellule n'est pas fusionnée).

    Maintenant, faire le teste ou passer sur chaque cellule .... c'est à toi de voir.

    J'ai tendance à penser qu'on a toujours + de cellules non fusionnées que de cellules fusionnées ... et que donc traiter plusieurs fois une plage fusionnée sera moins long que de tester chaque cellule pour savoir si elle est fusionnée et est bien la première cellule du groupe de fusion.

    Mais il faut surtout réfléchir à ce que font tes procédure, et répondre à la question : est-ce que traiter deux fois la même cellule (car une cellule fusionnée n'est ni plus ni moins qu'un groupe de cellules disposant chacun de leurs propriétés, mais toutes appliquées sur la première cellule de la zone) ne va pas engendrer des comportements inattendus ? A première vue je ne pense pas, mais c'est toi le patron.

  5. #5
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut
    Merci pour ta réactivité et la clarté de tes explications / précisions.

    Effectivement dans mon cas, traiter plusieurs fois la même cellule n'a pas d'effet indésirable. Je peux donc décider de mettre le test ou non.
    Je vais donc faire des tests pour comparer la vitesse d'exécution avec ou sans le test et avec plus ou moins de cellules fusionnées.
    En fonction du résultat et du fait qu'il a souvent plus de cellules non fusionnées que l'inverse, je ferais un choix.

    Encore merci, je passe en


    PS : dans mon premier code, il faut remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If Prefixe = vbNullString Then GoTo fin
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If Prefixe = vbNullString Or CStr(Prefixe) = "Faux" Then GoTo fin
    car Application.InputBox renvoie False si la pop-up est fermé ou si l'utilisateur clic sur annuler.
    Sauf si quelqu'un a mieux à proposer

    Edit : Grosse erreur de ma part
    If Prefixe = vbNullString Or Not Prefixe Then GoTo fin n'a aucun sens (prendre une variable pour un string et pour un booleen dans la même ligne )

  6. #6
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 169
    Billets dans le blog
    5
    Par défaut
    Juste pour partager nos méthodologies différentes mais aboutissant au même résultat, voici comment de mon côté j'effectue ce type de test

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Sub toto()
    Dim prefixe
    prefixe = Application.InputBox(prompt:="Entrez un préfixe", Type:=2)
        Select Case TypeName(prefixe) = "String" And prefixe <> vbNullString
            Case True
                MsgBox "Valeur ok"
            Case Else
                MsgBox "pas de valeur"
        End Select
    End Sub
    L'inconvénient (pas pour moi car ce n'est pas utile dans mes procédures à ce jour) c'est qu'on ne distingue pas la saisie vide de l'annulation d'inputbox

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

Discussions similaires

  1. Ajout d'une boucle sur les lignes d'une plage
    Par DexterV dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 31/05/2016, 21h49
  2. IsEmpty ne fonctionne pas sur une ligne ou plage de cellule
    Par sambrelin dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 11/03/2014, 09h04
  3. Comparer les valeurs de plages de cellules
    Par docjo dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 28/10/2009, 17h31
  4. [C#] Boucle sur les controles
    Par stailer dans le forum Windows Forms
    Réponses: 3
    Dernier message: 10/05/2006, 08h48
  5. Macro sur Excel/Boucle sur les lettres
    Par life is magic dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 25/11/2005, 11h56

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