🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA CallByName dans Excel — Lire ou écrire une propriété, ou exécuter une méthode, par son nom

|

VBA CallByName dans Excel — Lire ou écrire une propriété, ou exécuter une méthode, par son nom

TL;DR — CallByName(object, "MemberName", callType, args) lit une propriété, écrit une propriété ou exécute une méthode sur un objet en utilisant le nom du membre sous forme de chaîne. Le callType — VbGet, VbLet, VbSet ou VbMethod — indique à VBA laquelle de ces quatre choses vous voulez dire, et se tromper est la cause numéro un de l'erreur 438. Il n'atteint que les membres Public. Utilisez-le quand le nom de la propriété ou de la méthode se décide à l'exécution — un formulaire piloté par les données, une table de réglages — et non quand vous connaissez déjà le membre et pouvez écrire obj.Member directement.

Sub SetByName()
    Dim ctl As Object
    Set ctl = Me.Controls("txtName")
    ' Ecrit une propriete dont le nom est une chaine :
    CallByName ctl, "Value", VbLet, "Ada Lovelace"
    ' Lit une propriete dont le nom est une chaine :
    MsgBox CallByName(ctl, "Value", VbGet)
End Sub

Normalement, vous atteignez un membre d'un objet en le tapant : range.Value, sheet.Name, form.Hide. Cela fonctionne parce que vous connaissez le membre au moment où vous écrivez le code. CallByName sert au cas où vous ne le connaissez pas — le nom de la propriété ou de la méthode arrive sous forme de texte, depuis une table, une feuille de configuration ou une boucle. C'est le deuxième de trois outils qui partagent une même idée. Application.Run transforme une chaîne en une macro qui s'exécute ; CallByName transforme une chaîne en un appel de membre sur un objet ; et Evaluate transforme une chaîne en une expression Excel calculée. Tous trois échangent le compilateur contre de la souplesse à l'exécution : parce que le nom du membre est du texte, une faute de frappe n'est plus un trait rouge ondulé — c'est une erreur d'exécution. La même règle s'applique donc : ne donnez jamais à CallByName un nom de membre que vous n'avez pas vous-même construit ou validé.

Ce que vous allez apprendre

  • La place de CallByName aux côtés de Application.Run et Evaluate
  • Les quatre types d'appel — VbGet, VbLet, VbSet, VbMethod — et ce que chacun signifie
  • Pourquoi le mauvais type d'appel déclenche l'erreur 438, et comment lire le message
  • Le passage d'arguments à une méthode ou à une propriété indexée
  • La règle du tout-public qui fait échouer certains appels en silence
  • Le motif pour lequel la fonction existe : appliquer à un objet une table de noms et de valeurs

Le modèle mental : la réflexion appliquée aux membres d'un objet

Application.Run recherche une macro par son nom. CallByName fait le même tour de passe-passe un cran plus bas : il recherche un membre d'un objet précis par son nom. Vous lui remettez l'objet, le nom du membre sous forme de chaîne, et une chose de plus que la syntaxe directe vous cache — le type d'accès que vous voulez. obj.Value = 5, x = obj.Value et obj.Refresh semblent différents dans du code ordinaire, mais pour CallByName ce sont le même appel avec un callType différent.

x = obj.Caption            ' direct : lecture
CallByName obj, "Caption", VbGet          ' la meme lecture, nom du membre sous forme de chaine

Cet argument callType supplémentaire est toute la raison pour laquelle CallByName paraît déroutant. Dès que vous le voyez comme « lequel des quatre genres d'accès à un membre », la fonction cesse d'être mystérieuse.

Les quatre types d'appel

VBA distingue quatre choses que vous pouvez faire à un membre, et vous devez indiquer à CallByName laquelle :

CallByName obj, "Value",   VbGet                 ' lit une propriete  -> renvoie la valeur
CallByName obj, "Value",   VbLet, "New text"     ' ecrit une propriete de valeur
CallByName obj, "Range",   VbSet, someRange      ' ecrit une propriete OBJET (necessite Set)
CallByName obj, "Refresh", VbMethod              ' execute une methode

La distinction entre VbLet et VbSet reflète le Let et le Set propres à VBA : utilisez VbLet pour une valeur simple (un nombre, une chaîne, un booléen) et VbSet pour une référence d'objet (affecter un Range ou un autre objet à une propriété). VbGet lit ; VbMethod appelle. Presque tous les bugs de CallByName consistent à choisir le mauvais parmi ces quatre.

Le piège : le mauvais type d'appel déclenche l'erreur 438

Voici la ligne à retenir. Si le membre n'existe pas, ou si vous demandez le mauvais genre d'accès, VBA ne peut pas vous prévenir à la compilation — le nom est une chaîne — vous obtenez donc l'erreur d'exécution 438, « L'objet ne prend pas en charge cette propriété ou cette méthode » :

' Faux : Caption est une propriete, pas une methode
CallByName lbl, "Caption", VbMethod        ' -> erreur 438

' Correct : la lire avec VbGet
Dim text As String
text = CallByName(lbl, "Caption", VbGet)

Le message est un peu trompeur : bien souvent, l'objet prend en charge le membre — vous l'avez simplement demandé de la mauvaise façon (un VbMethod sur une propriété, ou un VbGet sur une méthode qui réclame VbMethod). Quand vous voyez 438 venir de CallByName, vérifiez le type d'appel avant de douter du nom du membre. Et comme le nom vient des données, enveloppez les appels issus de l'exécution dans une gestion On Error pour qu'un nom inattendu soit un résultat pris en charge, pas un plantage.

