[Xin giúp đỡ] Check user và pass, sau đó tìm ra level dùng VBA (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

gameonly308

Thành viên hoạt động
Tham gia
4/5/09
Bài viết
197
Được thích
10
Em có user form như sau:
217095

Và data trong 3 cột user - level và pass
217096

Em muốn viết trên User Form để khi điền vào user và pass, nếu thỏa mãn thì sẽ kiểm tra level của user .
Sau đó nếu là level 1 thì gọi userform "a1"
Sau đó nếu là level 2 thì gọi userform "a2"
Sau đó nếu là level 3 thì gọi userform "a3"
Sau đó nếu là level 4 thì gọi userform "a4"
Có bác nào thạo phần này giúp em với !Em cảm ơn ạ!
File Excel ở dưới ạ, em quên mất ko upfile @@
 

File đính kèm

Lần chỉnh sửa cuối:
Không lẽ bạn chờ người khác làm file rồi viết code luôn à?
Mà thông tin để trên sheet thì thôi khỏi mật khẩu chi cho mất công bạn.
 
Nếu là file của anh HTN viết thì bạn hỏi trong box đó, anh ấy hỗ trợ.
 
Không lẽ bạn chờ người khác làm file rồi viết code luôn à?
Mà thông tin để trên sheet thì thôi khỏi mật khẩu chi cho mất công bạn.
Em đang mò mẫm ạ, tại tự học nên vốn kiến thức không nhiều, còn 1 số cái em làm được rồi, cái này mới e chưa biết nên hỏi ạ.
Thông tin để trên sheet bình thường thôi ạ, em muốn làm để học + tính thống nhất cao trên 1 file excel chứ ko riêng bảo mật ạ.
Chứ nếu em code mà chạy dược thì không cần hướng dẫn rồi, hoặc anh biết ở đâu có hướng dẫn dạng kiểu này cho em link em học với ạ.
Còn không thì anh biết anh hướng dẫn em cách code với!
Bài đã được tự động gộp:

Nếu là file của anh HTN viết thì bạn hỏi trong box đó, anh ấy hỗ trợ.
Em ko lấy của ai ạ, tự nghĩ ra trong quá trình tự làm cho mình dùng thôi. Đến đoạn này ko biết làm tnao nên lên GPE hỏi ạ
 
Em cần học cách search user và pass trên vba sau đó lấy level của user đó, chứ còn insert qua sheet trung gian rồi lại lấy data từ sheet đó để thì có thể làm đc ạ.
Em thấy có hướng dẫn kết hợp dùng hàm Find trên VBA mà em ko biết cách làm ạ!
 
Em đang mò mẫm ạ, tại tự học nên vốn kiến thức không nhiều, còn 1 số cái em làm được rồi, cái này mới e chưa biết nên hỏi ạ.
Thông tin để trên sheet bình thường thôi ạ, em muốn làm để học + tính thống nhất cao trên 1 file excel chứ ko riêng bảo mật ạ.
Chứ nếu em code mà chạy dược thì không cần hướng dẫn rồi, hoặc anh biết ở đâu có hướng dẫn dạng kiểu này cho em link em học với ạ.
Còn không thì anh biết anh hướng dẫn em cách code với!
Bài đã được tự động gộp:


Em ko lấy của ai ạ, tự nghĩ ra trong quá trình tự làm cho mình dùng thôi. Đến đoạn này ko biết làm tnao nên lên GPE hỏi ạ
Bạn tham khảo bài này:
Tặng các bạn File đăng nhập, Admin có thể tạo User mới
 
Bạn nên tìm trong bài của @Hoàng Trọng Nghĩa là thấy cái bạn cần .... vba làm đơn giản còn hỏi vậy thì vb6 làm sao đây ??
đâu phải 1 vài dòng code là xong ... nó liên quan rất nhiều code trong 1 dự án code !!
Em không biết nó khó thế nào trên vb hoàn toàn, nhưng nếu chạy qua 1 sheet trung gian để kiểm tra user và pass để lấy level thì em làm được ngay mà bác! Đâu khó đến mức 1 dự án code đâu ạ?
 
làm được đó ... Mạnh viết trên VB6 (DLL có cái Form trong đó.. nhạp mã máy đăng ký ) ... còn delphi đang suy nghĩ code két sao ???? mò mò tiếp
nó cũng giống na na như vb thôi anh (hồi mới mò Delphi em cũng có viết thử rồi). em cũng mò check thời gian mà chưa ra hướng nào hay
 
Em làm đơn giản = check user trong list, nếu tồn tại user thì gán user + pass đăng nhập vào 2 ô trong sheet.
Sau đó check = hàm giữa user và pass vừa gán với user và pass trong list khớp không, nếu khớp thì gọi ra level của user đó.
Kết quả là ok.
Nhưng em muốn học hoàn toàn = code VBA, không gán giá trị vào sheet nữa ạ!
 
Em làm đơn giản = check user trong list, nếu tồn tại user thì gán user + pass đăng nhập vào 2 ô trong sheet.
Sau đó check = hàm giữa user và pass vừa gán với user và pass trong list khớp không, nếu khớp thì gọi ra level của user đó.
Kết quả là ok.
Nhưng em muốn học hoàn toàn = code VBA, không gán giá trị vào sheet nữa ạ!

Góp thêm ý nhé.
Làm Form đăng nhập có 2 kiểu:
- Chỉ được chọn User trong danh sách đã thiết lập sẳn qua combobox. Khi đó code chỉ cần kiểm tra trong ds User có đúng với User đã chọn hay không
- Tự gõ tên User vô rồi code sẽ check cả User lẫn Pass.
Bạn đang muốn làm theo cách nào?

Làm theo cách 1, sẽ ít code hơn.
- Tạo 2 textbox: 1lưu mật khẩu, 1 lưu UserLevel ngay trên Form. 2 textbox này bạn cho ẩn đi. Vd: txtPassTemp, txtUserLevel
- Khi người dùng chọn User từ Combobox, sự kiện AfterUpdate sẽ gán sẳn Pass và level của User đó vô 2 textbox ẩn ở trên.
- Khi nhập pass sẽ đối chiếu với txtPassTemp để thực các thao tác sau đó.

Xem demo cơ bản nhé.
 

File đính kèm

Lần chỉnh sửa cuối:
Góp thêm ý nhé.
Làm Form đăng nhập có 2 kiểu:
- Chỉ được chọn User trong danh sách đã thiết lập sẳn qua combobox. Khi đó code chỉ cần kiểm tra password có đúng với User đã chọn hay không
- Tự gõ tên User vô rồi code sẽ check cả User lẫn Pass.
Bạn đang muốn làm theo cách nào?

Làm theo cách 1, sẽ ít code hơn.
- Tạo 2 textbox: 1lưu mật khẩu, 1 lưu UserLevel ngay trên Form. 2 textbox này bạn cho ẩn đi. Vd: txtPassTemp, txtUserLevel
- Khi người dùng chọn User từ Combobox, sự kiện AfterUpdate sẽ gán sẳn Pass và level của User đó vô 2 textbox ẩn ở trên.
- Khi nhập pass sẽ đối chiếu với txtPassTemp để thực các thao tác sau đó.

Xem demo cơ bản nhé.
Em cảm ơn bác đã góp ý ạ.
Ý của em là muốn user + pass người dùng phải tự điền vào.
Ứng với mỗi user và pass sẽ tìm ra 1 level đã được quy định trong 1 bảng danh sách cho trước để load form.
Vậy suy cho cùng em vẫn phải dùng danh sách trên sheet2 để check user là level mấy bác nhỉ.
Bác kiểm tra cho em với, xem cách check trên Sheet2 của User và Pass như thế này có hiệu quả về mặt sử dụng, và tinh gọn về mặt code không ạ.
 

File đính kèm

Em cảm ơn bác đã góp ý ạ.
Ý của em là muốn user + pass người dùng phải tự điền vào.
Ứng với mỗi user và pass sẽ tìm ra 1 level đã được quy định trong 1 bảng danh sách cho trước để load form.
Vậy suy cho cùng em vẫn phải dùng danh sách trên sheet2 để check user là level mấy bác nhỉ.
Bác kiểm tra cho em với, xem cách check trên Sheet2 của User và Pass như thế này có hiệu quả về mặt sử dụng, và tinh gọn về mặt code không ạ.

Trong demo tôi dùng biến toàn cục để lưu User và UserLevel rồi đó bạn. Cần gì phải lưu User/Pass đã đăng nhập xuống Sheet. Sau đó ở các sự kiện khác của ứng dụng, cái nào cần kiểm tra UserLevel thì móc cái biến toàn cục đó ra đối chiếu thôi.
Bạn lưu xuống Sheet nếu bạn muốn theo dõi hoạt động của User đăng nhập, ngày giờ đăng nhập, thoát để truy cứu nếu có phát sinh việc gì đó. Lưu vào LogFile chẳng hạn.
Tôi thấy bạn tốn vừa code vừa công thức cho ô pass check và level check rồi đó.
 
Lần chỉnh sửa cuối:
Trong demo tôi dùng biến toàn cục để lưu User và UserLevel rồi đó bạn. Cần gì phải lưu User/Pass đã đăng nhập xuống Sheet. Sau đó ở các sự kiện khác của ứng dụng, cái nào cần kiểm tra UserLevel thì móc cái biến toàn cục đó ra đối chiếu thôi.
Bạn lưu xuống Sheet nếu bạn muốn theo dõi hoạt động của User đăng nhập, ngày giờ đăng nhập, thoát để truy cứu nếu có phát sinh việc gì đó. Lưu vào LogFile chẳng hạn.
Tôi thấy bạn tốn vừa code vừa công thức cho ô pass check và level check rồi đó.
Vâng em cảm ơn bác, về phần các hàm VBA em không biết nhiều do chả được học hành gì, em sẽ nghiên cứu thêm và áp dụng cách của bác cho tiện hơn. Có những chỗ nào không hiểu mong bác dành thời gian quan tâm thêm giúp em với nhé !.
 
Vâng em cảm ơn bác, về phần các hàm VBA em không biết nhiều do chả được học hành gì, em sẽ nghiên cứu thêm và áp dụng cách của bác cho tiện hơn. Có những chỗ nào không hiểu mong bác dành thời gian quan tâm thêm giúp em với nhé !.

- Bạn nên tập thói quen khai báo biến tường minh (Option Explicit) để VBA có thể giúp kiểm tra, tránh gõ sai tên biến trong code
- Khai báo loại dữ liệu luôn càng tốt để VBA nó dành bộ nhớ cho từng biến đúng kiểu dữ liệu của nó, tránh phân bổ dư thừa bộ nhớ.

Dựa theo file của bạn, code cho nút [Login] thiết kế đơn giản như bên dưới:

Mã:
Private Sub login_cmb_Click()
    Const TB As String = "Thông Báo!"
    Dim rngFoundCell As Range
   
    Application.ScreenUpdating = False
    If Trim(user_txt.Text) = "" Or Trim(pass_txt.Text) = "" Then
        MsgBox "Please enter UserName and Password!", vbOKOnly, TB
        user_txt.SetFocus
        Exit Sub
    ElseIf Trim(user_txt.Text) = "" Then
        MsgBox "Please enter the Username", vbOKOnly, TB
        user_txt.SetFocus
        Exit Sub
    ElseIf Trim(pass_txt.Text) = "" Then
        MsgBox "Please enter the Password", vbOKOnly, TB
        pass_txt.SetFocus
        Exit Sub
    Else
        Set rngFoundCell = Sheet2.Range(Sheet2.[c5], Sheet2.Range("C5").End(xlDown)).Find(user_txt.Value, , xlValues, xlWhole)
        If rngFoundCell Is Nothing Then
            MsgBox "Wrong User", vbOKOnly, TB
            user_txt.SetFocus
            Exit Sub
        End If
        If pass_txt.Text <> rngFoundCell.Offset(, 2).Value Then
            MsgBox "Wrong password", vbOKOnly, TB
            pass_txt.SetFocus
            Exit Sub
        End If
        MsgBox "Login successfull."
       
        sUser = user_txt.Value
        iUserLevel = rngFoundCell.Offset(, 1).Value
       
        MsgBox "User: " & sUser & vbNewLine & "Level: " & iUserLevel
       
    End If
    Application.ScreenUpdating = True
   
End Sub

Nhớ khai báo thêm 2 biến toàn cục: sUser iUserLevel trong Module (không phải Form module) để tái sử dụng trong các code sau.
 
Lần chỉnh sửa cuối:
Mã:
iUserLevel = rngFoundCell.Offset(, 1).Value
Cái này có lẽ là cái quan trọng nhất em cần để tìm level user theo user đăng nhập. Em cảm ơn bác, vướng nhất chỗ đấy đấy ạ. Quả thật cái hàm Offset nhiều ứng dụng hay thật.
 
- Bạn nên tập thói quen khai báo biến tường minh (Option Explicit) để VBA có thể giúp kiểm tra, tránh gõ sai tên biến trong code
- Khai báo loại dữ liệu luôn càng tốt để VBA nó dành bộ nhớ cho từng biến đúng kiểu dữ liệu của nó, tránh phân bổ dư thừa bộ nhớ.

Dựa theo file của bạn, code cho nút [Login] thiết kế đơn giản như bên dưới:

Mã:
Private Sub login_cmb_Click()
    Const TB As String = "Thông Báo!"
    Dim rngFoundCell As Range
  
    Application.ScreenUpdating = False
    If Trim(user_txt.Text) = "" Or Trim(pass_txt.Text) = "" Then
        MsgBox "Please enter UserName and Password!", vbOKOnly, TB
        user_txt.SetFocus
        Exit Sub
    ElseIf Trim(user_txt.Text) = "" Then
        MsgBox "Please enter the Username", vbOKOnly, TB
        user_txt.SetFocus
        Exit Sub
    ElseIf Trim(pass_txt.Text) = "" Then
        MsgBox "Please enter the Password", vbOKOnly, TB
        pass_txt.SetFocus
        Exit Sub
    Else
        Set rngFoundCell = Sheet2.Range(Sheet2.[c5], Sheet2.Range("C5").End(xlDown)).Find(user_txt.Value, , xlValues, xlWhole)
        If rngFoundCell Is Nothing Then
            MsgBox "Wrong User", vbOKOnly, TB
            user_txt.SetFocus
            Exit Sub
        End If
        If pass_txt.Text <> rngFoundCell.Offset(, 2).Value Then
            MsgBox "Wrong password", vbOKOnly, TB
            pass_txt.SetFocus
            Exit Sub
        End If
        MsgBox "Login successfull."
      
        sUser = user_txt.Value
        iUserLevel = rngFoundCell.Offset(, 1).Value
      
        MsgBox "User: " & sUser & vbNewLine & "Level: " & iUserLevel
      
    End If
    Application.ScreenUpdating = True
  
End Sub

Nhớ khai báo thêm 2 biến toàn cục: sUser iUserLevel trong Module (không phải Form module) để tái sử dụng trong các code sau.
Chào bác, cái lv_cbb của em khi không điều chỉnh gì thì nó hiện dải ô rất rộng trong khi mình có mỗi số 1-2-3-4 rất ngắn, em muốn thu nó lại thì điều chỉnh ở ListWith. Nhưng khi điều chỉnh (chỉnh ListWith thành 20pt) thì bị lỗi lv_cbb thằng này, nó cứ hiện lên cái như trong đóng khung rất khó chịu, có các nào để bỏ đi không ạ.
Em cảm ơn!
 
Chào bác, cái lv_cbb của em khi không điều chỉnh gì thì nó hiện dải ô rất rộng trong khi mình có mỗi số 1-2-3-4 rất ngắn, em muốn thu nó lại thì điều chỉnh ở ListWith. Nhưng khi điều chỉnh (chỉnh ListWith thành 20pt) thì bị lỗi lv_cbb thằng này, nó cứ hiện lên cái như trong đóng khung rất khó chịu, có các nào để bỏ đi không ạ.
Em cảm ơn!

Chỉnh Column Width nhé.Nếu combobox của bạn hiển thị 3 cột thì thiết lập độ rộng từng cột cách nhau dấu ";". ListWidth là tổng độ rộng của tất cả các cột hiển thị.
Ví dụ:
Column Width: 20pt;30pt;10pt
ListWidth: 60 pt
 
Chỉnh Column Width nhé.Nếu combobox của bạn hiển thị 3 cột thì thiết lập độ rộng từng cột cách nhau dấu ";". ListWidth là tổng độ rộng của tất cả các cột hiển thị.
Ví dụ:
Column Width: 20pt;30pt;10pt
ListWidth: 60 pt
OK bác chuẩn luôn ạ, chỉnh thêm cái Column Width = 20pt nữa là đẹp long lanh rồi ạ
 
Chỉnh Column Width nhé.Nếu combobox của bạn hiển thị 3 cột thì thiết lập độ rộng từng cột cách nhau dấu ";". ListWidth là tổng độ rộng của tất cả các cột hiển thị.
Ví dụ:
Column Width: 20pt;30pt;10pt
ListWidth: 60 pt
Chào bác, hnay em lại có lỗi phát sinh nữa ạ.
Khi vào user form "login" click "Admin", sau đó đăng nhập user và pass nào đó hợp lệ.
Khi vào được ấn Cancel để quay về lại user form "login" sau đó lại click "Admin" thì báo lỗi VBA: error 400 form already displayed can't show modally
Em buộc phải thêm 1 dòng code vào file "login" nhưng nói thật nó bị load 2 lần và không đẹp.
Trong khi các dòng code khác em đều để lệnh Unload admin_login thay cho Hide rồi, mong bác tư vấn hộ em với
 

File đính kèm

  • 4.jpg
    4.jpg
    370 KB · Đọc: 13
Chào bác, hnay em lại có lỗi phát sinh nữa ạ.
Khi vào user form "login" click "Admin", sau đó đăng nhập user và pass nào đó hợp lệ.
Khi vào được ấn Cancel để quay về lại user form "login" sau đó lại click "Admin" thì báo lỗi VBA: error 400 form already displayed can't show modally
Em buộc phải thêm 1 dòng code vào file "login" nhưng nói thật nó bị load 2 lần và không đẹp.
Trong khi các dòng code khác em đều để lệnh Unload admin_login thay cho Hide rồi, mong bác tư vấn hộ em với

Tôi thấy file cũ bạn chạy bình thường, không lỗi.
Mà ý đồ bạn muốn thiết kế như thế nào mà lại có thêm nút Admin trên form Login? Hiếm thấy... :)

