Code sự kiện Change chạy 03 lần là bị sai

Liên hệ QC

letienmai

Thành viên hoạt động
Tham gia
16/7/14
Bài viết
146
Được thích
45
Chào anh/ chị
Em đang viết một code để nhập nhanh ngày tháng. Tuy nhiên khi chạy 03 ô liên tục thì sẽ hiện kết quả sai, ví dụ
- nhập tại ô A1 giá trị 11 enter hiện 01/01/2019
- nhập tại ô A2 giá trị 22 enter hiện 02/02/2019
- nhập tại ô A3 giá trị 33 enter hiện 03/03/2019
- nhập tại ô A4 giá trị 44 enter hiện <> 04/04/2019 --> Sai giá trị mong muốn
Mình mò mãi mà không hiểu lý do tại sao, mong ac có kinh nghiệm nhờ chia sẻ.
Nó hơi khó hiểu nhờ ac xem test chi tiết trong file đính kèm.
Cám ơn mọi sự đóng góp và giúp đỡ.
 

File đính kèm

Chào anh/ chị
Em đang viết một code để nhập nhanh ngày tháng. Tuy nhiên khi chạy 03 ô liên tục thì sẽ hiện kết quả sai, ví dụ
- nhập tại ô A1 giá trị 11 enter hiện 01/01/2019
- nhập tại ô A2 giá trị 22 enter hiện 02/02/2019
- nhập tại ô A3 giá trị 33 enter hiện 03/03/2019
- nhập tại ô A4 giá trị 44 enter hiện <> 04/04/2019 --> Sai giá trị mong muốn
Mình mò mãi mà không hiểu lý do tại sao, mong ac có kinh nghiệm nhờ chia sẻ.
Nó hơi khó hiểu nhờ ac xem test chi tiết trong file đính kèm.
Cám ơn mọi sự đóng góp và giúp đỡ.
Có khó gì đâu, do vùng nhập liệu của bạn đang dạng ngày tháng nên nó sai là đúng rồi, cũng code đó bạn nhập với vùng dữ liệu kiểu Text sẽ thấy ngay kết quả.
 
Upvote 0
Có khó gì đâu, do vùng nhập liệu của bạn đang dạng ngày tháng nên nó sai là đúng rồi, cũng code đó bạn nhập với vùng dữ liệu kiểu Text sẽ thấy ngay kết quả.
Quả thật là như vậy luôn anh.
Mà có vấn đề là tại sao nó lại sai khi nhập liên tiếp lần thứ 4 nếu mình nhập 3 lần liên tiếp thì nó vẫn đúng.
Anh có thể giải thích thêm giùm được không.
Cám ơn anh.
 
Upvote 0
Quả thật là như vậy luôn anh.
Mà có vấn đề là tại sao nó lại sai khi nhập liên tiếp lần thứ 4 nếu mình nhập 3 lần liên tiếp thì nó vẫn đúng.
Anh có thể giải thích thêm giùm được không.
Cám ơn anh.
Cái này tôi đoán chắc có lẽ do chức năng tự động chuyển đổi của Excel, bạn thử chọn ô và xem nó định dạng kiểu gì, sau đó nhập liệu và xem lại nó kiểu gì nhé.
 
Upvote 0
Cái này tôi đoán chắc có lẽ do chức năng tự động chuyển đổi của Excel, bạn thử chọn ô và xem nó định dạng kiểu gì, sau đó nhập liệu và xem lại nó kiểu gì nhé.
Với lại sao em test nhập 4 số.
Ví dụ: 2510 -->Mong muốn: 25/10/2019 thì nó lại hiện 10/25/2019, mặc dù em đã thêm dòng code Target.NumberFormar = "dd/mm/yyyy"
 
Upvote 0
Dùng hàm Dateserial() chứ không dùng hàm DateValue().

Dùng DateValue() thì lại cái vòng luẩn quẩn chẳng được tác dụng gì cả. Vẫn phụ thuộc vào format của hệ điều hành.

Dateserial() trả về giá trị chuẩn của ngày cần, rồi muốn format giời bể gì cũng đúng, cũng được.!
 
Upvote 0
Quả thật là như vậy luôn anh.
Lúc đó dữ liệu là text. Và một ngày đẹp trời sẽ có bài: "Tại sao công thức ... trả về kết quả sai". Sai vì dữ liệu là text giả bộ ngày tháng chứ không là ngày tháng theo cách hiểu của Excel. Sống chỉ biết hôm nay, ngày mai nghĩ tiếp?
 
