Bonjour,
J'ai besoin d'un (ou plusieurs) avis sur ce problème VBA.
Dans le Sub b() je reçois un argument quelconque (tout type de variable).
Lorsque je passe un Range d'une seule cellule, ce n'est pas le Range qui est passé mais le Range.Value.
Comment éviter cela et empêcher ce ".Value" implicite ?
VB:
Sub a()
Dim r As Range
Set r = [A1]
Call b(r)
End Sub
Sub b(v As Variant)
'Problème ici -> v contient [A1].Value et non le Range [A1]
MsgBox VarType(v)
End Sub
Sub a()
Dim r As Range
Set r = [A1]
Call b(r)
End Sub
Sub b(v As Variant)
'Problème ici -> v contient [A1].Value et non le Range [A1] => totalement faux !!!
MsgBox IsObject(v)
MsgBox v.Parent.Name 'teste l'objet v
End Sub
IsObject renvoie VRAI donc v est bien un objet Range avec toutes ses propriétés.
Bonjour @soan
En effet, nouveau papillon pour le printemps 2021 .
Merci pour ta proposition.
Je peux passer l'adresse seule mais je ne bénéficie plus des autres propriétés du Range en particulier le .Parent et le .Parent.Parent.
Une autre option est de passer par une table de Variant de 1 élément contenant le Range cellule mais c'est encore indirect.
Certes mais je veux pouvoir passer autre chose qu'un Range (pour stocker dans un Dictionary).
Le truc c'est que c'est juste un problème lié à un Range d'une cellule.
Set r = [A1]
Call b(r) -> passe la valeur [A1].Value
Set r = [A1:A2]
Call b(r) -> passe le Range [A1:A2]
C'est ce ".Value" implicite d'un Range d'une seule cellule qui fiche le bazar.
D'ailleurs ça m'a toujours déplu qu'on puisse utiliser [A1] ou [A1].Value indistinctement.
La syntaxe a (devrait avoir) un sens et qualifier ce qu'on utilise c'est la moindre des choses.
L'expression entre crochet est évaluée car dans ce cas [...]= Evaluate(...) qui donne le résultat de l'expression !
C'est donc normal que dans le procédure b vous receviez la valeur de A1 et non sont objet range.
Si vous voulez l'objet range :
VB:
Sub a()
Dim r As Range
Set r = Range("A1") ' ou Cells(1,1)'
Call b(r)
End Sub
Cordialement
Edition : dans set r = [A1:A2] c'est l'objet qui est retourné, car une plage de cellules n'a pas de valeur propre.
Sub a()
Dim r As Range
Set r = [A1]
r = 1600
Call b(r)
r = "Staple"
Call c(r)
End Sub
Sub b(v As Range)
MsgBox TypeName(v) & Chr(13) & VarType(v) '->5
End Sub
Sub c(v As Variant)
MsgBox TypeName(v) & Chr(13) & VarType(v) '->8
End Sub
EDITION: Bonjour Roblochon
Un truc m'échappe
Chez moi, le MsgBox n'affiche jamais la valeur de A1
(voir message précédent)
L'expression entre crochet est évaluée car dans ce cas [...]= Evaluate(...) qui donne le résultat de l'expression !
C'est donc normal que dans le procédure b vous receviez la valeur de A1 et non sont objet range.
sauf que l'évaluation est faite pour r qui est un range, l'évaluation renvoie forcément un range et on passe bien un range à la sub et non la valeur de la range.
je suis entièrement d'accord avec toi d'autant plus que toute évaluation implique du temps de traitement. Aussi faible soit il, il peut avoir un impact non négligeable sur un grand ensemble de données.
Sub a()
Dim r As Range
Set r = [A1]
Call b(r)
End Sub
Sub b(v As Variant)
'Problème ici -> v contient [A1].Value et non le Range [A1] => totalement faux !!!
MsgBox IsObject(v)
MsgBox v.Parent.Name 'teste l'objet v
End Sub
IsObject renvoie VRAI donc v est bien un objet Range avec toutes ses propriétés.
Bonjour @job75,
Tu as raison. C'est le VarType(v) qui va chercher la valeur. Ça m'a confusé.
Un MsgBox TypeOf v Is Range retourne vrai également.
Merci pour ton éclairage salutaire. Et merci aussi à tous ceux qui s'y sont collés