2008-10-07 82 views
19

Có cách nào để bắt một nhấp chuột lên một ô trong VBA bằng Excel không? Tôi không đề cập đến sự kiện Worksheet_SelectionChange, vì điều đó sẽ không kích hoạt nhiều lần nếu ô được nhấp nhiều lần. BeforeDoubleClick không giải quyết được sự cố của tôi, vì tôi không muốn yêu cầu người dùng nhấp đúp vào điều đó một cách thường xuyên.OnClick trong Excel VBA

Giải pháp hiện tại của tôi không hoạt động với sự kiện SelectionChange, nhưng dường như yêu cầu sử dụng biến toàn cầu và thực tiễn mã hóa tối ưu khác. Nó cũng có vẻ dễ bị lỗi.

Trả lời

18

Rõ ràng, không có câu trả lời hoàn hảo.Tuy nhiên, nếu bạn muốn cho phép người sử dụng để

  1. chọn tế bào nhất định
  2. cho phép họ thay đổi những tế bào, và
  3. bẫy mỗi nhấp chuột, nhấp chuột thậm chí lặp đi lặp lại trên cùng một tế bào,

thì cách dễ nhất có vẻ là di chuyển tiêu điểm ra khỏi ô đã chọn, để nhấp vào nó sẽ kích hoạt sự kiện Chọn.

Một tùy chọn là di chuyển tiêu điểm như tôi đã đề xuất ở trên, nhưng điều này ngăn việc chỉnh sửa ô. Một tùy chọn khác là mở rộng lựa chọn bằng một ô (trái/phải/lên/xuống), bởi vì điều này cho phép chỉnh sửa ô ban đầu, nhưng sẽ kích hoạt sự kiện Chọn nếu ô đó được bấm lần nữa.

Nếu bạn chỉ muốn bẫy lựa chọn một cột ô, bạn có thể chèn cột bị ẩn ở bên phải, mở rộng lựa chọn để bao gồm ô ẩn ở bên phải khi người dùng nhấp vào và điều này cho phép bạn chỉnh sửa ô có thể bị bẫy mỗi khi được nhấp. Mã này là như sau

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    'prevent Select event triggering again when we extend the selection below 
    Application.EnableEvents = False 
    Target.Resize(1, 2).Select 
    Application.EnableEvents = True 
End Sub 
+0

Hoàn hảo, cảm ơn :) – haslo

0

Tôi không nghĩ vậy. Nhưng bạn có thể tạo một đối tượng hình dạng (hoặc wordart hoặc một cái gì đó tương tự) móc Nhấp vào sự kiện và đặt đối tượng đến vị trí của ô được chỉ định.

+0

Hm, rắc rối với điều đó là tôi muốn bắt lấy ô của nó, và có một số dòng tùy ý mà tôi muốn bắt nó, cùng với dòng mà nó bị bắt vào (SelectionChange đưa cho tôi một phạm vi đẹp cho rằng) ... – haslo

+0

Và người dùng cũng có thể dễ dàng chỉnh sửa trang tính, chẳng hạn như "bạn sẽ phải nhấp vào nút này, nếu bạn thêm một dòng mới bằng tay, nó sẽ không hoạt động". Nhưng tôi khá chắc chắn có thực sự không có cách nào (VBA không ngạc nhiên tôi một lần nữa), tôi cũng có thể chính thức chấp nhận câu trả lời của bạn ... – haslo

1

Lựa chọnThay đổi là sự kiện được tích hợp vào mô hình Đối tượng Excel cho việc này. Nó phải làm chính xác như bạn muốn, kích hoạt bất cứ lúc nào người dùng nhấp vào bất cứ nơi nào ...

Tôi không chắc chắn rằng tôi hiểu phản đối của bạn về biến toàn cầu ở đây, bạn sẽ chỉ cần 1 nếu bạn sử dụng sự kiện Application.SelectionChange . Tuy nhiên, bạn sẽ không cần bất kỳ điều gì nếu bạn sử dụng mã lớp Workbook phía sau (để bẫy sự kiện Workbook.SelectionChange) hoặc mã lớp Worksheet phía sau (để bẫy sự kiện Worksheet.SelectionChange). (Trừ khi vấn đề của bạn là vấn đề "khôi phục toàn cầu biến" trong VBA, mà chỉ có một giải pháp: xử lý lỗi ở mọi nơi. Không cho phép bất kỳ lỗi nào bị lỗi, thay vào đó hãy ghi nhật ký và/hoặc "báo cáo mềm" cho người dùng.)

