Quelle est la différence entre .text, .value et .value2?

180

Je ne demande de l'aide pour aucun script, mais ma question est une clarification. Dernièrement, j'ai fait beaucoup de scripts VB dans Excel, donc je fais vraiment référence à Excel dans cette question. Quelle est la différence entre .text, .value et .value2? Comme quand dois-je utiliser target.text, target.value et target.value2? Je n'ai jamais utilisé l'option value2 mais j'aimerais quand même savoir à quoi elle sert.

Parfois, si j'utilise .text, cela me donne une erreur et je dois utiliser .value lorsque je vérifie ou manipule uniquement le texte d'une cellule. Parfois, quand je pense que je devrais utiliser .value, j'obtiens une erreur et je dois utiliser .text. Habituellement, il accepte l'un ou l'autre ou sans problème, mais parfois cela fait une différence. Je sais qu'il doit y avoir une certaine logique à cela, mais je n'arrive pas à comprendre.

J'ai également découvert que si vous le laissez simplement comme cible sans spécifier .text ou .value, cela fonctionnera initialement, mais quelque chose que quelqu'un fait finira par provoquer une erreur dans le script, il est donc toujours préférable d'utiliser un .something dessus . Je suppose que ce que je demande, c'est si quelqu'un peut me donner une sorte de ligne directrice, une règle empirique, sur la façon d'utiliser correctement chacune d'elles et quand elle doit être utilisée.

Merci pour l'explication les gars. Je le comprends mieux. Ce sont tous les deux de bonnes explications. Voici un petit exemple de certains de mes codes qui fonctionnent. Je pensais que cela devrait être target.text, mais cela ferait une erreur alors quand j'utilisais target.value, cela fonctionnait.

If LCase(Target.Value) = LCase("HLO") And Target.Column = 15 Then
    Target.Value = "Higher Level Outage"
End If

Je suis encore un peu confus car quand je pense à valeur ou valeur2, surtout après vos réponses que vous avez fournies, je pense qu'elles ne devraient être utilisées que pour les chiffres. Cependant, dans mon exemple, je parle strictement de texte, qui est une grande partie de ce à quoi mon script fait référence (du texte dans les cellules, plus que des nombres).

Chris
la source
LCase (Target.Value) échouera si Target.Value n'est pas contraignable en chaîne car LCase nécessite une chaîne pour un argument. Vous devriez d'abord vérifier le VarType selon ma réponse. Notez également que vous pouvez utiliser UCase à la place et comparer directement à "HLO": cela ne sert à rien d'opérer sur un littéral.
Bathsheba
Merci pour les informations sur VarType. En ce qui concerne le LCase ou l'UCase pour cela, peu importe celui que j'ai utilisé. Certaines personnes le saisissent comme hlo et d'autres comme HLO. D'après ce que j'ai vu, il est apparu que la minuscule était utilisée plus souvent.
Chris

Réponses:

238

.Textvous donne une chaîne représentant ce qui est affiché à l'écran pour la cellule. Utiliser .Text est généralement une mauvaise idée car vous pourriez obtenir ####

.Value2 vous donne la valeur sous-jacente de la cellule (peut être vide, chaîne, erreur, nombre (double) ou booléen)

.Value vous donne la même chose que .Value2 sauf si la cellule a été formatée en tant que devise ou date, elle vous donne une devise VBA (qui peut tronquer les décimales) ou une date VBA.

L'utilisation de .Value ou .Text est généralement une mauvaise idée car vous ne pouvez pas obtenir la valeur réelle de la cellule et elles sont plus lentes que .Value2

Pour une discussion plus approfondie, voir mon texte vs valeur vs valeur2