Mã:
'Code cho nút Admin tren form Login'
Private Sub admin_cmb_Click()
    Me.Hide
    admin_login.Show
End Sub

'------------------------------------
'Code cho nút Cancel trên form admiin_login'
Private Sub CommandButton2_Click()
Me.Hide
Login.Show
End Sub
 
Tôi thấy file cũ bạn chạy bình thường, không lỗi.
Mà ý đồ bạn muốn thiết kế như thế nào mà lại có thêm nút Admin trên form Login? Hiếm thấy... :)

Mã:
'Code cho nút Admin tren form Login'
Private Sub admin_cmb_Click()
    Me.Hide
    admin_login.Show
End Sub

'------------------------------------
'Code cho nút Cancel trên form admiin_login'
Private Sub CommandButton2_Click()
Me.Hide
Login.Show
End Sub
Chào bác ạ, em muốn lấy cái list vào combo box từ cột M, từ M5 đến M*, M* là vì khi thêm mới dữ liệu ở cột M thì số dòng có dữ liệu sẽ thay đổi.
Em muốn khi có dữ liệu mới nó sẽ load vào combo box dựa vào tìm dòng cuối.
Nhưng khi viết đoạn load từ cột M vào combo box thì bị lỗi.
Bác xem code sai ở đâu hộ e với ạ + viết sao cho đúng ạ.
Mã:
Private sub userform_initialize()
Dim dong_cuoi as long
dong_cuoi = sheet2.cells(rows.count, “m”).end(xlup).row+1
dvql_cbb.list = sheet2.range(“m5:m&dong_cuoi”).value
End sub
Bác thông cảm, nhà em mất mạng, up ảnh chụp bằng điện thoại thì báo lỗi dung lượng lớn.
Của em là có 1 combo box tên là : dvql_cbb
Em muốn lấy dữ liệu trên sheet2 cột M bắt đầu từ M5 đến M dòng cuối cùng có dữ liệu.
Em cảm ơn!
 
