Was ist der Unterschied zwischen .text, .value und .value2?

179

Ich bitte nicht um Hilfe bei einem Skript, aber meine Frage dient der Klarstellung. In letzter Zeit habe ich viele VB-Skripte in Excel erstellt, daher beziehe ich mich in dieser Frage wirklich auf Excel. Was ist der Unterschied zwischen .text, .value und .value2? Zum Beispiel, wann sollte ich target.text, target.value und target.value2 verwenden? Ich habe die Option value2 nie verwendet, möchte aber trotzdem wissen, wofür sie verwendet wird.

Wenn ich .text verwende, wird manchmal ein Fehler angezeigt, und ich muss .value verwenden, wenn ich nur den Text in einer Zelle überprüfe oder bearbeite. Wenn ich dann denke, ich sollte .value verwenden, erhalte ich manchmal eine Fehlermeldung und muss .text verwenden. Normalerweise akzeptiert es entweder oder ohne Probleme, aber manchmal macht es einen Unterschied. Ich weiß, dass dies eine Logik haben muss, aber ich kann es nicht herausfinden.

Ich habe auch herausgefunden, dass, wenn Sie es einfach als Ziel belassen, ohne .text oder .value anzugeben, es zunächst funktioniert, aber dann etwas, das jemand tut, irgendwann zu einem Fehler im Skript führt. Daher ist es immer am besten, etwas .something darauf zu verwenden . Ich denke, ich frage, ob mir jemand eine Richtlinie geben kann, eine Faustregel, wie man jeden richtig benutzt und wann er benutzt werden muss.

Danke für die Erklärung Jungs. Ich verstehe es irgendwie besser. Sie sind beide gute Erklärungen. Unten finden Sie ein kleines Beispiel für einen Teil meines Codes, der funktioniert. Ich dachte, es sollte target.text sein, aber es würde ein Fehler sein, also funktionierte es, wenn ich target.value verwendete.

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

Ich bin immer noch etwas verwirrt, denn wenn ich an Wert oder Wert2 denke, insbesondere nach Ihren Antworten, die Sie gegeben haben, denke ich, dass sie nur für Zahlen verwendet werden sollten. In meinem Beispiel spreche ich jedoch ausschließlich von Text, worauf sich mein Skript häufig bezieht (Text in den Zellen, mehr als Zahlen).

Chris
quelle
LCase (Target.Value) schlägt fehl, wenn Target.Value nicht auf eine Zeichenfolge erzwungen werden kann, da LCase eine Zeichenfolge für ein Argument benötigt. Sie sollten zuerst den VarType gemäß meiner Antwort überprüfen. Beachten Sie auch, dass Sie stattdessen UCase verwenden und direkt mit "HLO" vergleichen können: Es macht nicht viel Sinn, mit einem Literal zu arbeiten.
Bathsheba
Vielen Dank für die Informationen zu VarType. Was die LCase oder UCase angeht, wäre es wirklich egal, welche ich verwendet habe. Einige Leute geben es als hlo ein und andere als HLO. Nach allem, was ich sah, wurde der Kleinbuchstabe häufiger verwendet.
Chris

Antworten:

236

.Textgibt Ihnen eine Zeichenfolge, die darstellt, was auf dem Bildschirm für die Zelle angezeigt wird. Die Verwendung von .Text ist normalerweise eine schlechte Idee, da Sie #### erhalten könnten

.Value2 gibt Ihnen den zugrunde liegenden Wert der Zelle an (kann leer, Zeichenfolge, Fehler, Zahl (doppelt) oder boolesch sein)

.Value gibt Ihnen das gleiche wie .Value2, außer wenn die Zelle als Währung oder Datum formatiert wurde, erhalten Sie eine VBA-Währung (die möglicherweise Dezimalstellen abschneidet) oder ein VBA-Datum.

Die Verwendung von .Value oder .Text ist normalerweise eine schlechte Idee, da Sie möglicherweise nicht den tatsächlichen Wert aus der Zelle erhalten und diese langsamer als .Value2 sind

Für eine ausführlichere Diskussion siehe meinen Text vs Value vs Value2

Charles Williams
quelle
6
Ich würde wahrscheinlich Format verwenden, um zu steuern, wie die Zahl in eine Zeichenfolge konvertiert wird: var = Format (Bereich ("a1"). Wert2, "#")
Charles Williams
2
Ich hoffe, dies ist keine separate Frage, aber: Was ist die Standardeinstellung? Das OP behauptet vage, dass das Auslassen von Text / Wert / Wert2 problematisch ist, aber sicherlich standardmäßig einer von ihnen?
Martin F
3
Es tut mir leid, diesen oooooold Beitrag aufzuwecken, aber ich sehe nicht den Vorteil, a Datein a Double(using .Value2) zu zwingen, wenn Sie a benötigen Date. Sollte nicht .Valuevorgezogen werden, .Value2wenn Sie einen DateWert betrachten? Der verlinkte Artikel macht das auch nicht sehr deutlich. Leistung weil keine Konvertierung? Sicher, aber wenn Ihr VBA-Code mit a arbeitet Date, verlieren Sie diesen Vorteil, indem Sie die Konvertierung implizit oder explizit selbst durchführen ... (Kontext - zögern Sie nicht, dies zu gewichten)
Mathieu Guindon
2
@ Mat's Mug - das Problem ist, dass Excel keinen echten Datums-Datentyp hat - Excel-Daten und -Zeiten sind nur Doppelwerte, die davon abhängen, welches Format vom Benutzer angewendet oder geändert wurde, um als Datum, Uhrzeit oder Währung oder nur als angezeigt zu werden Nummer. Value erzwingt also ein Excel-Double zu einem VBA-Datum, aber Value2 erzwingt nichts ... Bei Datumsangaben, bei denen das Double zu einem Datum gezwungen wird, wird wahrscheinlich kein Schaden angerichtet, solange der Code versteht, dass es von einem veränderbaren Format abhängt: Profis und Nachteile - was wir wirklich brauchen, sind mehr native Excel-Datentypen, um dieses Problem zu vermeiden.
Charles Williams
2
Wenn ich einen Zellenwert ohne Typkonvertierung gleich einer anderen Zelle setzen möchte (z. B. ohne eine als Text gespeicherte Zahl in eine Zahl umzuwandeln), verwende ich Folgendes : Format$(Range.Value2, Range.NumberFormat).
ChrisB
55

