เรียกใช้แมโคร Excel โดยอัตโนมัติในการเปลี่ยนแปลงเซลล์


91

ฉันจะเรียกใช้แมโคร Excel โดยอัตโนมัติทุกครั้งที่ค่าในเซลล์ใดเซลล์หนึ่งเปลี่ยนแปลงได้อย่างไร

ตอนนี้รหัสการทำงานของฉันคือ:

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

"H5"เซลล์ที่ถูกตรวจสอบอยู่ที่ไหนและMacroเป็นชื่อของมาโคร

มีวิธีที่ดีกว่า?


RunMacroWhenValueChanges UDF ใน FormulaDesk ตรงตามความต้องการของคุณหรือไม่ formuladesk.com
Gareth Hayter

คำตอบ:


108

รหัสของคุณดูดีทีเดียว

อย่างไรก็ตามโปรดระวังสำหรับการโทรของคุณRange("H5")เป็นคำสั่งทางลัดApplication.Range("H5")ซึ่งเทียบเท่ากับApplication.ActiveSheet.Range("H5"). สิ่งนี้อาจใช้ได้ดีหากการเปลี่ยนแปลงเพียงอย่างเดียวคือการเปลี่ยนแปลงของผู้ใช้ซึ่งเป็นเรื่องปกติมากที่สุด แต่เป็นไปได้ที่ค่าเซลล์ของแผ่นงานจะเปลี่ยนแปลงเมื่อไม่ใช่แผ่นงานที่ใช้งานอยู่ผ่านการเปลี่ยนแปลงทางโปรแกรมเช่น VBA

ด้วยเหตุนี้ฉันจะใช้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

หรือคุณสามารถใช้Me.Range("H5")หากตัวจัดการเหตุการณ์อยู่ในหน้ารหัสของแผ่นงานที่เป็นปัญหา (โดยปกติจะเป็น):

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

หวังว่านี่จะช่วยได้ ...


4
จะเกิดอะไรขึ้นถ้าเซลล์H5ถูกเปลี่ยนจากแผ่นงานอื่นแสดงว่าsheet2 ฟังก์ชันข้างต้นไม่ทำงาน โปรดช่วยในเรื่องนี้
dhpratik

2
สำหรับใครก็ตามที่มาที่นี่จากการค้นหาของ Google ตรวจสอบให้แน่ใจว่าคุณได้วางโค้ดนี้ลงในแผ่นงานใน vba ไม่ใช่โมดูลอย่างที่ฉันทำ ดูที่stackoverflow.com/questions/15337008/…
hammythepig

Application.ActiveSheet.Range ("H5") ==> target.parent.range ("H5") ปลอดภัยยิ่งขึ้น
ปิแอร์

1
@WillEdiger เมื่อใดก็ตามที่คุณไม่ได้ระบุอย่างชัดเจนอ้างอิงแผ่น, Excel ถือว่าActiveSheetและเมื่อใดก็ตามที่คุณไม่ได้ระบุอย่างชัดเจนว่ามันเป็น Excel ที่คุณกำลังทำงานกับ Excel Applicationถือว่า
Scott Marcus

1
โปรดทราบว่าในโมดูลโค้ดของเวิร์กชีต(ซึ่งเป็นที่ตั้งของWorksheet_Changeเหตุการณ์) ที่ไม่มีเงื่อนไขRangeไม่ได้เป็นค่าเริ่มต้นActiveSheetแต่หมายถึงแผ่นงานที่มีรหัสแทน ดังนั้นรหัสในคำตอบนี้จึงเหมือนกับรหัสในคำถาม (หมายเหตุ: ย้อนกลับไปในปี 2009 เมื่อมีการเขียนคำตอบนี้อาจแตกต่างออกไป แต่ฉันค่อนข้างมั่นใจว่าไม่ใช่)
YowE3K

7

จัดการกับWorksheet_Changeเหตุการณ์หรือWorkbook_SheetChangeเหตุการณ์

ตัวจัดการเหตุการณ์ใช้อาร์กิวเมนต์ "Target As Range" ดังนั้นคุณสามารถตรวจสอบได้ว่าช่วงที่เปลี่ยนไปมีเซลล์ที่คุณสนใจหรือไม่


ขอบคุณมันได้ผล Target.Address = Range("H5").Addressฉันจะตรวจสอบในช่วงที่มีการพูด, มีวิธีที่ง่ายกว่านี้ไหม?
namin

ทางเลือก: Not (Intersect(Target, Range("H5")) Is Nothing) . นี่เป็นวิธีที่คุณจะทำหรือไม่?
namin

2
ความคิดเห็นแรก ( Target.Address = Range("H5").Address) จะไม่ทำงานหากเซลล์ของคุณเป็นเพียงส่วนหนึ่งของช่วงที่เปลี่ยนแปลง ความคิดเห็นที่สองยังคงประสบปัญหาที่ Mike Rosenblum อธิบายไว้
มด