Chào bác ạ, em muốn lấy cái list vào combo box từ cột M, từ M5 đến M*, M* là vì khi thêm mới dữ liệu ở cột M thì số dòng có dữ liệu sẽ thay đổi.
Em muốn khi có dữ liệu mới nó sẽ load vào combo box dựa vào tìm dòng cuối.
Nhưng khi viết đoạn load từ cột M vào combo box thì bị lỗi.
Bác xem code sai ở đâu hộ e với ạ + viết sao cho đúng ạ.
Mã:
Private sub userform_initialize()
Dim dong_cuoi as long
dong_cuoi = sheet2.cells(rows.count, “m”).end(xlup).row+1
dvql_cbb.list = sheet2.range(“m5:m&dong_cuoi”).value
End sub
Bác thông cảm, nhà em mất mạng, up ảnh chụp bằng điện thoại thì báo lỗi dung lượng lớn.
Của em là có 1 combo box tên là : dvql_cbb
Em muốn lấy dữ liệu trên sheet2 cột M bắt đầu từ M5 đến M dòng cuối cùng có dữ liệu.
Em cảm ơn!

Tôi cũng mới làm quen với VBA Excel thôi bạn à nên còn nhiều cái chưa nắm rõ nhé bạn, cũng thuộc dạng nhập môn thôi :) , chưa sạch nước cản đó.
Về cái Range động để gán cho source của Combobox như bạn đề cập, tôi nghĩ nên đổi thành Table sẽ hiệu quả hơn. Tài liệu của MS cũng khuyến cáo vậy.
Để khai báo Range động thì có thể dùng hàm OFFSET hoặc như kiểu bạn đang làm:
= OFFSET(Sheet2!$M$5,0,0,COUNTA(Sheet2!$M:$M),1)
= "Info!$M$5:M" & Sheet2.Range("M" & Rows.Count).End(xlUp).Row

