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 :

Problème avec des plages de cellules non rectangulaires [XL-2003]


Sujet :

Macros et VBA Excel

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Problème avec des plages de cellules non rectangulaires
    Problème sous Excel 2003 VBA francisé (non testé avec d'autres versions)

    Bonjour à tous,

    J'ai un problème de réactions non homogènes de certaines fonctions VBA quand je leur passe une plage de cellules rectangulaire ou non.
    Il y a donc visiblement une différence que je ne comprends pas entre ces deux types de plages.
    Voici la mise en évidence de mon problème :
    Dans une feuille vide, je n'ai que 4 cellulles contenant des entiers :
    L1C1=11, L1C2=12, L2C1=21 et L2C2=22
    Ensuite, j'ai nommé deux plages :
    titi=Feuil1!L2C1:L2C2
    toto=Feuil1!L2C1;Feuil1!L1C2
    Enfin je fais trois appels à ma macro Test() avec :
    Test(-3;"-3")
    Test(titi;"titi")
    Test(toto;"toto")
    Ma macro est :
    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
    Public Function Test(zon As Variant, str As String) As Long
      Dim arg As Variant, var As Variant
      Dim res As Long
     
      res = 0
                     Debug.Print ">" & str
      arg = zon
      'For Each arg In zon
        If IsNumeric(arg) Then
          var = arg
                     Debug.Print "N" & var
          res = res + var
        ElseIf IsArray(arg) Then
          For Each var In arg
                     Debug.Print "A" & var
            res = res + var
          Next
        Else
                     Debug.Print "?" & arg
        End If
      'Next
      Test = res
                     Debug.Print "<" & res
    End Function 'Test
    Et j'obtiens ce résultat :
    >-3
    N-3
    <-3
    >titi
    A21
    A22
    <43
    >toto
    N21
    <21
    Les deux premières correspondent bien à ce que j'attendais mais pas la troisième. Visiblement, la plage "titi" - constituée de 2 cellules en ligne - est bien détectée comme non numérique par IsNumeric() puis comme un tableau par IsArray() alors que la plage "toto" - constituée de 2 cellulles jointes - n'est pas vue, par les mêmes fonctions, comme un tableau mais comme une valeur unique !

    Y a-t-il une raison pour qu'une plage sélectionnée en maintenant la touche SHIFT enfoncée ne réagisse pas comme une plage sélectionnée en maintenant la touche CTRL enfoncée ?
    Si oui (j'aimerais bien comprendre pourquoi), y a-t-il un moyen de les traiter de la même façon ou de les transformer toutes les deux dans un même type de tableau/collection qui réagisse de façon identique ?

    Note: ma macro Test est simplifiée pour cet exposé. Je cherchais à faire une macro qui gère ses arguments comme le font les macros SUM() ou MAX() d'Excel... ce qui sera plus compliqué, je le sais, mais là n'est pas ma question. Pourtant, si quelqu'un peut me fournir une référence d'un code qui simule la gestion des arguments de la macro MAX() par exemple, je serai preneur.

    Ce qui me turlupine plus pour l'instant, c'est de comprendre pourquoi ces deux types de plages ne réagissent pas de la même façon... j'ai peur d'avoir écrit, par le passé, un bon nombre de lignes de code à revoir !

    Merci à tous ceux qui ont déjà eu la patience de me lire

  2. #2
    Expert éminent Avatar de jfontaine
    Homme Profil pro
    Contrôleur de Gestion
    Inscrit en
    Juin 2006
    Messages
    4 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Contrôleur de Gestion

    Informations forums :
    Inscription : Juin 2006
    Messages : 4 754
    Points : 9 396
    Points
    9 396
    Par défaut
    Bonsoir,


    Note: ma macro Test est simplifiée pour cet exposé. Je cherchais à faire une macro qui gère ses arguments comme le font les macros SUM() ou MAX() d'Excel... ce qui sera plus compliqué, je le sais, mais là n'est pas ma question. Pourtant, si quelqu'un peut me fournir une référence d'un code qui simule la gestion des arguments de la macro MAX() par exemple, je serai preneur.
    Tu peux te servir de Application.WorksheetFunction pour utiliser les fonctions Excel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.WorksheetFunction.Max(Range("A1:A300"))

    Si tu souhaites lire chaque cellules dune plage nommée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Dim c As Range
     
    For Each c In Range("titi")
        MsgBox c.Value
    Next
    Bon courage

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci Jérome,
    mais je connaissais tout ça.

    Je ne veux pas simuler une des macros "WorksheetFunction" mais créer ma propre macro qui ne fait que gérer ses arguments de la même manière qu'un SUM() ou MAX()... en gros accepter un nombre quelconque d'arguments constitués de valeurs ou de plages pointées par l'utilisateur. En fait, je n'utiliserai pas de plages nommées (c'était juste pour la clarté de mon exposé).

    Dans "ma" réalité, ce sera l'utilisateur qui choisira un nombre quelconque de cellules associées (ou pas) avec la touche CTRL... d'où mon problème : comment manipuler des zones rectangulaires ou des zones de cellules disparates si les fonctions VBA ne les traitent pas de la même façon ?

    Normalement, je sais déjà gérer un nombre variable d'arguments, mon problème n'est pas là. Là, je suis démuni car, à cause de ce phénomène, je ne sais plus reconnaître correctement une plage rectangulaire de cellulles ou un ensemble disparate de cellulles d'une simple valeur numérique.

    Merci à tous

  4. #4
    Expert éminent Avatar de jfontaine
    Homme Profil pro
    Contrôleur de Gestion
    Inscrit en
    Juin 2006
    Messages
    4 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Contrôleur de Gestion

    Informations forums :
    Inscription : Juin 2006
    Messages : 4 754
    Points : 9 396
    Points
    9 396
    Par défaut
    Sans fichier avec exemple concret de ton problème il est difficile de comprendre ce qui ne va pas

    je ne sais plus reconnaître correctement une plage rectangulaire de cellulles ou un ensemble disparate de cellulles d'une simple valeur numérique.
    Une zone rectangulaire contient une plage de cellules contiguë, son adresse est A1:C2 alors qu'une plage disparate contient une adresse du type A1:A2,C1:C2,E1:E2

    Tu peux dans ce cas tester l'existence d'une virgule
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    If InStr(Selection.Address, ",") > 0 Then
        MsgBox "ensemble disparate"
    Else
        MsgBox "plage rectangulaire"
    End If

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci Jérome pour ta patience.
    Visiblement, j'ai du mal à me faire comprendre.

    Citation Envoyé par jfontaine Voir le message
    Une zone rectangulaire contient une plage de cellules contiguë, son adresse est A1:C2 alors qu'une plage disparate contient une adresse du type A1:A2,C1:C2,E1:E2
    Oui, je savais cela... sauf que, comme je suis francisé, le caractère virgule ',' est réservé pour les nombres décimaux et le caractère pour unir des plages non contiguës est le point-virgule (A1:A2;C1:C2;E1:E2)... mais là n'est pas le problème...

    Citation Envoyé par jfontaine Voir le message
    Tu peux dans ce cas tester l'existence d'une virgule
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    If InStr(Selection.Address, ",") > 0 Then
        MsgBox "ensemble disparate"
    Else
        MsgBox "plage rectangulaire"
    End If
    Ok pour ça aussi... mais je n'ai pas accès à quoique ce soit du genre "Selection", Range("machin") ou autre... je n'ai que le variant passé en argument.. qui peut être directement un nombre ou bien une plage... contiguë ou non.

    Citation Envoyé par jfontaine Voir le message
    Sans fichier avec exemple concret de ton problème il est difficile de comprendre ce qui ne va pas
    Mon premier post me semble pourtant tout expliquer avec tous les détails nécessaires !
    Reprennons donc pas à pas :

    D'abord, créer la macro Test (version simplifiée à l'extrème de ma précédente) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Public Function Test(arg As Variant) As Long
      Dim var As Variant, res As Long
     
      res = 0
        If IsNumeric(arg) Then
          res = res + arg
        ElseIf IsArray(arg) Then
          For Each var In arg
            res = res + var
          Next
        End If
      Test = res
    End Function 'Test
    Ensuite, dans une feuille vide, entrer les 4 cellules :
    L1C1=11
    L1C2=12
    L2C1=21
    L2C2=22

    Puis définir les 2 plages nommées :
    titi=Feuil1!L2C1:L2C2
    ;c.a.d. Faire Insertion/Nom/Définir, entrer le nom "titi" et sélectionner la plage en cliquant sur la cellule L2C2 puis, en maintenant la touche SHIFT enfoncée, sur la cellule L2C1. Valider.

    toto=Feuil1!L2C1;Feuil1!L1C2
    ;c.a.d. Faire Insertion/Nom/Définir, entrer le nom "toto" et sélectionner la plage en cliquant sur la cellule L1C2 puis, en maintenant la touche CTRL enfoncée, sur la cellule L2C1. Valider.

    Finalement, entrer les 6 formules suivantes :
    L3C1=Test(-3)
    L3C2=SOMME(-3)
    L4C1=Test(titi)
    L4C2=SOMME(titi)
    L5C1=Test(toto)
    L5C2=SOMME(toto)

    Vous devriez obtenir les résultats donnés dans les pièces jointes.
    On y voit que Test() réagit bien comme SOMME() sauf pour la ligne L5 où SOMME(toto) retourne 33 alors que Test(toto) retourne 21.
    Si vous reprennez le résultat des debug.print de mon premier post, vous comprendrez que cette différence est due au fait que IsArray (et IsNumeric) ne réagissent pas logiquement (dans ma logique, du moins) avec l'argument toto.
    La table de vérité observée est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    arg	IsArray(arg)	IsNumeric(arg)
    -3	False		True
    titi	True		False
    toto	False		True

    D'où ma question :
    Pourquoi le fait d'utiliser des plages de cellules contiguës ou non provoque des réactions différentes de IsArray et IsNumeric ?
    Alternativement, comment contourner ce problème ?

    Merci à tous.
    Images attachées Images attachées    

  6. #6
    Expert éminent
    Avatar de Didier Gonard
    Homme Profil pro
    Formateur Office et développeur VBA en freelance
    Inscrit en
    Février 2008
    Messages
    2 805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Formateur Office et développeur VBA en freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 2 805
    Points : 6 699
    Points
    6 699
    Par défaut
    Bonjour,

    Y a-t-il une raison pour qu'une plage sélectionnée en maintenant la touche SHIFT enfoncée ne réagisse pas comme une plage sélectionnée en maintenant la touche CTRL enfoncée ?
    Quelque part, Oui

    Si tu sélectionnes A1:A10 avec shift, puis B1:B10 avec Ctrl et 10 clics et que pour chacun, tu valides :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ? selection.areas.count
    dans la fenêtre exécution tu obtiendras respectivement, 1 et 10...

    pas le temps de creuser plus, mais as-tu testé si l'emploi de la méthode Union induisait un comportement différent ? (approche empirique).

    cordialement,

    Didier

  7. #7
    Expert éminent Avatar de jfontaine
    Homme Profil pro
    Contrôleur de Gestion
    Inscrit en
    Juin 2006
    Messages
    4 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Contrôleur de Gestion

    Informations forums :
    Inscription : Juin 2006
    Messages : 4 754
    Points : 9 396
    Points
    9 396
    Par défaut
    Oui, je savais cela... sauf que, comme je suis francisé, le caractère virgule ',' est réservé pour les nombres décimaux et le caractère pour unir des plages non contiguës est le point-virgule (A1:A2;C1:C2;E1:E2)... mais là n'est pas le problème...
    Point virgule dans une feuille et virgule dans l'adresse de VBA

    l'utilisation d'une variable de type variant ne doit pas arranger ton problème
    une variable de type range serait plus adaptée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Public Function test2(plage As Range) As Long
     
    test2 = Application.WorksheetFunction.Sum(plage)
     
    End Function

  8. #8
    Inactif  
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 054
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 054
    Points : 2 416
    Points
    2 416
    Par défaut
    Bonjour tous,
    Sais pas si j'ai bien compris mais...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        If IsNumeric(arg) Then
          res = res + arg
        ElseIf IsArray(arg) Then
          For Each var In arg
            res = res + var
          Next
        End If
    Quand tu test en numérique tu ne prend que la 1ère cellule ?
    Par contre quand tu prend en array tu additionne toutes les cellules ?
    Suis peut-être à côté de la plaque !!
    Je verrais ça comme..
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        For Each Var In arg
            If IsNumeric(Var) Then
              res = res + Var
            Else
                res = res + Var
            End If
        Next
    A+

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci à tous,
    en particulier Ormonth... sans répondre directement à ma question, tu m'as permis d'avancer.

    Ma future procédure (qui, je le rappelle, n'est pas une simple somme comme présenté ici pour plus de simplicité) sera montée sur le modèle de :
    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
    Public Function Test(Nombre1 As Variant, ParamArray Nombre2()) As Long
      Dim var As Variant, var2 As Variant, res As Long
      res = 0
      For Each var In Nombre2
        res = res + Test(var)
      Next
      If TypeOf Nombre1 Is Range Then
        For Each var2 In Nombre1
          For Each var In var2
            res = res + Test(var.Value)
          Next
        Next
      ElseIf IsArray(Nombre1) Then
        For Each var In Nombre1
          res = res + Test(var)
        Next
      ElseIf IsNumeric(Nombre1) Then
        res = res + Nombre1
      End If
      Test = res
    End Function 'Test
    Aussi loin que j'ai pu tester, elle réagit bien maintenant, au niveau des arguments, comme une fonction SOMME()... y compris pour Test({1;3};{4;5}) par exemple

    Mais je ne peux que conclure de cette mésaventure que IsNumeric et IsArray ne sont pas fiables dans un contexte ouvert d'arguments. Pour moi, IsNumeric devrait toujours retourner False quand on lui passe une plage
    Maintenant, il va falloir que je passe au peigne fin une bonne partie de mes lignes de code !!!

    Problème résolu.
    Merci à tous.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/10/2013, 15h52
  2. Problème étrange avec des plages de cellules
    Par ANOVA dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 11/08/2011, 23h12
  3. Problème avec des composants non déclarés
    Par vbcasimir dans le forum Bases de données
    Réponses: 1
    Dernier message: 20/01/2005, 11h17
  4. [STRUTS] Problème avec des ActionForm
    Par zarbydigital dans le forum Struts 1
    Réponses: 2
    Dernier message: 29/03/2004, 13h49
  5. Problèmes avec des vues
    Par dady dans le forum MFC
    Réponses: 22
    Dernier message: 09/01/2004, 16h26

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