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 :

Comment savoir si le nom d'une cellule existe ? [XL-2019]


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de DenisHen
    Homme Profil pro
    Dessinateur / projeteur
    Inscrit en
    Novembre 2013
    Messages
    415
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Dessinateur / projeteur
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Novembre 2013
    Messages : 415
    Par défaut Comment savoir si le nom d'une cellule existe ?
    Bonjour à la communauté.
    J'ai cherché dans plein de forum, mais rien ne fonctionne, (sans savoir pourquoi bien sur, si non, je ne serais pas là ).
    Ma question est donc : comment savoir si le nom d'une cellule existe ?
    En gros, dans ma feuille active, j'aimerais :

    Si Nom existe
    Valeur = NomCellule.value
    Sinon
    Nom de cellule AA1 est "MenuiMarge"
    Valeur de cette cellule = 1.35
    Fin de Si.


    Sachant que si une cellule a ce nom, elle n'est peut-être pas en AA1.

    Je n'ai encore jamais utilisé les nom de cellule en VBA, et je crois comprendre que ça a l'air d'une galère, car les questions sont très nombreuses sur la toile.

    Bien à toi la communauté.

    Denis...

  2. #2
    Membre éclairé Avatar de DenisHen
    Homme Profil pro
    Dessinateur / projeteur
    Inscrit en
    Novembre 2013
    Messages
    415
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Dessinateur / projeteur
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Novembre 2013
    Messages : 415
    Par défaut
    Après des heures de recherches, j'ai fini par compiler divers codes trouvés ici et là, donc le principale vient d'ExcelCorpo.com
    Je poste donc ma "solution" qui fonctionne pour l'instant :
    En gros : je cherche si le nom ("MenuiAAAMarge") d'une cellule existe, si oui, je récupère sa valeur, si non, je le créé et lui donne une valeur (22):
    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
    Function NomCelExist(Nom, Cible) As Boolean 'trouvé sur ExcelCorpo.com
      On Error Resume Next
      NomCelExist = Names(Nom).RefersToRange.Count
      If NomCelExist = False Then
        Range(Cible).Name = Nom
        Range(Cible).Value = 22
      End If
    End Function
    Sub ExamenSurLesNoms() 'trouvé sur ExcelCorpo.com
    Nom = "MenuiAAAMarge"
      If NomCelExist(Nom, "AA1") = True Then
        Debug.Print Names(Nom).RefersToRange.Value
      Else
        Debug.Print Names(Nom).RefersToRange.Value
      End If
    End Sub
    Si ça peut servir à quelqu'un, c'est un plaisir...
    Bien à toi la communauté...
    Denis...

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 508
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 508
    Par défaut
    Salut,

    Si je puis me permettre, ton code ne fait pas ce qu'il annonce (non respect du SRP: https://en.wikipedia.org/wiki/Single...lity_principle).
    La fonction NomCelExist dont le nom laisse supposer qu'elle vérifie qu'un nom existe, fait autre chose et renvoie un résultat faux:
    - Si le nom existe, elle renvoie True, Ok.
    - Si le nom n'existe pas, elle le créée et renvoie False, ce qui pose problème.
    D'une part créer un nom n'est pas son job.
    D'autre part elle renvoie False alors qu'elle vient de créer un nom, donc il existe, c'est incohérent.
    Quid si l'on ne veut pas créer le nom mais simplement vérifier son existence ? Opération impossible, il existera quoi qu'il arrive.

    La propriété Names renvoie un objet dont le comportement s'apparente à une collection.
    Sachant qu'une erreur d'exécution (exception) sera levée si l'on essaye d'accéder à un élément d'une collection dont l'indice ou la clef n'existe pas, on peut tourner ce comportement à notre avantage avec une fonction générique:
    On tente d'accéder à un élément, si succès, la clef existe,
    si échec (exception) la clef n'existe pas.
    Qui dit exception, dit gestionnaire d'erreur. Ce qui peut se traduire comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Public ExistInCollection(ByVal Clef As String, ByRef Collection As Object) As Boolean
    On Error Goto Error
        Dim Element As Variant
        Element = collection(Clef)    '// On tente d'accéder à un élément
        ExistInCollection = True       '// aucune exception n'a été levée, la clef existe
    Exit Function
    Error:
        ExistInCollection = False    '// Une exception a été levée, la clef n'existe pas
    End Function
    La collection en argument est de type Object, car la bibliothèque Excel propose de nombreuses collections fortement typées, qui bien que leur comportement soit similaire, ne sont pas strictement compatible avec le type Collection de VBA. Le type Object commun à tous les objets permet de contourner cette restriction.

    Mais, ce code ne fonctionne que si la collection ne contient que des types elementaires (integer, long, double, string, ect ...), en effet l'opérateur d'assignation lève une exception si l'on tente d'assigner un objet, Il va faloir écrire une fonction spécialisée pour ce cas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Public ExistInCollection(ByVal Clef As String, ByRef Collection As Object) As Boolean
    On Error Goto Error
        Dim Element As Variant
        Set Element = collection(Clef)    '// On tente d'accéder à un élément
        ExistInCollection = True       '// aucune exception n'a été levée, la clef existe
    Exit Function
    Error:
        ExistInCollection = False    '// Une exception a été levée, la clef n'existe pas
    End Function
    Mais alors, nous aurons 2 fonction spécialisées, ce qui implique de connaitre à l'avance le contenu de la collection ciblée, ce qui, dans le cadre de la généricité, n'est pas souhaitable.
    On va donc écrire une fonction supplémentaire qui appelera nos 2 fonctions spécialisées, ces dernières deviendrons privées afin de prévenir les fautes de programmation.
    Si l'une ou l'autre des fonction spécialisée renvoie True, alors la clef existe, et on aura achevé la généricité:
    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 ExistInCollection(ByVal Clef As String, ByRef Collection As Object) As Boolean
            '// Appel des 2 fonctions spécialisées
        ExistInCollection = ExistIncollectionByVal(Clef, Collection) Or ExistInCollectionByRef(Clef, Collection)
    End function
     
    Private ExistInCollectionByVal(ByVal Clef As String, ByRef Collection As Object) As Boolean
    On Error Goto Error
        Dim Element As Variant
        Element = collection(Clef)    '// On tente d'accéder à un élément (elementaire)
        ExistInCollectionByVal = True       '// aucune exception n'a été levée, la clef existe
    Exit Function
    Error:
        ExistInCollectionByVal = False    '// Une exception a été levée, la clef n'existe pas
    End Function
     
    Public ExistInCollectionByRef(ByVal Clef As String, ByRef Collection As Object) As Boolean
    On Error Goto Error
        Dim Element As Variant
        Set Element = collection(Clef)    '// On tente d'accéder à un élément (objet)
        ExistInCollectionByRef = True       '// aucune exception n'a été levée, la clef existe
    Exit Function
    Error:
        ExistInCollectionByRef = False    '// Une exception a été levée, la clef n'existe pas
    End Function

  4. #4
    Membre éclairé Avatar de DenisHen
    Homme Profil pro
    Dessinateur / projeteur
    Inscrit en
    Novembre 2013
    Messages
    415
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Dessinateur / projeteur
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Novembre 2013
    Messages : 415
    Par défaut
    Bonjour deedolith et merci pour tes explication.

    Certes, mon code n'est pas en adéquation avec mon sujet, mais il l'est avec ma demande. Enfin je le pense...

    Par contre, tes codes sont trop complexes pour mon petit niveau, je les comprends (presque), mais je choisirais de ne pas les intégrer au mien (pour l'instant), car je ne pourrais pas les adapter plus tard, s'il y a du changement...

    Je pense que tu comprendras que préfère un code (même un peu bancale) mais que je comprend, et peut le modifier, à la place d'un code impeccable, sans défaut, mais que je ne maitrise pas.

    Mais je vais prendre du temps pour analyser et tester ton code, qui me semble très approprié et particulièrement concis.

    Désolé de n'avoir pas respecté le "SRP", mais en tant que débutant, comme tant d'autres, nous devrions nécessiter d'une certaine amplitude d'erreurs.

    Et je vois que tu en es conscient, car tu m'as donné une solution, dont je te remercie grandement, pour moi et tout les autres "petits" développeurs amateurs.

    De plus, tes explications sont très généreusement argumentés (donc, d'une énorme valeur pour mon bas niveau).

    Je reste désolé pour mon non respect du SRP, et si un WebMaster passe par là, je ne prendrais pas mauvaise augure de la suppression de mon poste.

    J'ai juste pensé que, ayant cherché plusieurs heures ma réponse, j'ai trouvé communautaire de partager ma solution...

    Je connais Developpez.com depuis plusieurs décennies, et je sais que ces membres sont dévoués, pertinents et toujours à l'écoute des nouveaux ou des "petits" développeurs comme aux plus grands.

    Encore merci à toi deedolith .

    Bien à toi la communauté.

    Denis...

  5. #5
    Membre émérite Avatar de Valtrase
    Homme Profil pro
    Jeune retraité...
    Inscrit en
    Janvier 2016
    Messages
    509
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Jeune retraité...
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Janvier 2016
    Messages : 509
    Par défaut
    Bonjour à tous,

    @DenisHen, @Deedolith à raison une fonction ne doit avoir qu'un but, ici c'est de tester si le champ nommé existe.
    Si vous voulez :
    • Chercher si le champ existe
    • Si oui, lui attribuer une valeur

    Alors la fonction devrait retourner un objet Range que vous pouvez manipuler. Si le nom n'est pas trouvé, alors elle renvoie Nothing.
    A vous de traiter le retour dans une procédure.
    Exemple de fonction avec deux arguments :
    • Le nom du champ nommé
    • En option le classeur où l'on doit faire la recherche.


    Voici le code de la fonction :
    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
    '@Description "Renvoi un objet Range, Nothing si pas trouvée."
    Public Function GetNameRange(ByVal Nom As String, Optional ByVal OWorkbook As Excel.Workbook) As Excel.Range
        Dim localWorkbook As Excel.Workbook
        Set localWorkbook = OWorkbook
        If localWorkbook Is Nothing Then Set localWorkbook = ThisWorkbook
        With localWorkbook
            ' // Boucle sur tous les nom pour savoir si ce nom existe
            Dim itemName As Excel.Name
            For Each itemName In .Names
                With itemName
                    If StrComp(Nom, .Name, vbTextCompare) = 0 Then
                        Dim RefersTo As String
                        ' // Récupération de la référence après le signe égal
                        RefersTo = Replace(.RefersTo, "=", vbNullString, 1, -1, vbTextCompare)
                        If InStr(1, .RefersTo, "!", vbTextCompare) Then
                            ' // Construction du chemin complet à la référence
                            Set GetNameRange = localWorkbook.Worksheets(Split(RefersTo, "!", -1, vbTextCompare)(0)).Range(Split(RefersTo, "!", -1, vbTextCompare)(1))
                        End If
                    End If
                End With
            Next
        End With
    End Function
    Et pour l'appel, une procédure qui reçois trois arguments :
    • Le nom du champ nommé
    • La valeur à lui donner
    • En option le classeur de recherche.

    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
    '@Description "Ecrit une valeur dans un champ nommé si il existe."
    Public Sub AddNameToCell(ByVal Nom As String, ByVal Value As Variant, Optional ByVal OWorkbook As Excel.Workbook)
        Dim localWorkbook As Excel.Workbook
        Set localWorkbook = OWorkbook
        If localWorkbook Is Nothing Then Set localWorkbook = ThisWorkbook
     
        Dim itemrange As Excel.Range
        ' // On récupère la plage du champ nommé
        Set itemrange = GetNameRange(Nom, localWorkbook)
        If Not itemrange Is Nothing Then
            itemrange.Value = Value
        Else
            MsgBox "Pas de champ nommé portant ce nom !"
        End If
     
    End Sub

  6. #6
    Membre éclairé Avatar de DenisHen
    Homme Profil pro
    Dessinateur / projeteur
    Inscrit en
    Novembre 2013
    Messages
    415
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Dessinateur / projeteur
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Novembre 2013
    Messages : 415
    Par défaut
    Bonjour @Valtrase, et merci de venir dans ce poste.
    Mais je n'ai jamais dis que @Deedolith avait tord, loin de moi cette pensée...
    J'ai juste demandé un peu de mansuétude envers mon ignorance (et pas que la mienne, nous sommes légion).
    J'ai même précisé que @Deedolith m'avais proposé un code qui, je me répète, continu de réclamer toute mon attention (depuis ma lecture, en fait).
    Si nous (pauvre débutants) vous sollicitons, c'est pour votre connaissance livresque du code et de ce qui en découle et votre grand sens du partage et de votre "altruisme", à la Socrate.
    Et nous vous en remercierons jamais assez, ne l'oubliez jamais...

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

Discussions similaires

  1. [Toutes versions] Comment ressortir le nom d'une cellule active
    Par CINDYDYDY dans le forum Excel
    Réponses: 11
    Dernier message: 11/03/2020, 20h08
  2. Comment appeler le nom d'une cellule dans un programme VBA
    Par Sandra_R dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 27/11/2015, 16h38
  3. Réponses: 2
    Dernier message: 01/11/2005, 18h47
  4. Comment savoir si le bouton d'une fenêtre est enfoncé ?
    Par Lecerf dans le forum Composants VCL
    Réponses: 7
    Dernier message: 21/09/2005, 19h38
  5. Réponses: 19
    Dernier message: 26/01/2005, 10h41

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