Tạo menu popup trong EXCEL (1 người xem)

Liên hệ QC

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

kieunhu91

Thành viên mới
Tham gia
7/3/11
Bài viết
15
Được thích
0
Em tìm được bài viết này:
http://dongkhoibentre.com/forum/showthread.php?124-T%E1%BA%A1o-menu-popup-trong-excel
Từ bài viết này có thể biến đổi đi một chút để gọi hàm macro. Giả sử click vào trong popupmenu, chọn thẻ control 1 thì thực thi gọi hàm sub main ()

Nhưng hạn chế của bài viết này là: sẽ không sử dụng được popup của excel như thông thường nữa, các chức năng copy, paste,... sẽ bị mất đi, muốn dùng phải sử dụng phím tắt, khá bất tiện.

Vì vậy, ai có thể giúp em:
-Hoặc là sửa lại code, click chuột phải vào cell A1 thì hiện ra popup menu của mình, ngoài ra ở những chỗ khác thì vẫn là popup menu mặc định của excel
-Hoặc là, thêm vào popup menu mặc định của excel, ngoài các chức năng như copy, paste,... còn có thêm như là control 1, khi click vào đó sẽ gọi hàm sub main () của mình.

Em cảm ơn mọi người nhiều.
 
Em tìm được bài viết này:
http://dongkhoibentre.com/forum/showthread.php?124-Tạo-menu-popup-trong-excel
Từ bài viết này có thể biến đổi đi một chút để gọi hàm macro. Giả sử click vào trong popupmenu, chọn thẻ control 1 thì thực thi gọi hàm sub main ()

Nhưng hạn chế của bài viết này là: sẽ không sử dụng được popup của excel như thông thường nữa, các chức năng copy, paste,... sẽ bị mất đi, muốn dùng phải sử dụng phím tắt, khá bất tiện.

Vì vậy, ai có thể giúp em:
-Hoặc là sửa lại code, click chuột phải vào cell A1 thì hiện ra popup menu của mình, ngoài ra ở những chỗ khác thì vẫn là popup menu mặc định của excel
-Hoặc là, thêm vào popup menu mặc định của excel, ngoài các chức năng như copy, paste,... còn có thêm như là control 1, khi click vào đó sẽ gọi hàm sub main () của mình.

Em cảm ơn mọi người nhiều.
Tặng bạn 1 bộ 4 file tạo popup menu từ đơn giản đến phức tạp do tôi tự làm (khá đơn giản) ---> Các chức năng Cut, Copy, Paste... vẫn hoạt động bình thường
 

File đính kèm

Upvote 0
Rất hay, nhưng mình xin hỏi thêm:
Khi dùng sự kiện: Worksheet_Deactivate nếu trong chương trình (code) có vòng lặp di chuyển qua lại giữa các sheet để tham chiếu thì có ảnh hưởng nhiều đến tốc độ không? Có thể vô hiệu hóa sự kiện này giống như đối với sự kiện Worksheet_Change được không?
 
Upvote 0
Rất hay, nhưng mình xin hỏi thêm:
Khi dùng sự kiện: Worksheet_Deactivate nếu trong chương trình (code) có vòng lặp di chuyển qua lại giữa các sheet để tham chiếu thì có ảnh hưởng nhiều đến tốc độ không? Có thể vô hiệu hóa sự kiện này giống như đối với sự kiện Worksheet_Change được không?
Câu trả lời hay nhất cho vấn đề này không gì bằng thí nghiệm anh à
--------------
Vô hiệu hóa là sao? Em chưa hiểu ---> Anh không xài 1 sự kiện là xem như VÔ HIỆU HÓA sự kiện đó rồi
 
Upvote 0
Góp vui 1 chút, để có thể test dễ hơn ta sửa 1 chút File số 1:

1/Sửa:

Private Sub BuildPopupMenu()
With Application.CommandBars("Cell").Controls.Add(1, , , 1)
.Caption = "My Macro 1"
.OnAction = "Test1"
End With
MsgBox "Hello!Co toi"
End Sub
Private Sub ResetPopupMenu()
Application.CommandBars("Cell").Reset
MsgBox "Hi!Chao nha!"
End Sub

2/ Thêm:

Sub GPE()
Sheet1.Activate
Sheet2.Activate
Sheet1.Activate
Sheet2.Activate
End Sub

