SetFocus không có tác dụng ?

Liên hệ QC

Nguyen Rem

Tất cả chỉ là đưa ra quyết định đúng đắn
Tham gia
23/2/22
Bài viết
211
Được thích
30
Giới tính
Nữ
Em chào các anh chị trên diễn đàn . Em lại trở lại rồi đây ^^
Không nghỉ lễ ! Sáng nay em ngồi viết 1 file tổng hợp những kiến thức mà em đã học thì lại có một số vấn đề sau mong anh chị giải thích giúp em
Khi em nhấn vào Run thì tại TextBox có tên là "txtFullName" Nó không được focus .
Em mới học VBA nên code quá "cao siêu" em không hiểu ^^ nên anh chị giải thích kĩ giúp em nhé hihi
1651297315189.png
1651297414125.png
 

File đính kèm

  • usfInsertInformation.xlsm
    34.9 KB · Đọc: 6
Xóa vbModeless trong lệnh Show
 
Upvote 0
Bạn cắt đoạn code đưa vào sự kiện Userform_Actvivate

Vì Form Intiaalize là sự kiện khi khởi tạo nên không có một hành động nào được thực thi ngoài giao diện
cho đến khi Form được hiển thị thì bạn có thể SetFocus
JavaScript:
Private Sub UserForm_Activate()
  usfCoBan.txtFullName.SetFocus
End Sub
 
Upvote 0
Bạn cắt đoạn code đưa vào sự kiện Userform_Actvivate

Vì Form Intiaalize là sự kiện khi khởi tạo nên không có một hành động nào được thực thi ngoài giao diện
cho đến khi Form được hiển thị thì bạn có thể SetFocus
JavaScript:
Private Sub UserForm_Activate()
  usfCoBan.txtFullName.SetFocus
End Sub
Owa! Em làm được rồi . Em cảm ơn anh nhiều ^^
 
Upvote 0
Upvote 0
Tôi để nguyên SetFocus trong initialize, vẫn set focus được.
Khi mở ở chế độ Modal, form không phụ thuộc khung cửa sổ chính, con trỏ trỏ trực tiếp vào Form, nên có thể SetFocus ngay tại thời điểm khởi tạo Form.
Ở chế độ Modeless, vì con trỏ còn phải phụ thuộc vào khung cửa sổ chính (khung Excel)
Nên khi mở ở chế độ ModeLess con trỏ chưa trỏ đến Form ở thời điểm khởi tạo Intialize.
 
Upvote 0
Khi mở ở chế độ Modal, form không phụ thuộc khung cửa sổ chính, con trỏ trỏ trực tiếp vào Form, nên có thể SetFocus ngay tại thời điểm khởi tạo Form.
Ở chế độ Modeless, vì con trỏ còn phải phụ thuộc vào khung cửa sổ chính (khung Excel)
Nên khi mở ở chế độ ModeLess con trỏ chưa trỏ đến Form ở thời điểm khởi tạo Intialize.
Tôi biết điều đó. Bài 2 tôi chỉ ra nguyên nhân (nguyên nhân chính là ModeLess) và cách chữa. Còn bạn ở bài 4 không nói "tại ModeLess" mà chỉ nói rằng vì Initialize là sự kiện khi khởi tạo nên không có một hành động nào được thực thi (nguyên văn).
Anh có thể giải thích cho em được không ạ ? Hoặc anh cho em tài liệu để em đọc cũng được ^^
Nếu bạn vẫn thích ModeLess thì dùng code ở bài #4 và đọc giải thích ở bài #8, đừng đọc giải thích ở bài #4
 
Upvote 0
Theo tôi SetFocus vẫn có tác dụng. Chỉ có điều khi có vbModeless thì sau "cánh gà" một code nào đó đã được thực hiện thêm và làm "hỏng" focus.

Ta thêm và xét code
Mã:
Private Sub txtFullName_Enter()
    Me.Caption = "hic hic"
End Sub

