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 :

De l'importance de la spécification systématique des propriétés utilisées


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut De l'importance de la spécification systématique des propriétés utilisées
    Bonjour à tous
    Une discussion a été aujourd'hui ouverte.
    Il y était question d'une difficulté rencontrée pour déterminer le nombre de cellules contenant "Non"
    Bien qu'il soit plus que vraisemblable que la cause de cette difficulté était le fait d'espace(s) avant ou après la chaîne "Non", j'avais de mon côté fait observer qu'il valait toujours mieux préciser la propriété utilisée des cellules parcourues, plutôt que de laisser VBA "deviner" et choisir celle à prendre en considération.
    Cette remarque aura pu, je le sais, paraître quelque peu exagérée.
    Et pourtant ....
    Voici donc le petit test que je propose, plus particulièrement à ceux qui n'ont pas encore pris cette sage habitude (de spécifier clairement la propriété) --->>

    Une feuille de calcul avec un bouton de commande commandbutton1 et ce code :
    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
    Option Explicit
    Private Sub CommandButton1_Click()
      Dim dl As Long, k As Long, nbdefault As Long, nbvalue As Long, nbtext As Long, totalrejets As Double, totalretenu As Double
      dl = Range("A" & Rows.Count).End(xlUp).Row
      nbdefault = 0: nbvalue = 0: nbtext = 0: totalrejets = 0: totalretenu = 0
      For k = 1 To dl
        If Range("A" & k) = "Non" Then nbdefault = nbdefault + 1
        If Range("A" & k).Value = "Non" Then nbvalue = nbvalue + 1
        If Range("A" & k).Text = "Non" Then
          nbtext = nbtext + 1: totalrejets = totalrejets + Range("A" & k).Value
        Else
           totalretenu = totalretenu + Range("A" & k).Value
        End If
      Next
      MsgBox "      NOMBRE DE ""NON""" & vbCrLf & "sans utiliser de propriété  ===>> " & nbdefault & vbCrLf & _
      "en utlisant la propriété value (qui est celle par défaut) ===>> " & nbvalue & vbCrLf & _
      "mais en utilisant la propriété text ===>> " & nbtext & vbCrLf & vbCrLf & "      Regardons nos différents totaux" & vbCrLf & _
      "total réel ===>> " & WorksheetFunction.Sum(Range("A1:A" & dl)) & vbCrLf & _
      "total rejeté  ===>>  " & totalrejets & vbCrLf & _
      "total retenu  ===>> " & totalretenu
    End Sub
    
    Private Sub Worksheet_Change(ByVal Target As Range)
       If Target.Column > 1 Then Exit Sub
       Target.HorizontalAlignment = 3
       Target.NumberFormat = "#.00"
       On Error Resume Next
         If IsNumeric(Target.Text) And Target.Value <> "" And Target.Value < 10 Then Target.NumberFormat = """Non"""
       On Error GoTo 0
    End Sub
    Voilà -->> remplissez donc la colonne A de nombres, dont certains > 10 et d'autres < 10 -->> observez -->>
    Cliquez maintenant sur le bouton de commande --->> lisez

    Une précision : j'ai voulu ici ne montrer (je dis bien montrer car ce n'est en général pas le cas lorsque l'on met en place ce genre de stratagème) que la "moelle" des choses. Tout est donc ici visible et apparent, ce qui est loin d'être le cas lorsque le développeur installe ce genre de mécanisme.
    J'ai choisi des "Non". C'est bien "autre chose" qu'une chaîne bien trop visible que l'on choisit généralement
    Pourquoi et quand le ferait-il ? Comment "cacherait"-il, etc ??? -->> c'est en général là sa seule "affaire" et cela ne relevant que d'autres aspects, dont la créativité, je n'ai aucune intention d'en exposer les raisons.
    Contentez-vous du seul objectif de la présente discussion : Montrer l'importance de la spécification systématique des propriétés utilisées
    Amitiés

  2. #2
    Expert confirmé Avatar de Patrice740
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2007
    Messages
    2 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2007
    Messages : 2 478
    Par défaut
    Bonjour Jacques,

    Depuis toujours, je prône l'importance d'éviter l'emploi des déclarations implicites et par conséquence la spécification systématique des propriétés utilisées.

    J'ai souvent vu affirmer que dans certains cas, en l'absence de la propriété .Value pour un objet Range, VBA pouvait renvoyer autre chose (.Text ?).
    Mais à ce jour je suis toujours à la recherche d'un exemple qui pourrait mettre en évidence ce problème.

  3. #3
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Bonjour Patrice
    Non, VBA n'interprètera jamais comme propriété Text l'absence de précision de propriété d'un objet Range.
    Il pourra cependant dans certains cas de figure (va falloir que je retrouve cela dans mes souvenirs) prendre alors "pour argent comptant" l'objet range lui-même en lieu et place de sa propriété Value
    Amitiés


    EDIT : regarde, Patrice, ce qui peut entre autres arriver dans certains cas.
    Ici, je vais écrire comme un cochon (et VBA ne réagira pas) au clic d'un bouton de commande :
    Sur une feuille :
    en A1 : "coucou"
    en A2 : "voilà"
    1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Private Sub CommandButton1_Click()
      Dim tb As Range
      Set tb = Range("A1")
      tb = Range("A1:A2") 
    End Sub
    clique et cherche où "coucou" a disparu
    2)
    on remet "coucou" en A1 et -->>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Private Sub CommandButton1_Click()
      Dim tb As Range
      Set tb = Range("A1")
      tb = Range("A1:A2").Value
    End Sub
    Ah ...
    3) et maintenant, le pire à comprendre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Private Sub CommandButton1_Click()
      Dim tb As Range
      Set tb = Range("A1")
      tb = Range("A1:A2").Text
    End Sub
    Conclusions : -->>
    1) ne jamais écrire comme un cochon
    et
    2) et de toutes manières (juste pour le cas d'une inattention) : toujours préciser (en parfaite conscience de ce que l'on veut préciser) ce qu'il y a à préciser.

  4. #4
    Expert confirmé Avatar de Patrice740
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2007
    Messages
    2 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2007
    Messages : 2 478
    Par défaut Ah, les 3 petits cochons ...
    Re,
    Citation Envoyé par unparia Voir le message
    Non, VBA n'interprètera jamais comme propriété Text l'absence de précision de propriété d'un objet Range.
    C'est aussi ce que je continuerais à dire.

    J'ai du mal à comprendre ce qui se passe dans ton premier exemple et dans celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Private Sub CommandButton1_Click()
      [A1].Value = "Coucou"
      [A2].Value = "Voila"
      [A3].Value = "Ah"
      Range("A1:A2") = Range("A2:A3")
    End Sub
    ' On s'attend à cela :
    Private Sub CommandButton2_Click()
      [A1].Value = "Coucou"
      [A2].Value = "Voila"
      [A3].Value = "Ah"
      Range("A1:A2").Value = Range("A2:A3").Value
    End Sub

  5. #5
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Il n'y a rien à comprendre, sinon que VBA ne sait plus de quoi il s'agit en fait.
    Range étant un objet, il aurait du rejeter sévèrement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range("A1:A2") = Range("A2:A3")
    Mais voilà : il a voulu se montrer trop conciliant, pensant qu'il allait deviner la volonté réelle du développeur ... et s'est planté
    Il a "traduit" par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range("A1:A2").Value = Range("A2:A3")
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range("A1:A2") = Range("A2:A3").Value
    ou encore mieux par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range("A1:A2").value = Range("A2:A3").Value
    Il aurait mieux fait de ne pas s'en mêler et de se montrer sévère dès le début.

  6. #6
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Pour rester dans la rigueur :
    si je faisais partie de l'équipe de Microsoft Office, je n'accepterais même pas que l'on utilisât la propriété value comme il en a été décidé lorsque cette propriété concerne une plage de cellules. Car ce "genre" assez cavalier à mon sens échappe à la compréhension et à l'esprit logique.
    Ma réflexion : que sont donc les valeurs d'un objet Range pour Excel/Vba, sinon tout simplement une matrice de ces valeurs ? -->> c'est la même chose !
    Et alors, oui, l'égalité de deux matrices peut s'exprimer.
    Et voilà la syntaxe que j'aurais alors IMPOSEE. Elle est logique, compréhensible et ne laisse place à aucune ambiguïté --->>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [A1].Value = "a1"
    [A2].Value = "a2"
    [A3].Value = "a3"
    Range("A1:A2")() = Range("A2:A3")()
    Et ....--->> Il se trouve (quel hasard !) qu'elle "marche" bien, elle ...

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    Merci Patrice,

    Simple, concis, clair et efficace, loin du verbiage pompeux et incompréhensible et des "exemples" de code illisibles et mal torchés

    Cela dit, ça pose problème lorsque l'on doit affecter les .Value d'une plage au départ d'un tableau, lorsque les valeurs à l'intérieur du tableau sont de nature différente, ce qui me semble être souvent le cas... Dans l'exemple suivant, A2 et A3 seront aussi en texte, ce qui n'est pas forcément souhaité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Sub Test()
      Dim a(2, 0) As String
     
      a(0, 0) = "0600"
      a(1, 0) = 600
      a(2, 0) = Date
     
      Range("a1:a3").Value = a
    End Sub

    Dès lors, je préfère formater les cellules dans Excel avant l'affectation des valeurs (ce qui devrait d'ailleurs toujours être fait). Ca permet un mix de types de données au niveau du tableau non typé, ce que ne permet pas le tableau typé. Qui plus est, cela permet également de comprendre l'intention du codeur (A1 en texte, A2 en nombre et A3 en date, sans équivoque possible). On a la maîtrise totale sans laisser à VBA le soin d'interpréter notre souhait.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Sub Test()
      Dim a(2, 0)
     
      Range("a1").NumberFormat = "@"
      Range("a2").NumberFormat = "General"
      Range("a3").NumberFormat = "dd/mm/yyyy"
      a(0, 0) = "0600"
      a(1, 0) = 600
      a(2, 0) = Date
     
      Range("a1:a3").Value = a
    End Sub


    De plus, dans ton exemple, si par la suite l'utilisateur modifie manuellement la valeur de la cellule (un simple F2 puis ENTER suffit), ton "0600" va redevenir une valeur numérique avec perte du 0 à gauche. Ici, la ligne Range("d1").Value = Range("d1").Value modélise le F2+ENTER du clavier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Sub Test1()
      Dim a(0, 0) As String
     
      a(0, 0) = "0600"
      Range("d1").Value = a
      Range("d1").Value = Range("d1").Value
    End Sub

    D'une façon générale, il faut toujours s'assurer du format des cellules dans lesquelles on dépose des valeurs, de façon à ne laisser aucune initiative à Excel, ni au moment de l'affectation des valeurs, ni par la suite.
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    ---------------

  8. #8
    Expert confirmé Avatar de Patrice740
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2007
    Messages
    2 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2007
    Messages : 2 478
    Par défaut
    Bonjour Pierre
    Citation Envoyé par Pierre Fauconnier Voir le message
    D'une façon générale, il faut toujours s'assurer du format des cellules dans lesquelles on dépose des valeurs, de façon à ne laisser aucune initiative à Excel, ni au moment de l'affectation des valeurs, ni par la suite.
    A 100% d'accord, c'est le plus sûr

    Mon post précédent avait simplement pour vocation de mettre en garde sur une mauvaise interprétation probable de l'exemple de Joe.
    Et, accessoirement, donner une méthode pour écrire une variable typée dans une cellule au format Standard, sans laisser à Excel le loisir de changer ce type.

  9. #9
    Expert confirmé Avatar de Patrice740
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2007
    Messages
    2 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2007
    Messages : 2 478
    Par défaut
    C'est pareil que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Option Explicit
    Sub Test()
    Dim r As Range
    Dim s As String
    Dim l As Long
      Set r = Cells(1, 1)
      s = Cells(1, 1)
      l = Cells(1, 1)
      Debug.Print TypeName(r)
      Debug.Print TypeName(s)
      Debug.Print TypeName(l)
    End Sub
    En fait, Cells(1, 1) = Cells(1, 1).Value est mal dit, je voulais dire que x = Cells(1,1) est toujours identique à x = Cells(1,1).Value
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Option Explicit
    Sub Test()
    Dim v as Variant
      v = Cells(1, 1)
      Debug.Print TypeName(v)
      v = Cells(1, 1).Value
      Debug.Print TypeName(v)
    End Sub

Discussions similaires

  1. Réponses: 3
    Dernier message: 11/06/2007, 11h20
  2. Réponses: 1
    Dernier message: 24/03/2007, 18h50
  3. Importer via asp.net c# des variables dans mon namespace xsl
    Par akaii dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 23/01/2006, 08h41
  4. probleme d'import de fichier txt avec des tab
    Par lecureuil dans le forum Access
    Réponses: 4
    Dernier message: 23/08/2005, 19h22

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