Sub GPE1()
Application.EnableEvents = False
Sheet1.Activate
Sheet2.Activate
Sheet1.Activate
Sheet2.Activate
Application.EnableEvents = True
End Sub


Giờ bạn chạy thử 2 code thêm sẽ có khá nhiều đáp án cho câu hỏi của bạn Thanh Lanh
 
Upvote 0
Vậy mình xin sửa lại file1 của ndu như sau:
1. Trong sheet
Mã:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
  If Not Intersect(Range("A1:A10"), Target) Is Nothing Then
    Run ("ResetPopupMenu"): Run ("BuildPopupMenu")
  Else
    Run ("ResetPopupMenu")
  End If
End Sub
Private Sub Worksheet_Deactivate()
  Run ("ResetPopupMenu")
End Sub
Thay bằng:
Mã:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    Application.CommandBars("Cell").Reset
    If Not Intersect(Range("A1:A10"), Target) Is Nothing Then
        Run ("BuildPopupMenu")
    End If
End Sub
2. Trong Workbook
Mã:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
  Run ("ResetPopupMenu")
End Sub
Private Sub Workbook_Deactivate()
  Run ("ResetPopupMenu")
End Sub
Mình bỏ luôn

3. Trong Module
Mã:
Private Sub BuildPopupMenu()
  With Application.CommandBars("Cell").Controls.Add(1, , , 1)
    .Caption = "My Macro 1"
    .OnAction = "Test1"
  End With
End Sub
Private Sub ResetPopupMenu()
  Application.CommandBars("Cell").Reset
End Sub
Private Sub Test1()
  MsgBox "Test Popup menu"
End Sub
Sửa thành:
Mã:
Private Sub BuildPopupMenu()
  With Application.CommandBars("Cell").Controls.Add(1, , , 1)
    .Caption = "My Macro 1"
    .OnAction = "Test1"
  End With
End Sub
Private Sub Test1()
  MsgBox "Test Popup menu"
End Sub

Khỏi dùng đến sự kiện Workbook_Deactivate
Được không?
 

File đính kèm

Upvote 0
Khỏi dùng đến sự kiện Workbook_Deactivate
Được không?
Cái này là tùy theo nhu cầu anh à!
Có trường hợp người ta muốn popup menu chỉ hoạt động tại Sheet1 mà không hoạt động ở sheet khác đồng thời cũng không hoạt động trên những Workbook khác ---> Khi ấy anh vẫn buộc phải dùng sự kiện Deactivate thôi
Nếu không reset mọi thứ trở về nguyên mẫu thì khi xây dựng phần mềm, những hoạt động lung lung của nó sẽ khiến cho người ta ghét (tôi chỉ xài trong file này mà sao cái menu nó chứ nằm chình ình ở mọi nơi chứ)
Vậy nên code của em sẽ:
- Làm việc trong 1 phạm vi hạn chế
- Không có tác dụng không những nơi khác
- Khi workbook đóng lại, trả mọi thứ về trạng thái nguyên thủy

Ẹc... Ẹc... (cơ bản)
 
Lần chỉnh sửa cuối:
Upvote 0
- Làm việc trong 1 phạm vi hạn chế
- Không có tác dụng không những nơi khác
Thì mình đã Reset:
Mã:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    [B][COLOR=red]Application.CommandBars("Cell").Reset[/COLOR][/B]
    If Not Intersect(Range("A1:A10"), Target) Is Nothing Then
        Run ("BuildPopupMenu")
    End If
End Sub
Còn
Khi workbook đóng lại, trả mọi thứ về trạng thái nguyên thủy
Mình cho popup menu về nguyên thủy khi kết thúc lệnh
Mã:
Private Sub Test1()
  MsgBox "Test Popup menu"
  [COLOR=red][B]Application.CommandBars("Cell").Reset[/B][/COLOR]
End Sub
Ẹc... Ẹc... ' (Nhái)
 
Upvote 0
Thì mình đã Reset:
Mã:
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    [B][COLOR=red]Application.CommandBars("Cell").Reset[/COLOR][/B]
    If Not Intersect(Range("A1:A10"), Target) Is Nothing Then
        Run ("BuildPopupMenu")
    End If
End Sub
Còn