Bạn cũng có thể cần phải nắm bắt các sự kiện Worksheet.Activate() và Worksheet.Deactivate() (hoặc tương đương trong lớp Workbook) và/hoặc Workbook.Activate và Workbook.Deactivate () sự kiện để bạn biết khi nào người dùng đã chuyển đổi trang tính và/hoặc sổ làm việc. Cửa sổ kích hoạt và hủy kích hoạt sự kiện sẽ làm cho phương pháp này hoàn tất. Tất cả họ đều có thể gọi cùng một quy trình chính xác, tuy nhiên, tất cả đều biểu thị cùng một điều: người dùng đã thay đổi "tiêu điểm", nếu bạn muốn.

Nếu bạn không thích VBA, btw, bạn có thể làm tương tự bằng VB.NET hoặc C#.

[Chỉnh sửa: Dbb thực hiện một điểm rất tốt về sự kiện SelectionChange không nhận được nhấp chuột khi người dùng nhấp vào trong ô hiện được chọn. Nếu bạn cần phải chọn nó, thì bạn sẽ cần phải sử dụng phân lớp.]

+0

Biến toàn cầu chỉ là xấu xí, đó là tất cả :) Lý do tại sao tôi sử dụng một ở đây đặc biệt là vì tôi cũng đã thay đổi trang tính trong quá trình xử lý sự kiện, sao chép các hàng dán vào một trang tính khác. Nó thực sự chỉ là một ứng dụng nhỏ, VB.NET hoặc C# (trong khi tôi thích chúng tốt hơn rất nhiều) là một chút trên đầu trang. – haslo

+0

Ngoài ra, thông tin chi tiết rất tốt, cảm ơn! – haslo

5

Để bẫy các lần nhấp lặp lại trên cùng một ô, bạn cần di chuyển tiêu điểm đến ô khác, để mỗi lần bạn bấm , thực ra bạn đang di chuyển vùng chọn.

Mã bên dưới sẽ chọn ô trên cùng bên trái hiển thị trên màn hình, khi bạn nhấp vào bất kỳ ô nào. Rõ ràng, nó có lỗ hổng mà nó sẽ không bẫy một nhấp chuột vào ô trên cùng bên trái, nhưng điều đó có thể được quản lý (ví dụ bằng cách chọn ô trên cùng bên phải nếu activecell ở trên cùng bên trái).

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    'put your code here to process the selection, then.. 
    ActiveWindow.VisibleRange.Cells(1, 1).Select 
End Sub 
+1

Đây là một ý tưởng rất hay, nếu tất cả những gì bạn cần làm là nhận các nhấp chuột. Nhưng nếu người dùng cũng cần có khả năng chỉnh sửa giá trị ô, v.v. thì điều này sẽ không thể thực hiện được. (Ngay cả khi không, nó có thể là v. Khó hiểu.) Điểm tuyệt vời về SelectionChange không chọn lên một "cùng một tế bào" nhấp chuột, tuy nhiên; Tôi bỏ lỡ điều đó. –

0

này đã làm việc cho tôi .....

Private Sub Worksheet_Change(ByVal Target As Range) 

    If Mid(Target.Address, 3, 1) = "$" And Mid(Target.Address, 2, 1) < "E" Then 
     ' The logic in the if condition will filter for a specific cell or block of cells 
     Application.ScreenUpdating = False 
     'MsgBox "You just changed " & Target.Address 

     'all conditions are true .... DO THE FUNCTION NEEDED 
     Application.ScreenUpdating = True 
    End If 
    ' if clicked cell is not in the range then do nothing (if condttion is not run) 
End Sub 

Chú ý: chức năng này trong thực tế sử dụng tính lại một bảng pivot nếu người dùng thêm một mục trong một phạm vi dữ liệu từ A4 đến D500. Có các phần được bảo vệ và không được bảo vệ trong trang tính để kiểm tra thực tế cho nhấp chuột là nếu cột ít hơn "E" Logic có thể phức tạp như bạn muốn bao gồm hoặc loại trừ bất kỳ số lượng nào của khu vực

block1 = row > 3 and row < 5 and column column >"b" and < "d" 
block2 = row > 7 and row < 12 and column column >"b" and < "d" 
block3 = row > 10 and row < 15 and column column >"e" and < "g" 

If block1 or block2 or block 3 then 
    do function ..... 
end if