tự động thực thi macro Excel khi thay đổi ô


91

Làm cách nào để tôi có thể tự động thực thi macro Excel mỗi khi giá trị trong một ô cụ thể thay đổi?

Hiện tại, mã làm việc của tôi là:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub

nơi "H5"được các tế bào đặc biệt được giám sát và Macrolà tên của các vĩ mô.

Có cách nào tốt hơn?


RunMacroWhenValueChanges UDF trong FormulaDesk có đáp ứng yêu cầu của bạn không? formuladesk.com
Gareth Hayter

Câu trả lời:


107

Mã của bạn trông khá tốt.

Tuy nhiên, hãy cẩn thận vì lệnh gọi của bạn đến Range("H5")là một lệnh tắt đến Application.Range("H5"), tương đương với Application.ActiveSheet.Range("H5"). Điều này có thể ổn, nếu những thay đổi duy nhất là do người dùng thay đổi - đó là thay đổi điển hình nhất - nhưng các giá trị ô của trang tính có thể thay đổi khi nó không phải là trang tính hoạt động thông qua các thay đổi có lập trình, ví dụ: VBA.

Với suy nghĩ này, tôi sẽ sử dụng Target.Worksheet.Range("H5"):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub

Hoặc bạn có thể sử dụng Me.Range("H5"), nếu trình xử lý sự kiện nằm trên trang mã cho trang tính được đề cập (thường là):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub

Hi vọng điêu nay co ich...


4
điều gì sẽ xảy ra nếu ô H5được thay đổi từ một trang tính khác, giả sử sheet2 thì chức năng trên không hoạt động. làm ơn giúp đỡ trong này.
dhpratik

2
Đối với bất kỳ ai đến đây từ tìm kiếm trên google, hãy đảm bảo bạn dán mã này vào trang tính trong vba, không phải một mô-đun như tôi đã làm. nhìn vào stackoverflow.com/questions/15337008/…
hammythepig

Application.ActiveSheet.Range ("H5"). ==> target.parent.range ("H5") thậm chí còn an toàn hơn
Pierre

1
@WillEdiger Bất cứ khi nào bạn không chỉ định rõ ràng tham chiếu trang tính, Excel sẽ giả định ActiveSheetvà bất cứ khi nào bạn không chỉ định rõ ràng rằng đó là Excel bạn đang làm việc, Excel sẽ giả định Application.
Scott Marcus

1
Lưu ý rằng, trong một mô-đun mã bảng (đó là nơi mà một Worksheet_Changesự kiện phải được bố trí), một không đủ tiêu chuẩn Rangenào không mặc định ActiveSheetmà thay vào đó đề cập đến tấm chứa mã. Do đó, mã trong câu trả lời này giống với mã trong câu hỏi. : (Lưu ý Trở lại năm 2009 khi câu trả lời này đã được viết, nó có thể đã khác, nhưng tôi khá chắc chắn nó không được.)
YowE3K

7

Xử lý Worksheet_Changesự kiện hoặc Workbook_SheetChangesự kiện.

Các trình xử lý sự kiện nhận đối số "Nhắm mục tiêu theo phạm vi", vì vậy bạn có thể kiểm tra xem phạm vi đang thay đổi có bao gồm ô bạn quan tâm hay không.


Cảm ơn, nó hoạt động. Tôi kiểm tra phạm vi với, nói Target.Address = Range("H5").Address,. Có cách nào dễ hơn không?
namin

Một thay thế: Not (Intersect(Target, Range("H5")) Is Nothing) . Đây có phải là cách bạn sẽ làm điều đó?
namin

2
Nhận xét đầu tiên ( Target.Address = Range("H5").Address) sẽ không hoạt động nếu ô của bạn chỉ là một phần của dải ô đã thay đổi. Nhận xét thứ hai vẫn mắc phải các vấn đề được mô tả bởi Mike Rosenblum.
Ant

5