Nếu không có usfCoBan.txtFullName.SetFocus thì Caption không bị thay đổi do code txtFullName_Enter không được thực hiện. Bởi khi đó thì theo thiết lập trong design time thì textbox txtCode có focus chứ không phải txtFullName. Nhưng khi có usfCoBan.txtFullName.SetFocus thì dù là Show hay Show vbModeless thì Caption đều bị thay đổi thành "hic hic", chứng tỏ là trong 2 trường hợp đều sảy ra "SỰ ĐI VÀO" txtFullName. Chắc chắn focus đã tập trung vào txtFillName nhưng do vbModeless nên sau đó một cái gì đó được thực hiện thêm nên focus bị "hỏng".

Ngoài bỏ vbModeless thì vẫn có thể dùng nó. Lúc đó ngoài đặt SetFocus trong UserForm_Activate thì có thể đặt sau Show. Với Show modal thì nếu sau dòng usfCoBan.Show còn có những code khác thì những code đó chỉ được thực hiện sau khi đóng hoặc ẩn UserForm, bởi điều khiển (control) dừng ở dòng usfCoBan.Show cho tới tận khi đóng hoặc ẩn UserForm. Nhưng với Show vbModeless thì ngay sau khi Form được hiển thị thì các code sau Show nếu có thì sẽ được thực thi ngay lập tức. Vì thế có thể SetFocus sau Show
Mã:
Public Sub Show_usfCoBan()
    usfCoBan.Show vbModeless
    usfCoBan.txtFullName.SetFocus
End Sub
 
Upvote 0
Theo tôi SetFocus vẫn có tác dụng. Chỉ có điều khi có vbModeless thì sau "cánh gà" một code nào đó đã được thực hiện và làm "hỏng" focus.
Tôi biết rằng SetFocus vẫn có tác dụng, chỉ có con trỏ không nhấp nháy để gõ thôi. Tôi test bằng cách nhấn tab, thì control có TabIndex tiếp theo vẫn được focus.
 
Upvote 0
Tôi biết rằng SetFocus vẫn có tác dụng, chỉ có con trỏ không nhấp nháy để gõ thôi. Tôi test bằng cách nhấn tab, thì control có TabIndex tiếp theo vẫn được focus.
SetFocus vẫn được thực thi và có tác dụng. Chỉ là tôi cho rằng khi vbModeless thì một cái gì đấy làm HỎNG focus. Tức nếu nhấn TAB thì textbox tiếp theo có focus, nhưng không thể nhập liệu ngay vào txtFullName. Cái kiểu cờ đến tay txtFullName nhưng nó không phất được vì bị ai đó cho cú huých đau đớn vào bên sườn. :D
 
Upvote 0
Em cảm ơn mọi người rất nhiều <3 . Em vừa đi chơi về xong thì vào đọc liền hihi . Em học được rất nhiều từ cách mọi người thảo luận .
Cảm ơn mọi người đã dành thời gian đọc và trả lời chi tiết đến như vậy ^^
 