Trong cách khai báo Range ở trên có lồng các hàm CountA, Count nó sẽ thực hiện việc điếm nhiều dòng trong range do đó sẽ ảnh hưởng đến tốc độ thực thi khi cái range có số lượng dòng lớn. Dùng Range có cái lợi là có thể viết cho phiên bản Excel 2003. Dùng Table thì phải Excel 2007 trở lên mới hỗ trợ.
Form của bạn sửa lại:
- Tạo Table cho cái range có cột M, đặt tên ví dụ như: "UserLevelRange"
- Sự kiện UserForm_Initialize():
Me.dvql_cbb.RowSource = "UserLevelRange"
 
Tôi cũng mới làm quen với VBA Excel thôi bạn à nên còn nhiều cái chưa nắm rõ nhé bạn, cũng thuộc dạng nhập môn thôi :) , chưa sạch nước cản đó.
Về cái Range động để gán cho source của Combobox như bạn đề cập, tôi nghĩ nên đổi thành Table sẽ hiệu quả hơn. Tài liệu của MS cũng khuyến cáo vậy.
Để khai báo Range động thì có thể dùng hàm OFFSET hoặc như kiểu bạn đang làm:
= OFFSET(Sheet2!$M$5,0,0,COUNTA(Sheet2!$M:$M),1)
= "Info!$M$5:M" & Sheet2.Range("M" & Rows.Count).End(xlUp).Row

