Hỏi về phương thức Set Focus

Liên hệ QC

hoangdanh282vn

Nguyễn Cảnh Hoàng Danh
Thành viên danh dự
Tham gia
21/12/07
Bài viết
1,900
Được thích
5,277
Nghề nghiệp
Kinh doanh các mặt hàng văn phòng phẩm
Mình có 1 UserForm nhập liệu. Trên đó có 2 textbox
Textbox1 : Nhập ngày tháng
Textbox2 : Nhập số chứng từ

Mình muốn là khi nhập liệu ngày tháng vào textbox1 xong, bấm enter hay tab thì sẽ kiểm tra xem dữ liệu ngày trên textbox1 có hợp lệ không. Nếu đúng thì sẽ nhảy đến textbox2, nếu sai thì sẽ hiện thông báo và con trỏ vẫn ở tại textbox1 để nhập lại dữ liệu.

Mình đã thử vài sự kiện cho textbox1 như Exit, BeforeApdate, AfterApdate.. kết hợp với Set focus nhưng vẫn không được. Dù dữ liệu đúng hay sai thì khi tab xong, con trỏ vẫn luôn nhảy đến textbox2.

Mong được sự giúp đỡ của các bạn.
Cảm ơn!
 

File đính kèm

  • Hoi ve Set focus.xls
    30.5 KB · Đọc: 80
Hoang Danh thân, trước hết bạn phải dùng 1 trong 2 cách là:
-Phải set lại key code: KeyCode=0 để xóa bỏ lệnh chuyển trước đó vì bạn enter hay tab là dịch chuyển đối tượng.
-Bạn dùng lệnh cancel event. (Không nhớ chính xác cú pháp nhưng chắc ăn hơn vì trước mình cũng loay hoay mãi mới tìm ra)
Sau đó mới set focus.
 
Lần chỉnh sửa cuối:
Upvote 0
Hoang Danh thân, trước hết bạn phải dùng 1 trong 2 cách là:
-Phải set lại key code: KeyCode=0 hay KeyAscii=0 để xóa bỏ lệnh chuyển trước đó vì bạn enter hay tab là dịch chuyển đối tượng.
-Bạn dùng lệnh cancel event. (Không nhớ chính xác cú pháp nhưng chắc ăn hơn vì mình cũng loay hoay mãi mới tìm ra)
Sau đó mới set focus.

Bác có thể gửi file minh họa lên dùm được không ạ, cách gì cũng được, miễn chạy ok là được.
Cảm ơn Bác trước ạ!
 
Upvote 0
Bạn thử đặt vào keydown như ví dụ xem sao
 

File đính kèm

  • sealand03.xls
    29.5 KB · Đọc: 125
Upvote 0
Mình có 1 UserForm nhập liệu. Trên đó có 2 textbox
Textbox1 : Nhập ngày tháng
Textbox2 : Nhập số chứng từ

Mình muốn là khi nhập liệu ngày tháng vào textbox1 xong, bấm enter hay tab thì sẽ kiểm tra xem dữ liệu ngày trên textbox1 có hợp lệ không. Nếu đúng thì sẽ nhảy đến textbox2, nếu sai thì sẽ hiện thông báo và con trỏ vẫn ở tại textbox1 để nhập lại dữ liệu.

Mình đã thử vài sự kiện cho textbox1 như Exit, BeforeApdate, AfterApdate.. kết hợp với Set focus nhưng vẫn không được. Dù dữ liệu đúng hay sai thì khi tab xong, con trỏ vẫn luôn nhảy đến textbox2.

Mong được sự giúp đỡ của các bạn.
Cảm ơn!
Đây là code của bạn
Mã:
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If IsDate(TextBox1) Then
TextBox1 = Format(TextBox1, "dd/mm/yyyy")
Else
MsgBox "Ngay thang khong dung!"
[COLOR=Red]TextBox1.SetFocus[/COLOR]
End If
End Sub
Thay dòng TextBox1.SetFocus bằng lệnh Cacel = True
 