Mình cho popup menu về nguyên thủy khi kết thúc lệnh
Mã:
Private Sub Test1()
  MsgBox "Test Popup menu"
  [COLOR=red][B]Application.CommandBars("Cell").Reset[/B][/COLOR]
End Sub
Ẹc... Ẹc... ' (Nhái)
Anh mở file của anh lên rồi chuyển sang sheet2 xem ---> Cái popup vẫn còn hoạt động đây... Tiếp theo, khi anh đóng file của anh lại rồi mở 1 workbook khác (thậm chí là 1 Wb trắng), cái popup ấy vẫn còn chình ình
Chỉ khi anh xài xong rồi thì nó mới reset --> Vậy sao được ---> Cái này là "ép" hành khách ăn cơm quán mình đây, nếu không sẽ không cho "ra cổng" (cơm tù) ... Ẹc... Ẹc...
 
Lần chỉnh sửa cuối:
Upvote 0
Em thấy cách giải quyết như của anh ndu96081631 là hợp lý nhất, các sheet phía sau không bị ảnh hưởng.
em muốn hỏi một chút về code ạ:
Mã:
With Application.CommandBars("cell").Controls.Add(10, , , 1)
em không hiểu số 10 và số 1 ở trên có ý nghĩa là gì, ngoài ra phần khoảng trống giữa hai dấu phẩy có ý nghĩa gì, anh có thể giải thích giúp em với được không ạ ^^
Em cảm ơn anh.
 
Upvote 0
Để hiểu thì bạn cứ thay các số vào sẽ biết thôi
 
Upvote 0
Em thấy cách giải quyết như của anh ndu96081631 là hợp lý nhất, các sheet phía sau không bị ảnh hưởng.
em muốn hỏi một chút về code ạ:
Mã:
With Application.CommandBars("cell").Controls.Add(10, , , 1)
em không hiểu số 10 và số 1 ở trên có ý nghĩa là gì, ngoài ra phần khoảng trống giữa hai dấu phẩy có ý nghĩa gì, anh có thể giải thích giúp em với được không ạ ^^
Em cảm ơn anh.
Gữi nguyên văn trong help cho bạn tham khảo
1> Phương thức Add CommandBar

untitled1.JPG

2> Kiểu Control được liệt kê dưới đây

untitled2.JPG

Vậy số 10 chính là Type, tương đuong với hằng số msoControlPopup và số 1 là Temporary, có nghĩa là TRUE ---> Mục đích tạo 1 popup tạm, chỉ có tác dụng khi ta xài, còn khi đóng file lại thì cái control vừa tạo sẽ được xóa đi
Thay đổi Type thành số khác (từ 1 đến 25) sẽ thấy khác biệt
Nói tóm lại: Mọi thứ đều có trong Help của Excel VBA
 
Lần chỉnh sửa cuối:
Upvote 0
Popup menu trên UserForm

Nhân tiên nói về Popup, xin tặng các bạn 1 popup trên UserForm đây (nghe lạ nha)
Code như sau:
1> Code trong UserForm
PHP:
Private Sub UserForm_Initialize()
  On Error Resume Next
  With CommandBars.Add("ufPopup", 5).Controls.Add(1)
    .Caption = "THÔNG BÁO"
    .OnAction = "Test"
  End With
End Sub
PHP:
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
  If Button = 2 Then CommandBars("ufPopup").ShowPopup
End Sub
2> Code trong Module
PHP:
Sub Test()
  MsgBox "Day la menu chuot phai tren Form"
End Sub
Mở form, click chuột phải trên form xem có hấp dẫn không?
----------------------
Và cũng nhân đây, đố các bạn biết có điều gì chưa ổn trong code này? Ẹc... Ẹc...
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Có phải là không thể Unload UserForm1 được nếu không có dòng On Error Resume Next ở đầu sự kiện UserForm_Initialize?
Em gợi ý tình huống thế này:
- Lần đâu tiên anh chạy file trên, đừng vội khởi động UserForm, hãy Alt + F11 vào bỏ dòng On Error Resume Next
- Khởi động UserForm, mọi chuyện suôn sẻ
- Thoát UserForm và khởi động lần nữa ---> Báo lỗi
- Đóng file lại, mở 1 Wb trắng, chèn 1 Module với nội dung
PHP:
Sub Test()
 CommandBars("ufPopup").ShowPopup