Trong cách khai báo Range ở trên có lồng các hàm CountA, Count nó sẽ thực hiện việc điếm nhiều dòng trong range do đó sẽ ảnh hưởng đến tốc độ thực thi khi cái range có số lượng dòng lớn. Dùng Range có cái lợi là có thể viết cho phiên bản Excel 2003. Dùng Table thì phải Excel 2007 trở lên mới hỗ trợ.
Form của bạn sửa lại:
- Tạo Table cho cái range có cột M, đặt tên ví dụ như: "UserLevelRange"
- Sự kiện UserForm_Initialize():
Me.dvql_cbb.RowSource = "UserLevelRange"
Em vẫn chưa hiểu lắm ạ.
Em chỉ cần lấy cái giá trị của List = số phần tử hiện tại trên cột M có giá trị. Vi khi thêm dữ liệu vào cột M thì list của cột M sẽ thay đổi ạ.
Ví dụ dữ liệu đang có từ M5:M10, nhưng khi thêm dữ liệu vào thì list sẽ thành là M5:M12 ạ.
Em làm như của bác hướng dẫn nhưng ko được. Bác cho em hỏi cái "UserLevelRange" là sao bác?
Bài đã được tự động gộp:

Tôi cũng mới làm quen với VBA Excel thôi bạn à nên còn nhiều cái chưa nắm rõ nhé bạn, cũng thuộc dạng nhập môn thôi :) , chưa sạch nước cản đó.
Về cái Range động để gán cho source của Combobox như bạn đề cập, tôi nghĩ nên đổi thành Table sẽ hiệu quả hơn. Tài liệu của MS cũng khuyến cáo vậy.
Để khai báo Range động thì có thể dùng hàm OFFSET hoặc như kiểu bạn đang làm:
= OFFSET(Sheet2!$M$5,0,0,COUNTA(Sheet2!$M:$M),1)
= "Info!$M$5:M" & Sheet2.Range("M" & Rows.Count).End(xlUp).Row