Upvote 0
Với lại sao em test nhập 4 số.
Ví dụ: 2510 -->Mong muốn: 25/10/2019 thì nó lại hiện 10/25/2019, mặc dù em đã thêm dòng code Target.NumberFormar = "dd/mm/yyyy"
Bạn cắt có 1 ký tự mà đòi kết quả được 2 thì tui thua thật. Cách làm nhanh này không khuyến cáo, không lẽ lúc này cũng năm 2019. Giả sử hôm nay nhập, ngày mai (đã sang năm mới) cần sửa đổi thì lại vào code sửa nửa. Chán!
Bài đã được tự động gộp:

Lúc đó dữ liệu là text. Và một ngày đẹp trời sẽ có bài: "Tại sao công thức ... trả về kết quả sai". Sai vì dữ liệu là text giả bộ ngày tháng chứ không là ngày tháng theo cách hiểu của Excel. Sống chỉ biết hôm nay, ngày mai nghĩ tiếp?
Tôi thấy trên diễn đàn này có nhiều trường hợp giống thế này lắm.
 
Upvote 0
Dùng hàm Dateserial() chứ không dùng hàm DateValue().

Dùng DateValue() thì lại cái vòng luẩn quẩn chẳng được tác dụng gì cả. Vẫn phụ thuộc vào format của hệ điều hành.

Dateserial() trả về giá trị chuẩn của ngày cần, rồi muốn format giời bể gì cũng đúng, cũng được.!
Dùng DateSerial thì chuẩn rồi. Nhưng nếu chỉ sửa thành DateSerial thì cũng chả giải quyết được gì.
Bài đã được tự động gộp:

Bạn cắt có 1 ký tự mà đòi kết quả được 2 thì tui thua thật. Cách làm nhanh này không khuyến cáo, không lẽ lúc này cũng năm 2019. Giả sử hôm nay nhập, ngày mai (đã sang năm mới) cần sửa đổi thì lại vào code sửa nửa. Chán!
Người ta không nhập năm 2019 cứng nhắc. Người ta muốn nhập liệu với năm hiện hành và dùng Year(Date).
 
Upvote 0
Bạn cắt có 1 ký tự mà đòi kết quả được 2 thì tui thua thật. Cách làm nhanh này không khuyến cáo, không lẽ lúc này cũng năm 2019. Giả sử hôm nay nhập, ngày mai (đã sang năm mới) cần sửa đổi thì lại vào code sửa nửa. Chán!
Hi. Dạ cám ơn anh đã góp ý, tuy nhiên với với trường hợp Len(Target) = 4 thì em có cắt trái 2 ký tự và cắt phải 1 ký tự, còn cái năm thì em dùng Year(Date) để lấy năm hiện hành chứ không lấy chết năm 2019 ạ.
Bài đã được tự động gộp:

Lúc đó dữ liệu là text. Và một ngày đẹp trời sẽ có bài: "Tại sao công thức ... trả về kết quả sai". Sai vì dữ liệu là text giả bộ ngày tháng chứ không là ngày tháng theo cách hiểu của Excel. Sống chỉ biết hôm nay, ngày mai nghĩ tiếp?
Dạ em cám ơn anh góp ý, tuy nhiên định dạng Text em chỉ áp dụng cho mỗi cột ngày tháng thôi ạ để không ảnh hưởng đến phần công thức.
Bài đã được tự động gộp:

Dùng hàm Dateserial() chứ không dùng hàm DateValue().

Dùng DateValue() thì lại cái vòng luẩn quẩn chẳng được tác dụng gì cả. Vẫn phụ thuộc vào format của hệ điều hành.

Dateserial() trả về giá trị chuẩn của ngày cần, rồi muốn format giời bể gì cũng đúng, cũng được.!
Dạ em cám ơn anh, để em dùng áp dụng thử Dataserial.
 
Upvote 0
Dùng hàm Dateserial() chứ không dùng hàm DateValue().

Dùng DateValue() thì lại cái vòng luẩn quẩn chẳng được tác dụng gì cả. Vẫn phụ thuộc vào format của hệ điều hành.

Dateserial() trả về giá trị chuẩn của ngày cần, rồi muốn format giời bể gì cũng đúng, cũng được.!
Dạ anh cho em hỏi em dùng DateSerial nhưng sao em Enter thì nó hiển thị tháng/ngày/năm cụ thể nhập 2510 thì nó hiện là 10252019. cám ơn anh
 

File đính kèm

  • Capture.PNG
    Capture.PNG
    129.5 KB · Đọc: 14
Upvote 0
1/ Đọc kỹ hướng dẫn trước khi dùng
2/ Format gì tùm lum vậy?
Dạ rõ ràng em thêm Target.Numberformat = "dd/mm/yyyy" nhưng khi gán xuống cells thì lại thành mm/dd/yyyy nên em không hiểu.
Bài đã được tự động gộp:

Dạ rõ ràng em thêm Target.Numberformat = "dd/mm/yyyy" nhưng khi gán xuống cells thì lại thành mm/dd/yyyy nên em không hiểu.
Chết chết....em gõ nhầm "mm/dd/yyyy".
Em cám ơn các anh đã giúp đỡ.
 