Außer der ersten Antwort von Bathsheba, außer MSDN-Informationen für:

.Wert
.Wert2
.Text

Sie können diese Tabellen analysieren, um die Unterschiede zwischen den analysierten Eigenschaften besser zu verstehen.

Geben Sie hier die Bildbeschreibung ein

Kazimierz Jawor
quelle
4
@Chris, immer .Valueals Standardeigenschaft verwenden - für Text und Zahlen. Verwenden .Value2Sie diese Option, wenn Sie an Datum und einige Zahlen denken. Und .Textimmer verwenden, wenn Sie die Formatierung von allem, was Sie in Zelle / Bereich haben, beibehalten müssen. Also, dein Fragenbeispiel ist richtig!
Kazimierz Jawor
1
Warum hat sich das Datum von 10:12 auf 10:05 geändert? Tippfehler?
Katrin
1
Ich denke, es ist nur die Zeit zwischen dem Generieren der Ergebnisse und dem Erstellen des Screenshots vergangen
Kazimierz Jawor
25

target.Valuewird Ihnen einen VariantTyp geben

target.Value2gibt Ihnen auch einen VariantTyp, aber a Datewird zu a gezwungenDouble

target.TextVersuche, zu einem zu zwingen, schlagen Stringfehl, wenn der Basiswert Variantnicht zu einem StringTyp erzwungen werden kann

Am sichersten ist so etwas

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

Überprüfen Sie den Typ der Variante mit, VBA.VarType(v)bevor Sie einen expliziten Zwang versuchen.

Bathseba
quelle
11

Zu Konventionen in C #. Angenommen, Sie lesen eine Zelle, die ein Datum enthält, z. B. 22.10.2014.

Beim Benutzen:

.Texterhalten Sie die formatierte Darstellung des Datums, wie in der Arbeitsmappe auf dem Bildschirm angezeigt:
2014-10-22 . Der Typ dieser Eigenschaft ist immer string, liefert jedoch möglicherweise nicht immer ein zufriedenstellendes Ergebnis.

.ValueDer Compiler versucht, das Datum in ein DateTimeObjekt zu konvertieren : {2014-10-22 00:00:00} Höchstwahrscheinlich nur beim Lesen von Datumsangaben nützlich.

.Value2gibt Ihnen den tatsächlichen, zugrunde liegenden Wert der Zelle. Bei Datumsangaben handelt es sich um eine Datumsserie : 41934 . Diese Eigenschaft kann je nach Inhalt der Zelle einen anderen Typ haben. Für Datumsserien ist der Typ jedoch double.

So ermitteln Sie den Wert einer Zelle in entweder abrufen und speichern können dynamic, varoder objectaber zur Kenntnis , dass der Wert wird immer irgendeine Art von angeborenem Typ hat , dass Sie sich danach zu handeln.

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
Seidenfeuer
quelle
2

.Text ist der angezeigte Wert der formatierten Zelle. Der Wert ist der Wert der Zelle, der möglicherweise um Datums- oder Währungsindikatoren erweitert wird. .Wert2 ist der zugrunde liegende Rohwert, der keine fremden Informationen enthält.

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

Wenn Sie den Wert der Zelle verarbeiten, ist das Lesen des rohen .Value2 geringfügig schneller als .Value oder .Text. Wenn Sie Fehler suchen, gibt .Text so etwas wie #N/AText zurück und kann mit einer Zeichenfolge verglichen werden, während .Value und .Value2 den zurückgegebenen Wert mit einer Zeichenfolge vergleichen. Wenn Sie eine benutzerdefinierte Zellenformatierung auf Ihre Daten angewendet haben, ist .Text möglicherweise die bessere Wahl, wenn Sie einen Bericht erstellen.


quelle
0

Aus Neugier wollte ich sehen, wie man dagegen Valuevorgeht Value2. Nach ungefähr 12 Versuchen mit ähnlichen Prozessen konnte ich keine signifikanten Geschwindigkeitsunterschiede feststellen, daher würde ich immer empfehlen, diese zu verwenden Value. Ich habe den folgenden Code verwendet, um einige Tests mit verschiedenen Bereichen durchzuführen.

Wenn jemand etwas Gegenteiliges in Bezug auf die Leistung sieht, bitte posten.

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

Geben Sie hier die Bildbeschreibung ein

PGSystemTester
quelle