Trong cách khai báo Range ở trên có lồng các hàm CountA, Count nó sẽ thực hiện việc điếm nhiều dòng trong range do đó sẽ ảnh hưởng đến tốc độ thực thi khi cái range có số lượng dòng lớn. Dùng Range có cái lợi là có thể viết cho phiên bản Excel 2003. Dùng Table thì phải Excel 2007 trở lên mới hỗ trợ.
Form của bạn sửa lại:
- Tạo Table cho cái range có cột M, đặt tên ví dụ như: "UserLevelRange"
- Sự kiện UserForm_Initialize():
Me.dvql_cbb.RowSource = "UserLevelRange"
Chào bác, em vừa tìm được trên mạng đoạn code đơn giản như này, em vừa check thấy ok bác ạ
Mã:
Private Sub userform_initialize()
With Sheet2
    Me.dvql_cbb.List = .Range("m5", .Range("M" & .Rows.Count).End(xlUp)).Value
End With
End Sub
 
Lần chỉnh sửa cuối:
Em làm như của bác hướng dẫn nhưng ko được. Bác cho em hỏi cái "UserLevelRange" là sao bác?
Bài đã được tự động gộp:


Chào bác, em vừa tìm được trên mạng đoạn code đơn giản như này, em vừa check thấy ok bác ạ
Mã:
Private Sub userform_initialize()
With Sheet2
    Me.dvql_cbb.List = .Range("m5", .Range("M" & .Rows.Count).End(xlUp)).Value