End Sub
Sẽ thấy cái popup này hoạt động ngay trên 1 wb mới tinh
===> Tại sao có 2 hiện tượng trên? Cách khắc phục?
 
Upvote 0
Em gợi ý tình huống thế này:
- Lần đâu tiên anh chạy file trên, đừng vội khởi động UserForm, hãy Alt + F11 vào bỏ dòng On Error Resume Next
- Khởi động UserForm, mọi chuyện suôn sẻ
- Thoát UserForm và khởi động lần nữa ---> Báo lỗi
- Đóng file lại, mở 1 Wb trắng, chèn 1 Module với nội dung
PHP:
Sub Test()
CommandBars("ufPopup").ShowPopup
End Sub
Sẽ thấy cái popup này hoạt động ngay trên 1 wb mới tinh
===> Tại sao có 2 hiện tượng trên? Cách khắc phục?

Nguyên nhân: Tại cái "ufPopup" đã tồn tại
Khắc phục: "Giết nhầm hơn bỏ sót"
Trong Form sủa lại:
Mã:
Private Sub UserForm_Initialize()
  'On Error Resume Next [COLOR=darkorange]'Bo đi[/COLOR]
Run ("DeletePUp") [COLOR=darkorange]'Thêm[/COLOR]
With CommandBars.Add("ufPopup", 5).Controls.Add(1)
            .Caption = "THÔNG BÁO"
            .OnAction = "Test"
End With
End Sub
Trong module thêm:
Mã:
Sub DeletePUp() [COLOR=darkorange]' Tà đạo[/COLOR]
Dim cb As CommandBar
For Each cb In CommandBars
    If cb.Name = "ufPopup" Then
          Application.CommandBars("ufPopup").Delete
    End If
Next cb
End Sub
Trong Workbook thêm
Mã:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Run ("DeletePUp")
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Run ("DeletePUp")
End Sub
 
Upvote 0
Nguyên nhân: Tại cái "ufPopup" đã tồn tại
Khắc phục: "Giết nhầm hơn bỏ sót"
Trong Form sủa lại:
Mã:
Private Sub UserForm_Initialize()
  'On Error Resume Next [COLOR=darkorange]'Bo đi[/COLOR]
Run ("DeletePUp") [COLOR=darkorange]'Thêm[/COLOR]
With CommandBars.Add("ufPopup", 5).Controls.Add(1)
            .Caption = "THÔNG BÁO"
            .OnAction = "Test"
End With
End Sub
Trong module thêm:
Mã:
Sub DeletePUp() [COLOR=darkorange]' Tà đạo[/COLOR]
Dim cb As CommandBar
For Each cb In CommandBars
    If cb.Name = "ufPopup" Then
          Application.CommandBars("ufPopup").Delete
    End If
Next cb
End Sub
Trong Workbook thêm
Mã:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Run ("DeletePUp")
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Run ("DeletePUp")
End Sub
Anh có thể rút gọn thế này:
PHP:
Private Sub UserForm_Initialize()
  With CommandBars.Add("ufPopup", 5, , 1).Controls.Add(1, , , , 1)
    .Caption = "THÔNG BÁO"
    .OnAction = "Test"
    .Enabled = True
  End With
End Sub
PHP:
Private Sub UserForm_Terminate()
  CommandBars("ufPopup").Delete
End Sub

Chỉ cần xóa thằng ufPopup khi UserForm đóng lại. Không cần luôn sự kiện BeforeClose vì em tạo Popup dạng Temporary

Mã:
CommandBars.Add("ufPopup", 5, , [COLOR=red][B]1[/B][/COLOR]).Controls.Add(1, , , , [COLOR=red][B]1[/B][/COLOR])
---> Khi đóng file, popup sẽ tự xóa
Và nếu an toàn hơn 1 chút thì vầy:
PHP:
Private Sub UserForm_Initialize()
  On Error Resume Next
  CommandBars("ufPopup").Delete
  With CommandBars.Add("ufPopup", 5, , 1).Controls.Add(1, , , , 1)
    .Caption = "THÔNG BÁO"
    .OnAction = "Test"
    .Enabled = True
  End With