Upvote 0
rollover79 đã giải xong phần SetFocus. Nhưng còn đoạn mã này hoangdanh282vn xem lại, tôi thấy không ổn:
Mã:
If IsDate(TextBox1) Then
  TextBox1 = Format(TextBox1, "dd/mm/yyyy")
  .......
Else

nhập 13/1/08 hay 1/13/08 nó đều hiểu là ngày. Điều này rất nguy hiểm khi vô tình nhập sai. Ví dụ nhập ngày 1 tháng 2 năm 2008 nhưng nhập sai 1/22/08 thì nó chuyển thành 22/01/2008 và cho qua luôn.
 
Upvote 0
rollover79 đã giải xong phần SetFocus. Nhưng còn đoạn mã này hoangdanh282vn xem lại, tôi thấy không ổn:
Mã:
If IsDate(TextBox1) Then
  TextBox1 = Format(TextBox1, "dd/mm/yyyy")
  .......
Else

nhập 13/1/08 hay 1/13/08 nó đều hiểu là ngày. Điều này rất nguy hiểm khi vô tình nhập sai. Ví dụ nhập ngày 1 tháng 2 năm 2008 nhưng nhập sai 1/22/08 thì nó chuyển thành 22/01/2008 và cho qua luôn.
Vấn đề này quả thực cũng hơi phức tạp đấy.
Trước đây tôi có viết CT trên VB6/Access Database dù có thiết lập format cho ngày trên Win/Access/Form nhưng khi show trên textbox vẫn bị tình trạng như PhamduyLong nói.
Các bạn nghiên cứu và trao đổi xem nguyên nhân là do đâu?
 
Upvote 0
rollover79 đã giải xong phần SetFocus. Nhưng còn đoạn mã này hoangdanh282vn xem lại, tôi thấy không ổn:
Mã:
If IsDate(TextBox1) Then
  TextBox1 = Format(TextBox1, "dd/mm/yyyy")
  .......
Else

nhập 13/1/08 hay 1/13/08 nó đều hiểu là ngày. Điều này rất nguy hiểm khi vô tình nhập sai. Ví dụ nhập ngày 1 tháng 2 năm 2008 nhưng nhập sai 1/22/08 thì nó chuyển thành 22/01/2008 và cho qua luôn.

Thường thì các tác giả của VBA sẽ dùng 1 hàm để sửa lại ngày :
PHP:
Public Function SuaNgay(NgayBatKy, Optional Loai As String = "") As Date
    Dim WS As Variant, WP As Variant, WDD As Variant, WMM As Variant, WYY As Variant
    Dim KT As String
    WS = NgayBatKy
    If Not IsDate(WS) Then
        SuaNgay = Date
    Else
        If InStr(1, WS, "/") > 0 Then
            KT = "/"
        ElseIf InStr(1, WS, "-") > 0 Then
            KT = "-"
        End If
        WP = InStr(1, WS, KT)
        WDD = Left(WS, WP - 1)
        WS = Mid(WS, WP + 1)
        WP = InStr(1, WS, KT)
        If WP = 0 Then
            WMM = WS
            WYY = Year(Date)
        Else
            WMM = Left(WS, WP - 1)
            WYY = Mid(WS, WP + 1)
        End If
        SuaNgay = DateSerial(WYY, WMM, WDD)
        If Loai = "CN" And Weekday(SuaNgay, vbSunday) = 1 Then _
                MsgBox ("Day la ngay Chu Nhat"), vbInformation, "GPE"
    End If
End Function
Tham số Loai : Nếu cần phân biệt là ngày Chủ Nhật thì sẽ cảnh báo khi ngày chọn là Chủ Nhật.

Bạn có thể nhập ký tự phân cách là / (10/08/2008) hoặc - (10-08-2008)

--=-- : Việc khai báo biến chưa được tối ưu, bạn có thể sửa lại