Upvote 0
Nhưng mà anh ơi ! Anh có thể giải thích cho em thêm về chỗ này được không . Em vẫn chưa hiểu :>
Bạn nên hiểu là code bạn viết chỉ là nhưng "câu lệnh" đơn giản. Sau "cánh gà" code của các thư viện phải làm việc cật lực để thực hiện các code đó. Ví như bạn chỉ viết: rửa thịt và thái hành tỏi ... Nhưng trong bếp chúng được biến thành các lệnh chi tiết cho robot: cho vào ngăn A xối nước 50 độ + dấm, khuấy 5 phút thì xả nhiều nước ...
Bạn chỉ viết Show, Show vbModeless, nhưng code trong các thư viện sẽ thực hiện điều đó. Show (modal) và rất nhiều cửa sổ đối thoại cũng được hiển thị modal. Tức phải đóng chúng thì mới có thể làm "các việc khác". Để dễ hiểu thì bạn cứ tưởng tượng như sau. Code của bạn sẽ được load vào RAM và thực hiện. Giả sử dòng Show (modal) ở trong RAM ở địa chỉ ABC. Để thực hiện cái Show kia thì sẽ có một bước nhẩy tới địa chỉ XYZ trong thư viện (cũng có trong RAM nhưng ở vị trí khác) để thực hiện code có trách nhiệm hiển thị Form. Tại địa chỉ XYZ các code chịu trách nhiệm hiển thị Form sẽ được thực thi và nếu có vbModeless thì ngay lập tức lại có bước nhẩy về chỗ trong bộ nhớ ngay sau ABC để thực thi các lệnh tiếp theo. Nhưng nếu có vbModal (mặc định) thì code trong thư viện sau khi hiển thị Form thì không có bước nhẩy về sau ABC. Mà code sẽ thực hiện một vòng lặp (cứ cho là Do Loop để dễ theo dõi). Trong vòng lặp sẽ có việc thực hiện mọi vấn đề liên qua tới Form: phục vụ các thao tác với các control trên Form, làm mới Form ..., và kiểm tra xem cửa sổ Form đã được đóng hay chưa. Chỉ khi Form được đóng thì mới ra khỏi vòng lặp và lúc đó mới có bước nhảy trở về sau vị trí ABC để thực thi các code tiếp theo nếu có. Trong Windows, Excel, Word, Delphi, VB6 bạn sẽ gặp rất nhiều cửa sổ kiểu đối thoại mà bạn phải đóng chúng thì mới làm được các việc khác. UserForm với Show modal cũng thế: control (điều khiển) sẽ được chuyển tới XYZ và ở đấy sau khi làm các việc để hiển thị Form thì một vòng lặp sẽ được thực hiện. Chỉ khi cửa sổ Form được đóng thì mới ra khỏi vòng lặp, sẽ có bước nhảy trở về (return) vị trí sau ABC, tức ngay sau vị trí mà từ đó có sự ra đi, và control được trả về nơi có code của bạn. Chính vì thế bạn có thể có MsgBox "hic hic" và nhiều code khác nữa ngay sau USerForm.Show nhưng MsgBox bạn chỉ nhìn thấy khi đóng Form, và lúc đó các code kia mới được thực thi.
 