Upvote 0
Dạ em cám ơn anh góp ý, tuy nhiên định dạng Text em chỉ áp dụng cho mỗi cột ngày tháng thôi ạ để không ảnh hưởng đến phần công thức.
Ý tôi nói là công thức nào đó tham chiếu tới cột mà bạn định dạng là text kia. Lúc đó công thức sẽ lỗi/sai.
 
Upvote 0
Giải thích các thắc mắc của chủ topic:
"Khi chạy 03 ô liên tục thì sẽ hiện kết quả sai"
Code không liên quan gì đến số lần cả. Nhập ô A4 là sai là do ô A4 đang được định dạng ngày tháng, giá trị .Value là ngày tháng nên độ dài (kết quả của hàm Len) là 10 và code không làm gì cả. Nhập 44 hiển thị 13/02/1900 là do 13/02/1900 là giá trị 44 định dạng dưới dạng ngày tháng.
1572054262580.png
Ngoài ra, sau khi code chuyển giá trị nhập vào thành ngày tháng thì Excel sẽ tự định dạng ô dạng ngày tháng nên nếu bạn nhập lại một lần nữa cũng sẽ bị tương tự như khi nhập ô vào ô A4.
Hướng giải quyết:
Sử dụng .Value2 thay cho .Value và định dạng General hoặc ngày tháng (không định dạng Text vì nó sẽ làm thay đổi kiểu dữ liệu của bạn.
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim vCllVal As Variant
    If Target.Cells.Count > 1 Then Exit Sub
    vCllVal = Target.Value2
    If Not IsNumeric(vCllVal) Then Exit Sub
    If Len(vCllVal) = 2 Or Len(vCllVal) = 4 Then
        Application.EnableEvents = False
        Target.Value = DateSerial(Year(Date), Right(vCllVal, Len(vCllVal) / 2), Left(vCllVal, Len(vCllVal) / 2))
        Application.EnableEvents = True
    End If
End Sub
 
Upvote 0
Giải thích các thắc mắc của chủ topic:
"Khi chạy 03 ô liên tục thì sẽ hiện kết quả sai"
Code không liên quan gì đến số lần cả. Nhập ô A4 là sai là do ô A4 đang được định dạng ngày tháng, giá trị .Value là ngày tháng nên độ dài (kết quả của hàm Len) là 10 và code không làm gì cả. Nhập 44 hiển thị 13/02/1900 là do 13/02/1900 là giá trị 44 định dạng dưới dạng ngày tháng.
View attachment 227188
Ngoài ra, sau khi code chuyển giá trị nhập vào thành ngày tháng thì Excel sẽ tự định dạng ô dạng ngày tháng nên nếu bạn nhập lại một lần nữa cũng sẽ bị tương tự như khi nhập ô vào ô A4.
Hướng giải quyết:
Sử dụng .Value2 thay cho .Value và định dạng General hoặc ngày tháng (không định dạng Text vì nó sẽ làm thay đổi kiểu dữ liệu của bạn.
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim vCllVal As Variant
    If Target.Cells.Count > 1 Then Exit Sub
    vCllVal = Target.Value2
    If Not IsNumeric(vCllVal) Then Exit Sub
    If Len(vCllVal) = 2 Or Len(vCllVal) = 4 Then
        Application.EnableEvents = False
        Target.Value = DateSerial(Year(Date), Right(vCllVal, Len(vCllVal) / 2), Left(vCllVal, Len(vCllVal) / 2))
        Application.EnableEvents = True
    End If
End Sub
Dạ chân thành cám ơn anh nhiều ạ. Nay em biết thêm Value2.
 
Upvote 0
Thực ra bài không hề khó. Khi tôi góp ý về TEXT thì tôi nghĩ là sẽ có câu đại loại như: "Ừ nhỉ. Thế làm thế nào để chuẩn, để là ngày tháng?". Nhưng nhận được câu trả lời thì tôi hiểu là người hỏi hài lòng rồi. Người ta không cần tò mò gì thêm nên tôi cũng thôi luôn.
Sử dụng .Value2 thay cho .Value và định dạng General hoặc ngày tháng (không định dạng Text vì nó sẽ làm thay đổi kiểu dữ liệu của bạn.
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim vCllVal As Variant
    If Target.Cells.Count > 1 Then Exit Sub
    vCllVal = Target.Value2
    If Not IsNumeric(vCllVal) Then Exit Sub
    If Len(vCllVal) = 2 Or Len(vCllVal) = 4 Then
        Application.EnableEvents = False
        Target.Value = DateSerial(Year(Date), Right(vCllVal, Len(vCllVal) / 2), Left(vCllVal, Len(vCllVal) / 2))
        Application.EnableEvents = True
    End If
End Sub
Thế cần nhập vd. ngày 3 tháng 11 thì gõ thế nào? Gõ '0311 thì tốn 2 cú gõ '0.

Tôi làm cho VALUE.
Lưu ý:
- nếu ngày chỉ có 1 ký tự thì tháng ta gõ 1 hoặc 2 ký tự đều được. Vd. 51 -> 5/1, 501 -> 5/1, 511 -> 5/11
- nếu ngày có 2 ký tự thì tháng bắt buộc phải gõ 2 ký tự, thậm chí tháng 1-9. Vì nếu không sẽ có trường hợp không xác định. Vd. 311 là 31 tháng 1 hay 3 tháng 11?

Tóm lại nếu gõ 3 hoặc 4 ký tự thì 2 ký tự cuối luôn là tháng. Nếu ngày có 2 ký tự thì phải gõ 4 ký tự - vd. 2501, 2512.
Code chưa phục vụ lỗi. Vd. gõ 41,3
Định dạng General trên sheet.

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim text As String
    With Target
        If .Cells.Count > 1 Then Exit Sub
        text = CLng(.Value)
        Application.EnableEvents = False
        If Len(text) = 2 Then
            Target = DateSerial(Year(Date), Right(text, 1), Left(text, 1))
        ElseIf Len(text) <= 4 Then
            Target = DateSerial(Year(Date), Right(text, 2), Left(text, Len(text) - 2))
        End If
        Application.EnableEvents = True
    End With
End Sub
 
Upvote 0
Thực ra bài không hề khó. Khi tôi góp ý về TEXT thì tôi nghĩ là sẽ có câu đại loại như: "Ừ nhỉ. Thế làm thế nào để chuẩn, để là ngày tháng?". Nhưng nhận được câu trả lời thì tôi hiểu là người hỏi hài lòng rồi. Người ta không cần tò mò gì thêm nên tôi cũng thôi luôn.

Thế cần nhập vd. ngày 3 tháng 11 thì gõ thế nào? Gõ '0311 thì tốn 2 cú gõ '0.

Tôi làm cho VALUE.
Lưu ý:
- nếu ngày chỉ có 1 ký tự thì tháng ta gõ 1 hoặc 2 ký tự đều được. Vd. 51 -> 5/1, 501 -> 5/1, 511 -> 5/11
- nếu ngày có 2 ký tự thì tháng bắt buộc phải gõ 2 ký tự, thậm chí tháng 1-9. Vì nếu không sẽ có trường hợp không xác định. Vd. 311 là 31 tháng 1 hay 3 tháng 11?

Tóm lại nếu gõ 3 hoặc 4 ký tự thì 2 ký tự cuối luôn là tháng. Nếu ngày có 2 ký tự thì phải gõ 4 ký tự - vd. 2501, 2512.
Code chưa phục vụ lỗi. Vd. gõ 41,3
Định dạng General trên sheet.

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim text As String
    With Target
        If .Cells.Count > 1 Then Exit Sub
        text = CLng(.Value)
        Application.EnableEvents = False
        If Len(text) = 2 Then
            Target = DateSerial(Year(Date), Right(text, 1), Left(text, 1))
        ElseIf Len(text) <= 4 Then
            Target = DateSerial(Year(Date), Right(text, 2), Left(text, Len(text) - 2))
        End If
        Application.EnableEvents = True
    End With
End Sub
Em có vận dụng bài của anh như sau
1/ code chỉ cho kết quả ở cột F từ hàng thứ 10 trở xuống
2/ Tháng lấy ô A1 và năm lấy ô A2
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim text As String
    If CheckBox1 = False Then
        MsgBox "chua bat checkbox"
        Exit Sub
    End If
    With Target


        If Target.Count = 1 And Target.Column = 6 And Target.Row >= 10 Then
            If .Cells.Count > 1 Or Target < 1 Or Target > 31 Then
                MsgBox "Nhap ngày kg dung!"
                Target.NumberFormat = "General"
                Exit Sub
            End If
            text = CLng(.Value)
            Application.EnableEvents = False
            If Len(text) = 2 Then
                Target = DateSerial(Range("$A$2").Value, Range("$A$1").Value, Left(text, 2))
                '                Target = DateSerial(Range("$A$2").Value, Range("$A$1").Value, text)
                '        ElseIf Len(text) <= 4 Then
                '            Target = DateSerial(Year(Date), Range("A1"), Left(text, Len(text) - 2))
            End If
        End If

        Application.EnableEvents = True
    End With
    'End If
End Sub
Khi em gõ ở ô target từ 01 ->09 thì code không cho kết quả là ngày, tháng, năm
Anh vui lòng sửa giúp em, em cảm ơn
 

File đính kèm

Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom