Sự khác biệt giữa .text, .value và .value2 là gì?


180

Tôi không yêu cầu giúp đỡ với bất kỳ kịch bản, nhưng câu hỏi của tôi là để làm rõ. Gần đây tôi đã thực hiện rất nhiều kịch bản VB trong Excel, vì vậy tôi thực sự đề cập đến Excel trong câu hỏi này. Sự khác biệt giữa .text, .value và .value2 là gì? Giống như khi nào tôi nên sử dụng target.text, target.value và target.value2? Tôi không bao giờ sử dụng tùy chọn value2 nhưng vẫn muốn biết nó được sử dụng để làm gì.

Đôi khi nếu tôi sử dụng .text, nó sẽ báo lỗi và tôi cần sử dụng .value khi tôi chỉ kiểm tra hoặc thao tác văn bản trong một ô. Thỉnh thoảng khi tôi nghĩ rằng tôi nên sử dụng .value tôi gặp lỗi và tôi cần sử dụng .text. Thông thường, nó chấp nhận hoặc không có vấn đề, nhưng đôi khi nó tạo ra sự khác biệt. Tôi biết rằng phải có một số logic cho việc này, nhưng tôi dường như không thể tìm ra nó.

Tôi cũng phát hiện ra rằng nếu bạn chỉ để nó làm mục tiêu mà không chỉ định .text hoặc .value thì nó sẽ hoạt động, nhưng sau đó một cái gì đó mà ai đó cuối cùng sẽ gây ra lỗi script, vì vậy tốt nhất là luôn sử dụng một cái gì đó trên nó. . Tôi đoán những gì tôi đang hỏi là nếu ai đó có thể cho tôi một số hướng dẫn, quy tắc ngón tay cái, như làm thế nào để sử dụng đúng từng thứ và khi nào nó cần được sử dụng.

Cảm ơn các bạn đã giải thích. Tôi hiểu nó tốt hơn Cả hai đều là lời giải thích tốt. Dưới đây là một ví dụ nhỏ về một số mã của tôi không hoạt động. Tôi nghĩ rằng nó nên là target.text, nhưng nó sẽ báo lỗi nên khi tôi sử dụng target.value nó đã hoạt động.

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

Tôi vẫn hơi bối rối vì khi tôi nghĩ về giá trị hoặc value2, đặc biệt là sau câu trả lời của bạn mà bạn cung cấp, tôi nghĩ chúng chỉ nên được sử dụng cho các số. Tuy nhiên, trong ví dụ của tôi, tôi đang nói về văn bản nghiêm ngặt, đó là rất nhiều những gì kịch bản của tôi đề cập đến (văn bản trong các ô, nhiều hơn số).


LCase (Target.Value) sẽ thất bại nếu Target.Value không bị ép buộc thành một chuỗi vì LCase yêu cầu một chuỗi cho một đối số. Bạn nên kiểm tra VarType trước theo câu trả lời của tôi. Cũng lưu ý rằng bạn có thể sử dụng UCase thay thế và so sánh trực tiếp với "HLO": không có nhiều điểm trong hoạt động trên một nghĩa đen.
Bathsheba

Cảm ơn thông tin về VarType. Theo như LCase hoặc UCase cho điều này, nó thực sự không quan trọng với cái tôi đã sử dụng. Một số người gõ nó dưới dạng hlo và những người khác gõ nó dưới dạng HLO. Từ những gì tôi thấy, nó xuất hiện chữ thường được sử dụng thường xuyên hơn.
Chris

Câu trả lời:


238

.Textcung cấp cho bạn một chuỗi biểu thị những gì được hiển thị trên màn hình cho ô. Sử dụng .Text thường là một ý tưởng tồi vì bạn có thể nhận được ####

.Value2 cung cấp cho bạn giá trị cơ bản của ô (có thể trống, chuỗi, lỗi, số (gấp đôi) hoặc boolean)

.Value cung cấp cho bạn giống như .Value2 trừ khi ô được định dạng là tiền tệ hoặc ngày, nó cung cấp cho bạn một loại tiền tệ VBA (có thể cắt bớt các số thập phân) hoặc ngày VBA.

Sử dụng .Value hoặc .Text thường là một ý tưởng tồi vì bạn có thể không nhận được giá trị thực từ ô và chúng chậm hơn .Value2

Để thảo luận rộng hơn, hãy xem Văn bản của tôi so với Giá trị so với Giá trị2


6
Tôi có thể sẽ sử dụng Định dạng để kiểm soát cách số được chuyển đổi thành chuỗi: var = Format (Phạm vi ("a1"). Value2, "#")
Charles Williams

2
Tôi hy vọng đây không phải là một câu hỏi riêng biệt nhưng: Mặc định là gì? OP tuyên bố mơ hồ rằng việc bỏ đi văn bản / value / value2 là có vấn đề, nhưng chắc chắn nó mặc định với một trong số họ?
Martin F

3
Xin lỗi để đánh thức bài đăng này, nhưng tôi không thấy lợi thế của việc ép buộc Datevào một Double(sử dụng .Value2) khi những gì bạn cần là a Date. Không nên .Valueđược ưu tiên hơn .Value2khi bạn đang xem một Dategiá trị? Bài viết được liên kết cũng không làm rõ điều đó. Hiệu suất vì không chuyển đổi? Chắc chắn, nhưng sau đó nếu mã VBA của bạn hoạt động với a Date, thì bạn sẽ mất lợi thế đó khi tự mình thực hiện chuyển đổi, mặc nhiên hoặc rõ ràng ... (bối cảnh - thoải mái để cân nhắc)
Mathieu Guindon