End Sub
PHP:
Private Sub UserForm_Terminate()
  CommandBars("ufPopup").Delete
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Anh có thể rút gọn thế này:
PHP:
Private Sub UserForm_Initialize()
With CommandBars.Add("ufPopup", 5, , 1).Controls.Add(1, , , , 1)
.Caption = "THÔNG BÁO"
.OnAction = "Test"
.Enabled = True
End With
End Sub
PHP:
Private Sub UserForm_Terminate()
CommandBars("ufPopup").Delete
End Sub

Chỉ cần xóa thằng ufPopup khi UserForm đóng lại. Không cần luôn sự kiện BeforeClose vì em tạo Popup dạng Temporary

Mã:
CommandBars.Add("ufPopup", 5, , [COLOR=red][B]1[/B][/COLOR]).Controls.Add(1, , , , [COLOR=red][B]1[/B][/COLOR])
---> Khi đóng file, popup sẽ tự xóa
Và nếu an toàn hơn 1 chút thì vầy:
PHP:
Private Sub UserForm_Initialize()
On Error Resume Next
CommandBars("ufPopup").Delete
With CommandBars.Add("ufPopup", 5, , 1).Controls.Add(1, , , , 1)
.Caption = "THÔNG BÁO"
.OnAction = "Test"
.Enabled = True
End With
End Sub
PHP:
Private Sub UserForm_Terminate()
CommandBars("ufPopup").Delete
End Sub

Nhưng mình rất không thích dùng câu On Error Resume Next nên phải dùng vòng lặp tìm nếu có "ujPopup" thì xóa
 
Upvote 0
Nhưng mình rất không thích dùng câu On Error Resume Next nên phải dùng vòng lặp tìm nếu có "ujPopup" thì xóa
Dạ vâng! Em cũng ít khi thích dùng cái On Error... này... Có điều em sẽ dùng nó khi đã hiểu rõ lỗi có thể phát sinh là cái gì (sẽ đở tốn bao nhiêu đoạn code)
Tóm lại:
- Nếu chưa hiểu được lỗi nào phát sinh thì đừng dùng On Error ---> Mục đích "chờ" lỗi xuất hiện để còn biết đường mà tính
- Nếu đã hiểu được mọi thứ ---> Không có vấn đề gì khi dùng On Error cả

Cũng có trường hợp nếu hổng có nó thì cũng chẳng có cách nào khác để làm cả... Lấy ví dụ code này:
PHP:
Sub Test()
  Dim BlkRng As Range
  Set BlkRng = Sheet1.UsedRange.SpecialCells(4)
  BlkRng.Value = 0
End Sub
Trong vùng dữ liệu, cứ thấy cell nào rổng thì điều số 0 vào
Vậy với 1 sheet trắng tinh (chưa từng nhập liệu bao giờ) thì code sẽ bị lỗi ---> Trường hợp này anh dùng cách gì để vượt qua nếu không dùng On Error... ?
 
Lần chỉnh sửa cuối:
Upvote 0
Cũng có trường hợp nếu hổng có nó thì cũng chẳng có cách nào khác để làm cả... Lấy ví dụ code này:
PHP:
Sub Test()
Dim BlkRng As Range
Set BlkRng = Sheet1.UsedRange.SpecialCells(4)
BlkRng.Value = 0
End Sub
Trong vùng dữ liệu, cứ thấy cell nào rổng thì điều số 0 vào
Vậy với 1 sheet trắng tinh (chưa từng nhập liệu bao giờ) thì code sẽ bị lỗi ---> Trường hợp này anh dùng cách gì để vượt qua nếu không dùng On Error... ?

Được nè:

Mã:
Sub Test()
Dim BlkRng As Range
If UsedRange.Address <> "$A$1" Then
Set BlkRng = Sheet1.UsedRange.SpecialCells(4)
BlkRng.Value = 0
End If
End Sub
Nhưng cảm ơn ndu vì học thêm được 1 từ UsedRange (chưa biết bao giờ)
Như thế này phair dùng On Error:
Mã:
Sub Macro1()
    On Error GoTo thoat
    For i = 1 To 65000
        Range("A" & i).Value = i
        Range("B" & i).Interior.ColorIndex = i
    Next
thoat:
End Sub
 
Upvote 0
Web KT

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

Back
Top Bottom