Tôi đã dành rất nhiều thời gian để nghiên cứu vấn đề này và tìm hiểu cách hoạt động của tất cả, sau khi thực sự làm rối tung các trình kích hoạt sự kiện. Vì có quá nhiều thông tin rải rác, tôi quyết định chia sẻ những gì tôi đã tìm thấy để làm việc tất cả ở một nơi, từng bước như sau:

1) Mở VBA Editor, trong Dự án VBA (YourWorkBookName.xlsm) mở Đối tượng Microsoft Excel và chọn Trang tính mà sự kiện thay đổi sẽ liên quan.

2) Chế độ xem mã mặc định là "Chung". Từ danh sách thả xuống ở giữa trên cùng, hãy chọn "Trang tính".

3) Private Sub Worksheet_SelectionChange đã có sẵn như bình thường, hãy để nó yên. Sao chép / Dán mã của Mike Rosenblum từ bên trên và thay đổi tham chiếu .Range thành ô mà bạn đang xem để thay đổi (trong trường hợp của tôi là B3). Tuy nhiên, chưa đặt Macro của bạn (tôi đã xóa từ "Macro" sau "Sau đó"):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub

hoặc từ danh sách thả xuống ở trên cùng bên trái, chọn "Thay đổi" và trong khoảng trống giữa Sub riêng và Sub kết thúc, hãy dán If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) Trên dòng sau "Sau đó", hãy tắt các sự kiện để khi bạn gọi macro của mình, nó sẽ không kích hoạt các sự kiện và cố gắng chạy lại Worksheet_Change này trong một chu kỳ không bao giờ kết thúc làm hỏng Excel và / hoặc làm mọi thứ rối tung lên:

Application.EnableEvents = False

5) Gọi macro của bạn

Call YourMacroName

6) Bật lại sự kiện để kích hoạt thay đổi tiếp theo (và bất kỳ / tất cả các sự kiện khác):

Application.EnableEvents = True

7) Kết thúc khối If và khối Sub:

    End If
End Sub

Toàn bộ mã:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
        Application.EnableEvents = False
        Call UpdateAndViewOnly
        Application.EnableEvents = True
    End If
End Sub

Điều này giúp bật / tắt các sự kiện khỏi Mô-đun tạo ra sự cố và chỉ cần cho phép trình kích hoạt thay đổi, tắt các sự kiện, chạy macro của bạn và bật lại các sự kiện.


3

Tôi thích cách này hơn, không sử dụng ô mà là một dải ô

    Dim cell_to_test As Range, cells_changed As Range

    Set cells_changed = Target(1, 1)
    Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )

    If Not Intersect(cells_changed, cell_to_test) Is Nothing Then 
       Macro
    End If

Nó giống như một ô. Bạn có thể đặt một phạm vi dưới dạng một ô, phạm vi ô liên tục hoặc thậm chí các ô phân tán (tất cả được phân tách bằng dấu phẩy).
Shai Alon

0

Tôi có một ô được liên kết với cơ sở dữ liệu chứng khoán trực tuyến và được cập nhật thường xuyên. Tôi muốn kích hoạt macro bất cứ khi nào giá trị ô được cập nhật.

Tôi tin rằng điều này tương tự như việc thay đổi giá trị ô bởi một chương trình hoặc bất kỳ bản cập nhật dữ liệu bên ngoài nào nhưng các ví dụ trên bằng cách nào đó không hoạt động với tôi. Tôi nghĩ vấn đề là do các sự kiện nội bộ excel không được kích hoạt, nhưng đó là suy đoán của tôi.

Tôi đã làm như sau,

Private Sub Worksheet_Change(ByVal Target As Range) 
  If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
   'Run Macro
End Sub

1
Tôi không thể làm cho nó hoạt động vì một số lý do. Khi tôi yêu cầu mã chạy trong VBA, nó sẽ xuất hiện một menu bật lên và hỏi tôi liệu tôi có muốn chạy macro thay vì chạy macro automaticaly không?
David Van der Vieren
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.