VBA สำหรับคำสั่ง if -then- else

ด้านล่างนี้เป็นโค้ดที่ฉันคัดลอกค่าจากเซลล์ Q13 และวางลงในคอลัมน์ E จนกว่ารายการจะเสร็จสมบูรณ์ (Q13 จะได้รับการอัปเดตด้วยค่าใหม่ทุกครั้ง) ฉันมีเงื่อนไขที่บอกว่าถ้า Q13 อ่าน "45" ให้คัดลอกค่านั้นและวางลงในคอลัมน์ p ฉันรู้ว่านี่เป็นคำสั่ง if -then- else แต่ฉันได้รับข้อผิดพลาดในการคอมไพล์ที่แตกต่างกันสองสามอย่าง (บล็อกถ้าไม่มีจุดสิ้นสุด if และหากไม่มีการบล็อกถ้า) และตระหนักว่าเป็นไปได้มากว่าไวยากรณ์ของฉัน ถ้ามีใครมารีวิวเรื่องนี้ได้จะสุดยอดมาก

Sub Test()
Dim c As Range
Dim ws As Worksheet: Set ws = Sheet2
Dim range1 As Range: Set range1 = ws.Range("Q13")
Dim Cell As Range

For Each Cell In range1
If Cell.Value = "45" Then
    NextRow = ws.Cells(ws.Rows.Count, "P").End(xlUp).Offset(1, 0).Row
    Cell.Copy ws.Range("P" & NextRow)
    Else
 For Each c In Range("B2:B" & Range("B65536").End(xlUp).Row)
Dim R As Range
Set R = Worksheets("Sheet2").Cells(Rows.Count, "E").End(xlUp) 'last cell in Column E with data
 If Len(R.Value) > 0 Then Set R = R.Offset(1)
R.Value = Worksheets("Sheet2").Range("Q13").Value
Exit For
End If
Next ws
End If