End With
End Sub

Bạn nên ngâm cứu về Table và Name Range trong Excel đi nhé, sử dụng nó tiện lắm đó. Cái "UserLevelRange" là cái tên tự đặt cho cái Table chứa cột dữ liệu từ M5 đến dòng cuối có dữ liệu đó. Muốn đặt tên gì dễ nhớ, dễ hiểu để dễ gọi trong code.
Thay vì bạn dùng:
Me.dvql_cbb.List = .Range("m5", .Range("M" & .Rows.Count).End(xlUp)).Value

Thì tôi dùng: gọn hơn và kết quả như nhau nhưng về mặt tốc độ thì chắc chắn nhanh hơn.
Me.dvql_cbb.RowSource = "UserLevelRange"
Cách dùng này dễ bảo trì, sửa code hơn. Ví dụ: sau này bạn thay đổi địa chỉ ô M5 sang vị trí khác thì phải vô sửa code. Còn dùng Tên Table như cách của tôi thì khi bạn thay đổi địa chỉ khai báo cho cái table đó thì không cần đổi code miễn là cái tên Table ("UserLevelRange")không đổi là vẫn chạy được.
 
Bạn nên ngâm cứu về Table và Name Range trong Excel đi nhé, sử dụng nó tiện lắm đó. Cái "UserLevelRange" là cái tên tự đặt cho cái Table chứa cột dữ liệu từ M5 đến dòng cuối có dữ liệu đó. Muốn đặt tên gì dễ nhớ, dễ hiểu để dễ gọi trong code.
Thay vì bạn dùng:
Me.dvql_cbb.List = .Range("m5", .Range("M" & .Rows.Count).End(xlUp)).Value

Thì tôi dùng: gọn hơn và kết quả như nhau nhưng về mặt tốc độ thì chắc chắn nhanh hơn.
Me.dvql_cbb.RowSource = "UserLevelRange"
Cách dùng này dễ bảo trì, sửa code hơn. Ví dụ: sau này bạn thay đổi địa chỉ ô M5 sang vị trí khác thì phải vô sửa code. Còn dùng Tên Table như cách của tôi thì khi bạn thay đổi địa chỉ khai báo cho cái table đó thì không cần đổi code miễn là cái tên Table ("UserLevelRange")không đổi là vẫn chạy được.
Bác qua đây tư vấn giúp e về code load Chart với ạ.
 

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

Back
Top Bottom