5

ฉันใช้เวลาค้นคว้าเรื่องนี้นานมากและเรียนรู้วิธีการทำงานทั้งหมดหลังจากที่ทำให้เหตุการณ์เกิดความสับสน เนื่องจากมีข้อมูลกระจัดกระจายมากมายฉันจึงตัดสินใจแบ่งปันสิ่งที่ฉันพบว่าใช้งานได้ทั้งหมดในที่เดียวทีละขั้นตอนดังนี้:

1) เปิด VBA Editor ภายใต้โครงการ VBA (YourWorkBookName.xlsm) เปิดวัตถุ Microsoft Excel และเลือกแผ่นงานที่จะเกี่ยวข้องกับเหตุการณ์การเปลี่ยนแปลง

2) มุมมองโค้ดเริ่มต้นคือ "ทั่วไป" จากรายการแบบเลื่อนลงตรงกลางด้านบนเลือก "แผ่นงาน"

3) Private Sub Worksheet_SelectionChange มีอยู่แล้วตามที่ควรจะเป็นปล่อยไว้คนเดียว คัดลอก / วางรหัสของ Mike Rosenblum จากด้านบนและเปลี่ยนการอ้างอิง. ช่วงไปยังเซลล์ที่คุณกำลังเฝ้าดูการเปลี่ยนแปลง (B3 ในกรณีของฉัน) อย่าวางมาโครของคุณอย่างไรก็ตาม (ฉันลบคำว่า "มาโคร" หลัง "จากนั้น"):

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

หรือจากรายการแบบเลื่อนลงที่ด้านซ้ายบนให้เลือก "เปลี่ยน" และในช่องว่างระหว่าง Private Sub และ End Sub ให้วาง If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) ในบรรทัดหลังจาก "จากนั้น" ปิดเหตุการณ์เพื่อที่เมื่อคุณเรียกใช้มาโครของคุณจะไม่ทำให้เกิดเหตุการณ์และพยายามเรียกใช้ Worksheet_Change นี้อีกครั้งในวงจรที่ไม่สิ้นสุดซึ่งทำให้ Excel ขัดข้องและ / หรือทำให้ทุกอย่างยุ่งเหยิง:

Application.EnableEvents = False

5) เรียกมาโครของคุณ

Call YourMacroName

6) เปิดเหตุการณ์อีกครั้งเพื่อให้การเปลี่ยนแปลงครั้งต่อไป (และเหตุการณ์อื่น ๆ / ทั้งหมด) ทริกเกอร์:

Application.EnableEvents = True

7) สิ้นสุดบล็อก If และ Sub:

    End If
End Sub

รหัสทั้งหมด:

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

สิ่งนี้จะเปิด / ปิดเหตุการณ์ออกจากโมดูลซึ่งสร้างปัญหาและเพียงแค่ให้ทริกเกอร์การเปลี่ยนแปลงปิดเหตุการณ์เรียกใช้แมโครของคุณและเปิดเหตุการณ์อีกครั้ง


3

ฉันชอบวิธีนี้มากกว่าไม่ใช้เซลล์ แต่เป็นช่วง

    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

มันเหมือนกับเซลล์เดียว คุณสามารถตั้งค่าช่วงเป็นเซลล์เดียวช่วงของเซลล์ต่อเนื่องหรือแม้แต่เซลล์ที่กระจัดกระจาย (ทั้งหมดคั่นด้วยลูกน้ำ)
Shai Alon

0

ฉันมีเซลล์ที่เชื่อมโยงกับฐานข้อมูลหุ้นออนไลน์และอัปเดตบ่อยๆ ฉันต้องการเรียกใช้มาโครทุกครั้งที่มีการอัปเดตค่าของเซลล์

ฉันเชื่อว่านี่คล้ายกับการเปลี่ยนแปลงค่าของเซลล์โดยโปรแกรมหรือการอัปเดตข้อมูลภายนอก แต่ตัวอย่างข้างต้นไม่ได้ผลสำหรับฉัน ฉันคิดว่าปัญหาเป็นเพราะเหตุการณ์ภายในของ excel ไม่ได้ถูกเรียก แต่นั่นคือการคาดเดาของฉัน

ฉันทำสิ่งต่อไปนี้

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
ฉันไม่สามารถใช้งานได้ด้วยเหตุผลบางประการ เมื่อฉันบอกให้รหัสทำงานใน VBA มันกำลังดึงเมนูป๊อปอัปขึ้นมาและถามฉันว่าฉันต้องการเรียกใช้แมโครแทนการเรียกใช้มาโครโดยอัตโนมัติหรือไม่?
David Van der Vieren
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.