Jaka jest różnica między .text, .value i .value2?

180

Nie proszę o pomoc przy żadnym scenariuszu, ale moje pytanie ma na celu wyjaśnienie. Ostatnio robiłem dużo skryptów VB w Excelu, więc naprawdę odnoszę się do Excela w tym pytaniu. Jaka jest różnica między .text, .value i .value2? Na przykład, kiedy powinienem używać target.text, target.value i target.value2? Nigdy nie korzystałem z opcji value2, ale nadal chciałbym wiedzieć, do czego jest używana.

Czasami, gdy używam .text, pojawia się błąd i muszę użyć .value, gdy tylko sprawdzam tekst w komórce lub manipuluję nim. Czasami, gdy myślę, że powinienem użyć .value, pojawia się błąd i muszę użyć .text. Zwykle akceptuje albo bez problemu, ale czasami robi różnicę. Wiem, że musi być w tym jakaś logika, ale nie mogę tego rozgryźć.

Dowiedziałem się również, że jeśli po prostu zostawisz go jako cel bez określenia .text lub .value, początkowo zadziała, ale coś, co ktoś zrobi, ostatecznie spowoduje błąd w skrypcie, więc zawsze najlepiej jest użyć na nim. . Myślę, że pytam, czy ktoś może dać mi jakąś wskazówkę, praktyczną zasadę, jak właściwie używać każdego z nich i kiedy należy go używać.

Dzięki za wyjaśnienie. Rozumiem to lepiej. Oba są dobrym wyjaśnieniem. Poniżej znajduje się mały przykład mojego kodu, który działa. Pomyślałem, że powinien to być target.text, ale wystąpiłby błąd, więc gdy użyłem target.value, zadziałało.

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

Nadal jestem trochę zdezorientowany, ponieważ kiedy myślę o value lub value2, szczególnie po twoich odpowiedziach, które udzieliłeś, myślę, że powinny być używane tylko do liczb. Jednak w moim przykładzie mówię o stricte tekstu, do którego odnosi się mój skrypt (tekst w komórkach, bardziej niż liczby).

Chris
źródło
LCase (Target.Value) nie powiedzie się, jeśli Target.Value nie będzie koercyjny do łańcucha, ponieważ LCase wymaga łańcucha jako argumentu. Powinieneś najpierw sprawdzić VarType zgodnie z moją odpowiedzią. Zauważ również, że możesz zamiast tego użyć UCase i porównać bezpośrednio z „HLO”: nie ma sensu operować na literale.
Batszeba
Dzięki za informacje o VarType. Jeśli chodzi o LCase lub UCase, to naprawdę nie ma znaczenia, którego użyłem. Niektórzy wpisują go jako hlo, a inni jako HLO. Z tego, co zobaczyłem, okazało się, że częściej używano małej litery.
Chris

Odpowiedzi:

238

.Textdaje ci ciąg reprezentujący to, co jest wyświetlane na ekranie dla komórki. Używanie .Text jest zwykle złym pomysłem, ponieważ możesz uzyskać ####

.Value2 podaje podstawową wartość komórki (może być pusta, ciąg, błąd, liczba (podwójna) lub logiczna)

.Value daje to samo co .Value2, z wyjątkiem sytuacji, gdy komórka została sformatowana jako waluta lub data, podaje walutę VBA (która może obcinać miejsca dziesiętne) lub datę VBA.

Używanie .Value lub .Text jest zwykle złym pomysłem, ponieważ możesz nie uzyskać rzeczywistej wartości z komórki i są one wolniejsze niż .Value2

Aby uzyskać bardziej obszerną dyskusję, zobacz mój tekst vs wartość vs wartość2

Charles Williams
źródło
6
Prawdopodobnie użyłbym Format do kontrolowania, w jaki sposób liczba jest konwertowana na ciąg: var = Format (Zakres ("a1"). Wartość2, "#")
Charles Williams
2
Mam nadzieję, że to nie jest oddzielne pytanie, ale: jakie jest domyślne? OP twierdzi niejasno, że pominięcie tekstu / wartości / wartości2 jest problematyczne, ale na pewno domyślnie jest to jeden z nich?
Martin F
3
Przepraszam, że budzę ten ooooo stary post, ale nie widzę korzyści z Dateprzekształcania a w Double(używanie .Value2), gdy to, czego potrzebujesz, to Date. Nie powinno .Valuebyć preferowane, .Value2gdy patrzysz na Datewartość? Z podanego artykułu też nie wynika jasno. Wydajność, ponieważ brak konwersji? Jasne, ale jeśli twój kod VBA działa z a Date, stracisz tę krawędź, wykonując konwersję samodzielnie, niejawnie lub jawnie ... (kontekst - nie krępuj się)
Mathieu Guindon
2
Kubek @ Mata - problem polega na tym, że Excel nie ma prawdziwego typu danych Data - daty i godziny w Excelu są po prostu podwojone, które zależą od tego, jaki format został zastosowany lub zmieniony przez użytkownika, aby pojawiały się jako daty, godziny lub waluta lub po prostu numer. Więc Value wymusza podwójne Excela do daty VBA, ale Value2 nie robi żadnego wymuszenia ... W przypadku dat wymuszenie podwójnej daty prawdopodobnie nie powoduje żadnych szkód, o ile kod rozumie, że jest zależny od zmiennego formatu: plusy i wady tak czy inaczej - to, czego naprawdę potrzebujemy, to bardziej natywne typy danych programu Excel, aby uniknąć tego problemu.
Charles Williams
2
Gdy chcę ustawić wartość równa komórek do innej komórki bez konwersji typu (na przykład, bez przekształcania numer zapisany jako tekst na liczby) Używam tego: Format$(Range.Value2, Range.NumberFormat).
ChrisB
55

