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. LecallType—VbGet,VbLet,VbSetouVbMethod— 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 membresPublic. 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 écrireobj.Memberdirectement.
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
CallByNameaux côtés deApplication.RunetEvaluate - 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