Upvote 0
Bạn nên hiểu là code bạn viết chỉ là nhưng "câu lệnh" đơn giản. Sau "cánh gà" code của các thư viện phải làm việc cật lực để thực hiện các code đó. Ví như bạn chỉ viết: rửa thịt và thái hành tỏi ... Nhưng trong bếp chúng được biến thành các lệnh chi tiết cho robot: cho vào ngăn A xối nước 50 độ + dấm, khuấy 5 phút thì xả nhiều nước ...
Bạn chỉ viết Show, Show vbModeless, nhưng code trong các thư viện sẽ thực hiện điều đó. Show (modal) và rất nhiều cửa sổ đối thoại cũng được hiển thị modal. Tức phải đóng chúng thì mới có thể làm "các việc khác". Để dễ hiểu thì bạn cứ tưởng tượng như sau. Code của bạn sẽ được load vào RAM và thực hiện. Giả sử dòng Show (modal) ở trong RAM ở địa chỉ ABC. Để thực hiện cái Show kia thì sẽ có một bước nhẩy tới địa chỉ XYZ trong thư viện (cũng có trong RAM nhưng ở vị trí khác) để thực hiện code có trách nhiệm hiển thị Form. Tại địa chỉ XYZ các code chịu trách nhiệm hiển thị Form sẽ được thực thi và nếu có vbModeless thì ngay lập tức lại có bước nhẩy về chỗ trong bộ nhớ ngay sau ABC để thực thi các lệnh tiếp theo. Nhưng nếu có vbModal (mặc định) thì code trong thư viện sau khi hiển thị Form thì không có bước nhẩy về sau ABC. Mà code sẽ thực hiện một vòng lặp (cứ cho là Do Loop để dễ theo dõi). Trong vòng lặp sẽ có việc thực hiện mọi vấn đề liên qua tới Form: phục vụ các thao tác với các control trên Form, làm mới Form ..., và kiểm tra xem cửa sổ Form đã được đóng hay chưa. Chỉ khi Form được đóng thì mới ra khỏi vòng lặp và lúc đó mới có bước nhảy trở về sau vị trí ABC để thực thi các code tiếp theo nếu có. Trong Windows, Excel, Word, Delphi, VB6 bạn sẽ gặp rất nhiều cửa sổ kiểu đối thoại mà bạn phải đóng chúng thì mới làm được các việc khác. UserForm với Show modal cũng thế: control (điều khiển) sẽ được chuyển tới XYZ và ở đấy sau khi làm các việc để hiển thị Form thì một vòng lặp sẽ được thực hiện. Chỉ khi cửa sổ Form được đóng thì mới ra khỏi vòng lặp, sẽ có bước nhảy trở về (return) vị trí sau ABC, tức ngay sau vị trí mà từ đó có sự ra đi, và control được trả về nơi có code của bạn. Chính vì thế bạn có thể có MsgBox "hic hic" và nhiều code khác nữa ngay sau USerForm.Show nhưng MsgBox bạn chỉ nhìn thấy khi đóng Form, và lúc đó các code kia mới được thực thi.
Em cảm ơn anh nhiều ^^ Thật khó tìm ở đâu một bài viết chi tiết như vậy.
Nhưng có thể vì nó sâu quá nên em vẫn chưa hiểu hết được bản chất của nó . Nhưng không sao em sẽ lưu bài viết này để sau khi tiếp xúc đủ nhiều rồi đọc lại .
Những điều rút ra:
Khi dùng vbModal trong một thủ tục thì các dòng code sau đó sẽ không chạy cho đến khi userform được đóng
<code>
Sub Test ()
usf1.Show
MsgBox " Đây là usf1" 'Dòng này không chạy'
End Sub
</code>

Khi dùng vbModeless thì các dòng code sau đó vẫn chạy bình thường
<code>
Sub Test ()
usf1.Show vbModeless
MsgBox " Đây là usf1" 'Dòng này chạy bình thường'
End Sub
</code>
 
Upvote 0
Những điều rút ra:
Khi dùng vbModal trong một thủ tục thì các dòng code sau đó sẽ không chạy cho đến khi userform được đóng
<code>
Sub Test ()
usf1.Show
MsgBox " Đây là usf1" 'Dòng này không chạy'
End Sub
</code>

Khi dùng vbModeless thì các dòng code sau đó vẫn chạy bình thường
<code>
Sub Test ()
usf1.Show vbModeless
MsgBox " Đây là usf1" 'Dòng này chạy bình thường'
End Sub
</code>
Đúng rồi, trong trườg hợp 1 thì tất cả các dòng code sau Show chỉ được thực hiện sau khi đóng Form. Tức nếu hiển thị Form 2 giờ rồi người dùng mới đóng nó thì phải sau 2 giờ MsgBox " Đây là usf1" 'Dòng này không chạy' mới được thực hiện. Còn trong trường hợp Show vbModeless thì MsgBox hiển thị ngay cho dù 2 tiếng sau người dùng mới đóng Form.
 
Upvote 0
Đúng rồi, trong trườg hợp 1 thì tất cả các dòng code sau Show chỉ được thực hiện sau khi đóng Form. Tức nếu hiển thị Form 2 giờ rồi người dùng mới đóng nó thì phải sau 2 giờ MsgBox " Đây là usf1" 'Dòng này không chạy' mới được thực hiện. Còn trong trường hợp Show vbModeless thì MsgBox hiển thị ngay cho dù 2 tiếng sau người dùng mới đóng Form.
Em biết ! Em có thể cũng sẽ vẫn không hiểu như trên nhưng đọc nó vẫn cứ cuốn cuốn . Anh có thể viết thêm cho em về tại sao nó phải chờ 2h sau mới chạy MsgBox " Đây là usf1" không ạ ^^
 
Upvote 0