Khi đó :

PHP:
Private Sub TBCTNgay_AfterUpdate()
    On Error Resume Next
    Me.TBCTNgay.Value = Format(SuaNgay(Me.TBCTNgay.Value, "CN"), "dd/mm/yyyy")
End Sub
Chúc vui
 
Upvote 0
Theo như bạn thì hàm sẽ kiểm tra giá trị ngày tháng, nếu không đúng thì sẽ lấy ngày hệ thống, ngược lại sẽ chuyển đổi.
Nhưng theo ý của Thầy Phamduylong thì nhập 13/01/2008 hay 01/13/2008 đều đúng cả, như vậy câu lệnh : If Not IsDate(WS) Then có còn chính xác không?
 
Upvote 0
Theo như bạn thì hàm sẽ kiểm tra giá trị ngày tháng, nếu không đúng thì sẽ lấy ngày hệ thống, ngược lại sẽ chuyển đổi.
Nhưng theo ý của Thầy Phamduylong thì nhập 13/01/2008 hay 01/13/2008 đều đúng cả, như vậy câu lệnh : If Not IsDate(WS) Then có còn chính xác không?

Khi bạn nhập vào thì nó mới chỉ là ký tự, và chưa là ngày.
Hàm này làm theo định nghĩa : Nhập trước là ngày, nhập sau là tháng
Nếu phát hiện ngày tháng đó không có thì nó sẽ trả về ngày hệ thống.


Nếu nhập : 12/01/2008 thì sẽ là : Ngày 12 tháng 01
Nếu nhập : 01/12/2008 thì sẽ là : Ngày 01 tháng 12
Chứ nếu nhập lung tung thì cũng chịu thôi.

Và khi đã thể hiện lên rồi thì nhất định phải ngày trước tháng sau rồi (theo Format)
Chúc vui
 
Upvote 0
Khi bạn nhập vào thì nó mới chỉ là ký tự, và chưa là ngày.
Hàm này làm theo định nghĩa : Nhập trước là ngày, nhập sau là tháng
Nếu phát hiện ngày tháng đó không có thì nó sẽ trả về ngày hệ thống.


Nếu nhập : 12/01/2008 thì sẽ là : Ngày 12 tháng 01
Nếu nhập : 01/12/2008 thì sẽ là : Ngày 01 tháng 12
Chứ nếu nhập lung tung thì cũng chịu thôi.

Và khi đã thể hiện lên rồi thì nhất định phải ngày trước tháng sau rồi (theo Format)
Chúc vui

Ý em là nếu ta nhập bị sai, như 12/31/2008 chẳng hạn, thì nhập vào vẫn ok, khi đó ngày lại chuyển thành 12/07/2010.
Như vậy là sai rồi, khi đó sử dụng hàm Isdate là thiếu chính xác.
 
Upvote 0
Ý em là nếu ta nhập bị sai, như 12/31/2008 chẳng hạn, thì nhập vào vẫn ok, khi đó ngày lại chuyển thành 12/07/2010.
Như vậy là sai rồi, khi đó sử dụng hàm Isdate là thiếu chính xác.

Thực ra mà nói : Ngày 12/31/2008 chính là ngày 12/07/2010.
Vì vậy việc nhập ở trên không sai về kỹ thuật.
Vì ngày tháng được diễn tả như là một chuỗi số liên tiếp
Cũng như việc nhập 00/02/2008 thì chính là ngày 31/01/2008

Vì vậy ta phải đặt ra việc nhập sai : Như thế nào là nhập sai?? Ví dụ :
Khi nhập 12/31/2008 thì

  1. Ngày cứ sẽ là những ký tự đầu tiên trước dấu phân cách đầu tiên (12)
  2. Tháng là ký tự nằm giữa 2 dấu phân cách (31)
  3. Còn lại là năm (2008)
