XL 2016 VBA - Comment faire reconnaître l'argument Variant comme Range

Dudu2

XLDnaute Barbatruc
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

Merci par avance.
 
Solution
Bonjour Dudu2, le fil,

Testez :
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] => 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.

C'est vérifié avec la 2ème MsgBox.

A+

Dudu2

XLDnaute Barbatruc
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.
 

Bernard_XLD

XLDnaute Barbatruc
Membre du Staff
Bonjour Dudu2, Soan, le forum

à mon humble avis:
VB:
Sub b(v As Range)
si tu veux un range, déclare un range, un variant renverra une donnée typée adaptée à l'instruction ou la méthode appellante.

Cordialement
 

Dudu2

XLDnaute Barbatruc
Bonjour @Yeahou,
si tu veux un range, déclare un range
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.
 
Dernière édition:

Hasco

XLDnaute Barbatruc
Repose en paix
Bonjour,

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.
 

Staple1600

XLDnaute Barbatruc
Bonjour le fil,

Comme Paf, je propose TypeName
VB:
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)
 

Bernard_XLD

XLDnaute Barbatruc
Membre du Staff
Bonjour le fil

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.
 

Hasco

XLDnaute Barbatruc
Repose en paix
Bonjour Roblochon
Un truc m'échappe
Chez moi, le MsgBox n'affiche jamais la valeur de A1
(voir message précédent)
C'est pourquoi je ne me sers qu'exceptionnellement de la notation [ ] on ne sait jamais exactement ce qu'elle va retourner avec les objets. Tester :
VB:
Sub a()
    Dim r As Range
    Set r = ["A1"] 'devrait planter
    r = 1600
    Call b(r)
    r = "Staple"
    Call c(["A1"]) ' passera l'objet range ou sa valeur.
End Sub

Cordialement
 

Bernard_XLD

XLDnaute Barbatruc
Membre du Staff
C'est pourquoi je ne me sert qu'exceptionnellement de la notation [ ] on ne sait jamais exactement ce qu'elle va retourner avec les objets. Tester :
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.
 

job75

XLDnaute Barbatruc
Bonjour Dudu2, le fil,

Testez :
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] => 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.

C'est vérifié avec la 2ème MsgBox.

A+
 

Discussions similaires

Statistiques des forums

Discussions
312 231
Messages
2 086 442
Membres
103 210
dernier inscrit
Bay onais