person Jeremie Tomkins    schedule 12.11.2019    source แหล่งที่มา
comment
Google ข้อผิดพลาด :) Next ws เช่น ws ไม่มีการวนซ้ำ   -  person Nathan_Sav    schedule 12.11.2019
comment
ลองใช้ หัวกด เพื่อทำให้โครงสร้างที่ซ้อนกันดู... ซ้อนกัน มันมีแนวโน้มที่จะช่วยในการจัดเรียงจุดเริ่มต้นและจุดสิ้นสุดของบล็อคโค้ด   -  person Mathieu Guindon    schedule 12.11.2019
comment
การเยื้องที่เหมาะสมจะช่วยให้คุณติดตามข้อผิดพลาดทางไวยากรณ์ได้ คำแนะนำ: คุณขาด Next   -  person Brian M Stafford    schedule 12.11.2019
comment
FWIW ไม่จำเป็นต้องมี ws (หรืออะไรก็ตาม) ใน Next ws: แค่ Next ก็เพียงพอแล้ว   -  person Mathieu Guindon    schedule 12.11.2019
comment
@MathieuGuindon - Next ws ไม่ควรโยนข้อผิดพลาดใช่ไหม for loop ที่เริ่มต้นคือ For each Cell...หรือ VBA จะเพิกเฉยต่อสิ่งที่เกิดขึ้นหลังจาก Next จริง ๆ หรือไม่ (โดยทั่วไปฉันจะรวมตัวแปร Next ไว้เสมอ เช่น Next ws / Next Cell ดังนั้นฉันจึงสามารถเห็นได้ทันทีว่าฉันอยู่ในวงใด แต่ไม่เคยคิดจริงๆ ว่า VBA ใช้ข้อมูลนั้นจริงหรือไม่   -  person BruceWayne    schedule 12.11.2019
comment
@BruceWayne ใช่ Next ws เป็นข้อผิดพลาดทางไวยากรณ์เนื่องจาก ws ไม่ใช่ตัวแปรวนซ้ำ ฉันไม่เคยระบุตัวแปรลูปใน Next เพราะหากตัวแปรลูปนั้นมีค่าใดๆ อยู่ที่นั่น แสดงว่าเนื้อความของลูปน่าจะทำหลายสิ่งมากเกินไปและควรปรับโครงสร้างใหม่เป็นขอบเขตขั้นตอนของมันเอง มีตัวแปรลูปเดี่ยวทางวากยสัมพันธ์เพียงตัวเดียวที่ถูกต้องตามกฎหมายทันทีหลังจากโทเค็น Next และนั่นคือตัวแปรลูปสำหรับลูปที่ป้อนครั้งล่าสุด ไวยากรณ์ Next foo นี้มีไว้เพื่อสนับสนุนสิ่งที่น่ารังเกียจอย่างแท้จริงที่ Next foo, bar เป็นเท่านั้น   -  person Mathieu Guindon    schedule 12.11.2019
comment
@MathieuGuindon - ขอบคุณสำหรับสิ่งนั้น! ฉันลังเลที่จะถามว่า Next foo, bar จะเป็นเช่นไร? นั่นเป็นการก่อสร้างที่ถูกต้องใน VBA หรือไม่หากน่ารังเกียจ ...   -  person BruceWayne    schedule 12.11.2019
comment
@บรูซเวย์น For foo = 1 To 10; For bar = 1 To 10; Debug.Print foo, bar; Next foo, bar -- เชื่อหรือไม่ว่าถูกกฎหมาย! (thingsLearnedWhileWorkingOnRubberduck++;)   -  person Mathieu Guindon    schedule 12.11.2019


คำตอบ (1)


อย่าใส่ตัวแปร loop หลังคีย์เวิร์ด Next มันไม่มีประโยชน์ สิ่งเดียวที่ทำได้คือทำให้ VBA ส่งข้อผิดพลาดของคอมไพเลอร์หากคุณใช้ตัวแปรลูปผิด - ดังเช่นกรณีนี้ หากมีโค้ดมากมายในตัว loop body ซึ่งคุณไม่รู้ว่าตัวเองอยู่จุดไหนแล้วเมื่อถึงจุดต่ำสุด แสดงว่า loop body กำลังทำหลายสิ่งมากเกินไป วิธีแก้ไขคือการดึงโค้ดจากตัวลูปไปเป็นขั้นตอนที่เล็กกว่าและเฉพาะทางมากขึ้น

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

Dim c As Range
Dim ws As Worksheet: Set ws = Sheet2
Dim range1 As Range: Set range1 = ws.Range("Q13")
Dim Cell As Range

For Each Cell In range1
|   If Cell.Value = "45" Then
|   |   NextRow = ws.Cells(ws.Rows.Count, "P").End(xlUp).Offset(1, 0).Row
|   |   Cell.Copy ws.Range("P" & NextRow)
|   Else
|   |   For Each c In Range("B2:B" & Range("B65536").End(xlUp).Row)
|   |   |   Dim R As Range
|   \   |   Set R = Worksheets("Sheet2").Cells(Rows.Count, "E").End(xlUp) 'last cell in Column E with data
\   |\  /   If Len(R.Value) > 0 Then Set R = R.Offset(1)
 \  | \/    R.Value = Worksheets("Sheet2").Range("Q13").Value
  \ / /\    Exit For
   /\/  End If
  / Next
End If

บล็อก If...Else...End If สิ้นสุดด้วย Next; ลูป For Each...Next ด้านในสิ้นสุดด้วย End If และลูป For Each...Next ด้านนอกสิ้นสุดด้วย End If - คุณต้องทำให้สิ่งนี้ไม่พันกัน

Dim c As Range
Dim ws As Worksheet: Set ws = Sheet2
Dim range1 As Range: Set range1 = ws.Range("Q13")
Dim Cell As Range

For Each Cell In range1
    If Cell.Value = "45" Then
        NextRow = ws.Cells(ws.Rows.Count, "P").End(xlUp).Offset(1, 0).Row
        Cell.Copy ws.Range("P" & NextRow)
    Else
        For Each c In Range("B2:B" & Range("B65536").End(xlUp).Row)
            Dim R As Range
            Set R = Worksheets("Sheet2").Cells(Rows.Count, "E").End(xlUp) 'last cell in Column E with data
            If Len(R.Value) > 0 Then Set R = R.Offset(1)
            R.Value = Worksheets("Sheet2").Range("Q13").Value
            Exit For
        Next
    End If
Next
person Mathieu Guindon    schedule 12.11.2019