Z wyjątkiem pierwszej odpowiedzi z Batszeby, z wyjątkiem informacji MSDN dotyczących:

.Value
.Value2
.Text

można przeanalizować te tabele, aby lepiej zrozumieć różnice między analizowanymi właściwościami.

wprowadź opis obrazu tutaj

Kazimierz Jawor
źródło
4
@Chris, używaj .Valuejako standardowej właściwości przez cały czas - dla tekstu i liczb. Użyj, .Value2gdy myślisz o dacie i niektórych liczbach. I używaj .Textzawsze, jeśli chcesz zachować formatowanie wszystkiego, co masz w komórce / zakresie. Więc przykład twojego pytania, jeśli jest poprawny!
Kazimierz Jawor
1
dlaczego data zmieniła się z 10:12 na 10:05? literówka?
Katrin
1
Myślę, że to tylko czas, który upłynął od wygenerowania wyników do zrobienia zrzutu ekranu
Kazimierz Jawor
25

target.Valueda ci Varianttyp

target.Value2poda również Varianttyp, ale a Datejest wymuszone naDouble

target.Textpróbuje wymusić na a Stringi zakończy się niepowodzeniem, jeśli Variantinstrument bazowy nie podlega przymusowi do aString typ

Najbezpieczniejszą rzeczą do zrobienia jest coś takiego

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

I sprawdź typ używanego wariantu, VBA.VarType(v)zanim spróbujesz użyć jawnego przymusu.

Batszeba
źródło
11

Odnośnie konwencji w C #. Powiedzmy, że czytasz komórkę zawierającą datę, np. 2014-10-22.

Podczas używania:

.Text, otrzymasz sformatowaną reprezentację daty, jak widać w skoroszycie na ekranie:
2014-10-22 . Typ tej właściwości jest zawsze, stringale nie zawsze, zwraca satysfakcjonujący wynik.

.Valuekompilator próbuje przekonwertować datę na DateTimeobiekt: {2014-10-22 00:00:00} Przydatne najprawdopodobniej tylko przy odczytywaniu dat.

.Value2, podaje rzeczywistą, podstawową wartość komórki. W przypadku dat jest to serial daty: 41934 . Ta właściwość może mieć inny typ w zależności od zawartości komórki. Jednak w przypadku seriali z datami typ todouble .

Możesz więc pobrać i zapisać wartość komórki w jednym lub drugim dynamic, ale pamiętaj, że wartość zawsze będzie miała jakiś rodzaj wrodzony, na który będziesz musiał działać.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
Silkfire
źródło
2

.Text to wyświetlana wartość sformatowanej komórki; .Value to wartość komórki, ewentualnie powiększona o wskaźniki daty lub waluty; .Value2 to surowa wartość bazowa pozbawiona wszelkich dodatkowych informacji.

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

Jeśli przetwarzasz wartość komórki, odczyt surowej wartości .Value2 jest nieznacznie szybszy niż .Value lub .Text. Jeśli lokalizujesz błędy, to .Text zwróci coś w rodzaju #N/Atekstu i może być porównane do łańcucha, podczas gdy .Value i .Value2 będą się dławić porównując swoją zwróconą wartość do łańcucha. Jeśli do danych zastosowano niestandardowe formatowanie komórek, podczas tworzenia raportu lepszym wyborem może być .Text.


źródło
0

Z ciekawości chciałem zobaczyć, jak się Valuespisuje przeciwko Value2. Po około 12 próbach podobnych procesów nie widziałem żadnych znaczących różnic w szybkości, więc zawsze zalecałbym używanie Value. Użyłem poniższego kodu, aby uruchomić kilka testów z różnymi zakresami.

Jeśli ktoś widzi coś sprzecznego z wydajnością, napisz.

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

wprowadź opis obrazu tutaj

PGSystemTester
źródło