Sau đó nếu ngày tháng đó được chấp nhận, và không biến đổi (như trường hợp trên) thì lấy, còn không thì lấy ngày hệ thống???
Nếu thế thì thêm mấy cái If là được mà.

Liệu có phải bạn đang diễn giải như thế ??

Chúc vui.
 
Upvote 0
Đúng vậy, ngoài hàm isdate, ta nên thêm hàm Mid, Instr để cắt lấy tháng trong chuỗi ngày tháng, sau đó so sánh với 12, nếu <=12 thì Go, ngược lại thì End.
 
Upvote 0
Đúng vậy, ngoài hàm isdate, ta nên thêm hàm Mid, Instr để cắt lấy tháng trong chuỗi ngày tháng, sau đó so sánh với 12, nếu <=12 thì Go, ngược lại thì End.

Đúng vậy :

PHP:
Public Function SuaNgay(NgayBatKy, Optional Loai As String = "") As Date
    Dim WS  As String, WP As String, WDD As String, WMM As String, WYY As String
    Dim KT As String
    WS = NgayBatKy
    If Not IsDate(WS) Then
        SuaNgay = Date
    Else
        If InStr(1, WS, "/") > 0 Then
            KT = "/"
        ElseIf InStr(1, WS, "-") > 0 Then
            KT = "-"
        End If
        WP = InStr(1, WS, KT)
        WDD = Left(WS, WP - 1)
        WS = Mid(WS, WP + 1)
        WP = InStr(1, WS, KT)
        If WP = 0 Then
            WMM = WS
            WYY = Year(Date)
        Else
            WMM = Left(WS, WP - 1)
            WYY = Mid(WS, WP + 1)
        End If
        If Val(WMM) > 12 Then Exit Function
        If Val(WDD) > 31 Then Exit Function
        SuaNgay = DateSerial(WYY, WMM, WDD)
        If Loai = "CN" And Weekday(SuaNgay, vbSunday) = 1 Then _
                MsgBox ("Day la ngay Chu Nhat"), vbInformation, "GPE"
    End If
End Function
PHP:
Private Sub TextBox1_AfterUpdate()
    On Error Resume Next
    Dim iDate As Date
    iDate = SuaNgay(Me.TextBox1.Value, "CN")
    If iDate > 0 Then
        Me.TextBox1.Value = Format(iDate, "dd/mm/yyyy")
    Else
        Me.TextBox1.Value = ""
    End If
End Sub
Chúc vui.
 
Upvote 0
Lệnh đại ca đã thương thì thương cho trót. Kiểm tra luôn tháng thiếu và đủ/tháng 2 năm nhuận để chặn nhập sai ngày khi nhập dữ liệu luôn.
 
Upvote 0
Lệnh đại ca đã thương thì thương cho trót. Kiểm tra luôn tháng thiếu và đủ/tháng 2 năm nhuận để chặn nhập sai ngày khi nhập dữ liệu luôn.
Có trong Function mà
PHP:
...
NgayBatKy="29/02/2009"
WS = NgayBatKy 
If Not IsDate(WS) Then
Msgbox "Khong co ngay nhu the!"
        SuaNgay = Date
    Else
 
Upvote 0
Có trong Function mà
PHP:
...
NgayBatKy="29/02/2009"
WS = NgayBatKy 
If Not IsDate(WS) Then
Msgbox "Khong co ngay nhu the!"
        SuaNgay = Date
    Else
Tôi cũng chưa test nhưng nếu có thì không cần dòng lệnh:
HTML:
If Val(WDD) > 31 Then Exit Function
và dòng: 
If Val(WMM) > 12 Then Exit Function
còn không thì kiểm tra cả việc nhâp số âm (<0)
 