Passer des arguments à une méthode ou à une propriété indexée

Les arguments viennent après le type d'appel, dans l'ordre :

' Une methode avec arguments :
CallByName ws, "Protect", VbMethod, "password123"

' Une propriete indexee (Cells(2, 3)) via CallByName :
Dim v As Variant
v = CallByName(ws, "Cells", VbGet, 2, 3)     ' equivaut a ws.Cells(2, 3)

Les arguments sont positionnels, exactement comme avec Application.Run. Si une méthode en prend plusieurs, énumérez-les dans l'ordre de la signature. C'est aussi ainsi que vous atteignez des propriétés indexées comme Cells(row, col) quand le nom de la propriété est lui-même dynamique.

La règle du tout-public

CallByName ne peut atteindre que les membres Public. Une propriété ou une méthode Private à l'intérieur d'un module de classe lui est invisible et — parce que le nom est une chaîne — vous obtenez la même 438 d'exécution que pour une faute d'orthographe, sans le moindre indice que le vrai problème est la visibilité. Si un appel échoue sur un membre dont vous êtes sûr de l'existence, confirmez qu'il est déclaré Public sur la classe de l'objet. C'est un accroc fréquent quand vous pilotez vos propres objets de classe par leur nom plutôt que des objets Excel intégrés.

Le motif pour lequel elle existe : une table de noms et de valeurs

CallByName mérite sa place quand vous avez beaucoup de membres à toucher et que leurs noms vivent dans les données. Le cas d'école : appliquer une table de noms de propriétés et de valeurs à un contrôle, une forme ou un graphique, sans écrire une ligne d'affectation par propriété.

' Les reglages pourraient venir d'une feuille : colonne A = propriete, colonne B = valeur
Dim props As Variant, vals As Variant, i As Long
props = Array("Caption", "Width", "Visible")
vals  = Array("Total", 120, True)
For i = LBound(props) To UBound(props)
    CallByName btn, props(i), VbLet, vals(i)      ' une seule boucle au lieu de trois affectations
Next i

Trois propriétés, c'est un jouet ; trente, c'est un vrai formulaire, et c'est là que la boucle remplace un mur de lignes btn.Caption = ... : btn.Width = .... Le jugement à porter est le même que pour le reste de cette famille : si les noms de membres sont des constantes que vous tapez une fois, utilisez la syntaxe directe — btn.Caption = "Total" est plus clair et le compilateur le vérifie. Ce n'est que lorsque les noms sont réellement des données que CallByName compense la perte de sécurité à la compilation.

Comment ExcelMaster vous aide

Les erreurs, ici, sont discrètes : un VbMethod là où il fallait un VbGet, un membre Private que vous ne pouvez pas atteindre, un nom venu d'une feuille de réglages qui ne correspond plus à l'objet. Chacune remonte sous la forme de la même erreur 438, difficile à situer.

ExcelMaster vous laisse décrire l'intention — « règle ces propriétés sur ce contrôle à partir d'une table, et préviens-moi si un nom ne convient pas » — et il écrit la boucle CallByName avec les bons types d'appel et un garde-fou d'erreur déjà en place. Vous conservez le classeur et le code, et vous vous épargnez la chasse à la 438.

Questions fréquentes

Que fait CallByName en VBA ?

Il lit une propriété, écrit une propriété ou exécute une méthode sur un objet en utilisant le nom du membre sous forme de chaîne plutôt que du code écrit en dur. La syntaxe est CallByName(object, "MemberName", callType, args), où callType vaut VbGet, VbLet, VbSet ou VbMethod. Utilisez-le quand le nom du membre se décide à l'exécution ; quand vous le connaissez au moment d'écrire le code, object.Member est plus clair.

Quelle est la différence entre VbGet, VbLet, VbSet et VbMethod ?

VbGet lit une propriété et renvoie sa valeur. VbLet écrit une propriété de valeur simple (nombre, chaîne, booléen). VbSet écrit une propriété d'objet, à l'image du Set de VBA. VbMethod exécute une méthode. Choisir le mauvais est la cause habituelle de l'erreur 438, car l'objet prend en charge le membre, mais pas de la manière que vous avez demandée.

Pourquoi CallByName déclenche-t-il l'erreur 438 ?

Parce que le membre que vous avez nommé ne peut pas être accédé de la façon demandée : le nom est mal orthographié, le membre est Private (CallByName n'atteint que les membres Public), ou le type d'appel est erroné — par exemple VbMethod sur une propriété. Comme le nom est une chaîne, VBA ne peut détecter cela qu'au moment où la ligne s'exécute. Vérifiez le type d'appel et la visibilité du membre.

CallByName peut-il appeler une méthode privée ?

Non. CallByName n'atteint que les membres Public. Une propriété ou une méthode Private dans un module de classe déclenche l'erreur 438, la même que celle d'un nom mal orthographié, ce qui peut compliquer le diagnostic. Rendez le membre Public si vous devez l'atteindre par son nom.

Quand faut-il utiliser CallByName plutôt que object.Member ?

Uniquement quand le nom du membre est dynamique — il vient d'une table, d'une feuille de configuration ou d'une boucle sur des noms de propriétés. Si vous connaissez le membre au moment d'écrire le code, utilisez object.Member : c'est plus clair et le compilateur détecte les fautes de frappe. Pour exécuter une macro autonome par son nom, utilisez plutôt Application.Run.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 27/09/2026.

Guides associés : VBA Application.Run · VBA Evaluate · VBA Class Module · VBA With · VBA On Error · VBA CreateObject · VBA Dictionary