2
@ Mat's Mug - vấn đề là Excel không có kiểu dữ liệu Ngày thực - ngày và giờ excel chỉ tăng gấp đôi phụ thuộc vào bất kỳ định dạng nào đã được người dùng áp dụng hoặc thay đổi để xuất hiện dưới dạng ngày, giờ hoặc tiền tệ hoặc chỉ là một con số. Vì vậy, Value đang ép buộc gấp đôi Excel thành một ngày VBA nhưng Value2 không thực hiện bất kỳ sự ép buộc nào ... Đối với các ngày, việc ép buộc gấp đôi thành một ngày có thể không gây ra bất kỳ thiệt hại nào miễn là mã đó hiểu rằng nó phụ thuộc vào định dạng có thể thay đổi: và nhược điểm - cách chúng ta thực sự cần là các kiểu dữ liệu Excel nguyên gốc hơn để tránh vấn đề này.
Charles Williams

2
Khi tôi muốn đặt một giá trị ô bằng với một ô khác mà không cần chuyển đổi loại (ví dụ: không chuyển đổi một số được lưu dưới dạng văn bản thành một số), tôi sử dụng cách này : Format$(Range.Value2, Range.NumberFormat).
ChrisB

55

Ngoại trừ mẫu câu trả lời đầu tiên Bathsheba, ngoại trừ thông tin MSDN cho:

.Value
.Value2
.text

bạn có thể phân tích các bảng này để hiểu rõ hơn về sự khác biệt giữa các thuộc tính được phân tích.

nhập mô tả hình ảnh ở đây


4
@Chris, sử dụng .Valuelàm tài sản tiêu chuẩn mọi lúc - cho văn bản và số. Sử dụng .Value2khi bạn nghĩ về ngày và một số số. Và .Textluôn luôn sử dụng nếu bạn cần giữ định dạng của bất cứ thứ gì bạn có trong ô / phạm vi. Vì vậy, ví dụ câu hỏi của bạn nếu chính xác!
Kazimierz Jawor

1
Tại sao ngày thay đổi từ 10:12 đến 10:05? lỗi đánh máy?
Katrin

1
Tôi nghĩ rằng đó chỉ là thời gian trôi qua giữa việc tạo ra kết quả và thời gian thực hiện chụp màn hình
Kazimierz Jawor

25

target.Valuesẽ cung cấp cho bạn một Variantloại

target.Value2cũng sẽ cung cấp cho bạn một Variantloại nhưng a Datebị ép buộcDouble

target.Textcố gắng ép buộc Stringvà sẽ thất bại nếu cơ sở Variantkhông thể cưỡng chế thành một Stringloại

Điều an toàn nhất để làm là một cái gì đó như

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

Và kiểm tra loại biến thể sử dụng VBA.VarType(v)trước khi bạn thử cưỡng chế rõ ràng.


11

Về các quy ước trong C #. Giả sử bạn đang đọc một ô có chứa một ngày, ví dụ 2014-10-22.

Khi đang sử dụng:

.Text, bạn sẽ nhận được đại diện được định dạng của ngày, như được thấy trong sổ làm việc trên màn hình:
2014-10-22 . Loại tài sản này luôn luôn stringnhưng có thể không luôn luôn trả về một kết quả thỏa đáng.

.Value, trình biên dịch cố gắng chuyển đổi ngày thành một DateTimeđối tượng: {2014-10-22 00:00:00} Có lẽ chỉ hữu ích khi đọc ngày.

.Value2, cung cấp cho bạn giá trị thực, tiềm ẩn của ô. Trong trường hợp cho ngày, đó là một chuỗi ngày: 41934 . Thuộc tính này có thể có một loại khác nhau tùy thuộc vào nội dung của ô. Đối với serial ngày mặc dù, loại là double.

Vì vậy, bạn có thể lấy và lưu trữ các giá trị của một ô trong một trong hai dynamic, varhoặc objectnhưng lưu ý rằng giá trị sẽ luôn luôn có một số loại kiểu bẩm sinh mà bạn sẽ phải hành động theo.

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

2

.Text là giá trị hiển thị của ô được định dạng; .Value là giá trị của ô có thể tăng theo chỉ số ngày hoặc tiền tệ; .Value2 là giá trị cơ bản thô bị tước bỏ mọi thông tin không liên quan.

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

Nếu bạn đang xử lý giá trị của ô thì việc đọc .Value2 thô nhanh hơn một chút so với .Value hoặc .Text. Nếu bạn đang định vị lỗi thì .Text sẽ trả về một cái gì đó như #N/Avăn bản và có thể được so sánh với một chuỗi trong khi .Value và .Value2 sẽ bóp nghẹt so sánh giá trị trả về của chúng với một chuỗi. Nếu bạn có một số định dạng ô tùy chỉnh được áp dụng cho dữ liệu của mình thì .Text có thể là lựa chọn tốt hơn khi tạo báo cáo.


0

Vì tò mò, tôi muốn xem cách Valuebiểu diễn chống lại Value2. Sau khoảng 12 thử nghiệm của các quá trình tương tự, tôi không thể thấy bất kỳ sự khác biệt đáng kể nào về tốc độ nên tôi luôn khuyên bạn nên sử dụng Value. Tôi đã sử dụng mã dưới đây để chạy một số thử nghiệm với các phạm vi khác nhau.

Nếu bất cứ ai nhìn thấy bất cứ điều gì trái ngược về hiệu suất, xin vui lòng gửi.

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

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.