Charles Williams
la source
6
J'utiliserais probablement Format pour contrôler la conversion du nombre en chaîne: var = Format (Range ("a1"). Value2, "#")
Charles Williams
2
J'espère que ce n'est pas une question distincte mais: quelle est la valeur par défaut? L'OP prétend vaguement que laisser de côté texte / valeur / valeur2 est problématique, mais il est sûrement par défaut l' un d'entre eux?
Martin F
3
Désolé de réveiller ce post oooooold, mais je ne vois pas l'avantage de forcer un Datedans un Double(utilisation .Value2) lorsque ce dont vous avez besoin est un Date. Ne devrait-il pas .Valueêtre préféré .Value2à une Datevaleur? L'article lié ne le précise pas non plus. Performance car pas de conversion? Bien sûr, mais si votre code VBA fonctionne avec a Date, vous perdrez cet avantage en effectuant la conversion vous-même, implicitement ou explicitement ... (contexte - n'hésitez pas à peser)
Mathieu Guindon
2
@ Mat's Mug - le problème est qu'Excel n'a pas de véritable type de données Date - les dates et heures Excel ne sont que des doubles qui dépendent du format appliqué ou modifié par l'utilisateur pour apparaître sous forme de dates, d'heures ou de devises ou simplement nombre. Donc Value contraint un double Excel à une date VBA mais Value2 ne fait aucune contrainte ... Pour les dates contraindre le double à une date ne fait probablement aucun dommage tant que le code comprend que cela dépend d'un format variable: pros et les inconvénients de toute façon - ce dont nous avons vraiment besoin, ce sont des types de données Excel plus natifs pour éviter ce problème.
Charles Williams
2
Quand je veux définir une valeur de cellule égale à une autre cellule sans conversion de type (par exemple, sans la conversion d' un numéro enregistré sous forme de texte à un numéro) J'utilise ceci: Format$(Range.Value2, Range.NumberFormat).
ChrisB
55

Sauf le premier formulaire de réponse Bathsheba, sauf les informations MSDN pour:

.Value
.Value2
.Text

vous pouvez analyser ces tableaux pour mieux comprendre les différences entre les propriétés analysées.

entrez la description de l'image ici

Kazimierz Jawor
la source
4
@Chris, utilisez .Valuecomme propriété standard tout le temps - pour le texte et les nombres. À utiliser .Value2lorsque vous pensez à la date et à certains chiffres. Et utilisez .Texttoujours si vous avez besoin de continuer à mettre en forme tout ce que vous avez dans la cellule / plage. Donc, votre exemple de question est correct!
Kazimierz Jawor
1
pourquoi la date a changé de 10h12 à 10h05? faute de frappe?
Katrin
1
Je pense que c'est juste le temps écoulé entre la génération des résultats et le moment de la capture d'écran
Kazimierz Jawor
25

target.Value te donnera un Variant type

target.Value2vous donnera également un Varianttype mais a Dateest contraint à unDouble

target.Texttente de forcer à un Stringet échouera si le sous Variant- jacent n'est pas contraignable à un Stringtype

La chose la plus sûre à faire est quelque chose comme

Dim v As Variant
v = target.Value 'but if you don't want to handle date types use Value2

Et vérifiez le type de la variante en utilisant VBA.VarType(v)avant de tenter une coercition explicite.

Bathsheba
la source
11

Concernant les conventions en C #. Supposons que vous lisiez une cellule contenant une date, par exemple le 22/10/2014.

Lors de l'utilisation:

.Text, vous obtiendrez la représentation formatée de la date, comme indiqué dans le classeur à l'écran:
22/10/2014 . Le type de cette propriété est toujours, stringmais pas toujours, un résultat satisfaisant.

.Value, le compilateur tente de convertir la date en DateTimeobjet: {2014-10-22 00:00:00} Très probablement utile uniquement lors de la lecture des dates.

.Value2, vous donne la valeur réelle sous-jacente de la cellule. Dans le cas des dates, c'est une série de dates: 41934 . Cette propriété peut avoir un type différent selon le contenu de la cellule. Pour les périodiques de date cependant, le type est double.

Vous pouvez donc récupérer et stocker la valeur d'une cellule dans l'un ou l' autre dynamic, mais notez que la valeur aura toujours une sorte de type inné sur lequel vous devrez agir.varobject

dynamic x = ws.get_Range("A1").Value2;
object  y = ws.get_Range("A1").Value2;
var     z = ws.get_Range("A1").Value2;
double  d = ws.get_Range("A1").Value2;      // Value of a serial is always a double
feu de soie
la source
2

.Text est la valeur affichée de la cellule formatée; .Value est la valeur de la cellule éventuellement augmentée d'indicateurs de date ou de devise; .Value2 est la valeur sous-jacente brute dépouillée de toute information superflue.

range("A1") = Date
range("A1").numberformat = "yyyy-mm-dd"
debug.print range("A1").text
debug.print range("A1").value
debug.print range("A1").value2

'results from Immediate window
2018-06-14
6/14/2018 
43265 

range("A1") = "abc"
range("A1").numberformat = "_(_(_(@"
debug.print range("A1").text
debug.print range("A1").value
debug.print range("A1").value2

'results from Immediate window
   abc
abc
abc

range("A1") = 12
range("A1").numberformat = "0 \m\m"
debug.print range("A1").text
debug.print range("A1").value
debug.print range("A1").value2

'results from Immediate window
12 mm
12
12

Si vous traitez la valeur de la cellule, la lecture de la valeur brute .Value2 est légèrement plus rapide que celle de .Value ou .Text. Si vous recherchez des erreurs, .Text renverra quelque chose comme du #N/Atexte et pourra être comparé à une chaîne tandis que .Value et .Value2 s'étoufferont en comparant leur valeur renvoyée à une chaîne. Si vous avez une mise en forme de cellule personnalisée appliquée à vos données, .Text peut être le meilleur choix lors de la création d'un rapport.


la source
0

Par curiosité, je voulais voir comment Valueperformé contre Value2. Après environ 12 essais de processus similaires, je n'ai pas pu voir de différences significatives de vitesse, je recommanderais donc toujours d'utiliserValue . J'ai utilisé le code ci-dessous pour exécuter des tests avec différentes plages.

Si quelqu'un voit quelque chose de contraire concernant les performances, veuillez poster.

Sub Trial_RUN()
    For t = 0 To 5
        TestValueMethod (True)
        TestValueMethod (False)
    Next t

End Sub




Sub TestValueMethod(useValue2 As Boolean)
Dim beginTime As Date, aCell As Range, rngAddress As String, ResultsColumn As Long
ResultsColumn = 5

'have some values in your RngAddress. in my case i put =Rand() in the cells, and then set to values
rngAddress = "A2:A399999" 'I changed this around on my sets.



With ThisWorkbook.Sheets(1)
.Range(rngAddress).Offset(0, 1).ClearContents


beginTime = Now

For Each aCell In .Range(rngAddress).Cells
    If useValue2 Then
        aCell.Offset(0, 1).Value2 = aCell.Value2 + aCell.Offset(-1, 1).Value2
    Else
        aCell.Offset(0, 1).Value = aCell.Value + aCell.Offset(-1, 1).Value
    End If

Next aCell

Dim Answer As String
 If useValue2 Then Answer = " using Value2"

.Cells(Rows.Count, ResultsColumn).End(xlUp).Offset(1, 0) = DateDiff("S", beginTime, Now) & _
            " seconds. For " & .Range(rngAddress).Cells.Count & " cells, at " & Now & Answer


End With


End Sub

entrez la description de l'image ici

PGSystemTester
la source