Nhưng có thể vì nó sâu quá nên em vẫn chưa hiểu hết được bản chất của nó

Em biết ! Em có thể cũng sẽ vẫn không hiểu như trên nhưng đọc nó vẫn cứ cuốn cuốn . Anh có thể viết thêm cho em về tại sao nó phải chờ 2h sau mới chạy MsgBox " Đây là usf1" không ạ ^^

Biết nói thế nào cho đơn giản hơn nhỉ.

Ta xét code
Mã:
Sub tach()
dim s As String
    s = Sheet1.Range("A1").Value
    Debug.Print s
End Sub

Sub hichic ()
Call tach
MsgBox "Đây là thông báo"
End Sub

Ta thực hiện Sub hichic. Rõ ràng trước tiên sub tach được thực hiện. Chỉ khi sub tach được THỰC HIỆN XONG HOÀN TOÀN thì mới thực thi MsgBox, đúng không?

Vậy bây giờ ta xét code
Mã:
Sub Test ()
usf1.Show
MsgBox " Đây là usf1" 'Dòng này không chạy' (A)
End Sub
Trước tiên phải thực hiện usf1.Show. Chỉ khi thực hiện xong usf1.Show thì mới thực hiện MsgBox " Đây là usf1" 'Dòng này không chạy', đúng không?

Thế thì bây giờ bạn tưởng tượng rằng trong thư viện VBA code của phương thức Show của UserForm nó như thế này
Mã:
Hiển thị UserForm
...
<bắt đầu một VÒNG LẶP>
...
nếu Form được đóng thì ra khỏi vòng lặp
<kết thúc VÒNG LẶP>

Nếu người dùng sau khi chạy sub Test được 5 tiếng đồng hồ mới đóng Form usf1 thì sao? Thì suốt 5 tiếng code cứ quẩn quanh trong VÒNG LẶP. Chỉ sau 5 tiếng đồng hồ thì mới ra khỏi VÒNG LẶP, và lúc đó code Show mới được thực hiện xong. Lúc đó mới đến lượt code MsgBox được thực thi, đúng không? Còn với vbModeless thì không có VÒNG LẶP kia nên phương thức Show được thực hiện xong ngay lập tức, nên ngay lập tức MsgBox được thực thi, đúng không?
 
Lần chỉnh sửa cuối:
Upvote 0
Biết nói thế nào cho đơn giản hơn nhỉ.

Ta xét code
Mã:
Sub Test ()
usf1.Show
MsgBox " Đây là usf1" 'Dòng này không chạy' (A)
End Sub
Trước tiên phải thực hiện usf1.Show. Chỉ khi thực hiện xong usf1.Show thì mới thực hiện MsgBox " Đây là usf1" 'Dòng này không chạy', đúng không?

Thế thì bây giờ bạn tưởng tượng rằng trong thư viện VBA code của phương thức Show của UserForm nó như thế này
Mã:
Hiển thị UserForm
...
<bắt đầu một VÒNG LẶP>
...
nếu Form được đóng thì ra khỏi vòng lặp
<kết thúc VÒNG LẶP>

Nếu người dùng sau khi chạy sub Test được 5 tiếng đồng hồ mới đóng Form usf1 thì sao? Thì suốt 5 tiếng code cứ quẩn quanh trong VÒNG LẶP. Chỉ sau 5 tiếng đồng hồ thì mới ra khỏi VÒNG LẶP, và lúc đó code Show mới được thực hiện xong. Lúc đó mới đến lượt code MsgBox được thực thi, đúng không? Còn với vbModeless thì không có VÒNG LẶP kia nên phương thức Show được thực hiện xong ngay lập tức, nên ngay lập tức MsgBox được thực thi, đúng không
Dạ vâng ạ ! Em hiểu sao nó bị chậm 2 tiếng rồi ạ ^^ thôi anh ngủ đi ! Cũng muộn lắm rồi ấy anh :> Em cảm ơn anh rất nhiều hi
 
Upvote 0
Web KT

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

Back
Top Bottom