Upvote 0
Tôi cũng chưa test nhưng nếu có thì không cần dòng lệnh:
HTML:
If Val(WDD) > 31 Then Exit Function
và dòng:
If Val(WMM) > 12 Then Exit Function
còn không thì kiểm tra cả việc nhâp số âm (<0)
Có khi bỏ nó cũng chạy, tôi cũng không test, nhưng hàm IsDate mà true thì chắc ngày hợp lệ.
Tôi có thấy 1 file của ai đó trên GPE, hình như là NVThien1967 mà tách ngày thành 3 textbox: TextDD, TextMM, TextYY. Và khi nhập text box nào kiểm tra ngay TextBox ấy.
Khi ghép lại có thêm 1 hàm IsDate DateSerial(year(TextYY),month(TextMM),day(TextDD)).
Bác thử theo hướng ấy, có khi lại hay.
 
Upvote 0
Có khi bỏ nó cũng chạy, tôi cũng không test, nhưng hàm IsDate mà true thì chắc ngày hợp lệ.
Tôi có thấy 1 file của ai đó trên GPE, hình như là NVThien1967 mà tách ngày thành 3 textbox: TextDD, TextMM, TextYY. Và khi nhập text box nào kiểm tra ngay TextBox ấy.
Khi ghép lại có thêm 1 hàm IsDate DateSerial(year(TextYY),month(TextMM),day(TextDD)).
Bác thử theo hướng ấy, có khi lại hay.

Nếu không có nó thì khi nhập 12/31/2008 nó lại ra 12/07/2010.
Vì vậy hơi phiền.

Nếu có bỏ thì bỏ :

PHP:
If Val(WDD) > 31 Then Exit Function
Chúc vui.
 
Upvote 0
Có khi bỏ nó cũng chạy, tôi cũng không test, nhưng hàm IsDate mà true thì chắc ngày hợp lệ.
Tôi có thấy 1 file của ai đó trên GPE, hình như là NVThien1967 mà tách ngày thành 3 textbox: TextDD, TextMM, TextYY. Và khi nhập text box nào kiểm tra ngay TextBox ấy.
Khi ghép lại có thêm 1 hàm IsDate DateSerial(year(TextYY),month(TextMM),day(TextDD)).
Bác thử theo hướng ấy, có khi lại hay.
Kiểm tra bằng cách này không được Thu Nghi. Vì bất kỳ 3 số nào đưa vào DateSerial cũng cho ra kết quả là ngày. Ví dụ DateSerial(2008, 120, 100) cho kết quả ngày 10/03/2018. Không phải Excel sai vì DateSerial hiểu:
- 120 là 120 tháng=12 năm >2008+12=2018
- 100 ngày là 3 tháng + 10 ngày nên kết quả cuối cùng là 10/03/2018.
Nhưng vẫn có thể dùng DateSerial để kiểm tra ngày nhập sai như 29/2/2007, 31/11/2008, 27/13/2008 bằng cách so sánh ngày, tháng, năm nhập trong TextBox với ngày tháng năm từ kết quả của DateSerial.
Nếu ngày tháng trong TextBox khác với ngày tháng của DateSerial là ngày TextBox không hợp lệ.
Hàm DMY kiểm tra ngày nhập dạng d/m/yy, nếu đúng thì chuyển sang dạng đ/mm/yyyy
Nếu năm yy nhập tắt (nhỏ hợn 100) thì chuyển sang 20yy.
Mã:
Function DMY(txt) As String
Dim dd As Byte, mm As Byte, yy As Integer, vt1 As Byte, vt2 As Byte
vt1 = InStr(1, txt, "/")
vt2 = InStr(vt1 + 1, txt, "/")
dd = Left(txt, vt1 - 1)
mm = Mid(txt, vt1 + 1, vt2 - vt1 - 1)
yy = Mid(txt, vt2 + 1)
If yy < 100 Then yy = 2000 + yy
If dd = Day(DateSerial(yy, mm, dd)) And mm = Month(DateSerial(yy, mm, dd)) Then
  DMY = Format(dd, "00") & "/" & Format(mm, "00") & "/" & yy
Else
  DMY = "???"
End If
End Function
 
Upvote 0
Web KT
Back
Top Bottom