解决VBA计划 - 控制结构的责任?

时间:2014-01-04 20:57:12

标签: excel-vba vba excel

我差不多完成了一个程序,但在我完成它之前,我需要找到一个bug的原因。虽然我的本能是提供我认为可能导致问题的部分,但我已经复制了下面的整个程序。毕竟,如果我对问题所在的地方是对的,我现在可能已经能够找到它,而且我已经知道人们希望尽可能多地继续下去。事实上,经过几个小时,我能做的最好的事情是更严密地定义错误!

预期成果: 一个贯穿整个计划涉及到:

   Merc01-Merc04

按此顺序,然后调用

    Merc05-Merc09

或只是

    Merc10

(在特殊任务的情况下)。

最后,在每种情况下,

    Merc11
应该叫

。问题在于,在30个大约1个案例中,这个预期的序列正在破裂。在正确执行Merc09和Merc11之后,控制将返回到Merc07,而不是停止,然后Merc08-Merc09和Merc11正常运行。我没有找到为什么会这样。一个(其他)特性是,如果程序在第一次传递时执行了Merc10,则不会出现此错误。关于在哪里寻找我难以捉摸的bug的任何建议都将不胜感激。

Option Explicit

Dim ArmOfService As Byte
Dim Bottom
Dim CharacterNumber As Long
Dim CurrentTerm As Byte
Dim DecorationRollMade As Byte
Dim DecorationRollNeeded As Byte
Dim DiceSize As Byte
Dim GenAssignment
Dim GenAssignmentSwitchInt As Byte
Dim GenAssignmentSwitchOff As Byte
Dim iLoopControl
Dim jLoopControl
Dim kLoopControl
Dim LeftCol
Dim LineIncrement As Integer
Dim lLoopControl
Dim Merc(100)
Dim NoOfDice As Byte
Dim OfficerPromotion(63 To 78) As Byte
Dim PromotionRollMade As Byte
Dim PromotionRollNeeded As Byte
Dim Rank
Dim Roll As Byte
Dim SkillColumn
Dim SkillRollMade As Integer
Dim SkillRollNeeded As Integer
Dim SpecAssignmentSwitchEnd As Byte
Dim SurvivalRollMade As Byte
Dim SurvivalRollNeeded As Byte
Dim TechLevel As Byte
Dim Temp, Temp2, Temp3, Temp4, Temp5
Dim Term As Byte
Dim TestCount
Dim Top
Dim UnitAssignment
Dim WhichTable
Dim XTrainedArm
Dim Year As Byte

'UDF to roll a number of Dice of specified size and total them
  Function Dice(NoOfDice, DiceSize)
    For iLoopControl = 1 To NoOfDice
      Dice = Dice + WorksheetFunction.RandBetween(1, DiceSize)
    Next
  End Function

'UDF to generate a skill from the MOS Table
  Function MOSSkill(ArmOfService, TechLevel)
    Roll = Dice(1, 6)
      If TechLevel = 2 Then Roll = Roll + 1 'TL-11 or less = 1; TL-12+ = 2
      MOSSkill = WorksheetFunction.VLookup((WorksheetFunction.VLookup(Roll, (Range(Cells(4, 2), Cells(10, 8))), ArmOfService, False)), (Range(Cells(9, 32), Cells(39, 33))), 2, False)
  End Function

'UDF to generate a skill from the Skill Tables
  Function SixTables(SkillColumn, Rank)
    Roll = Dice(1, 6)
    SixTables = WorksheetFunction.VLookup((WorksheetFunction.VLookup(Roll + RankDMs(WhichTable, Rank), (Range("SKILL_TABLES")), SkillColumn, False)), (Range("Skills_Lookup")), 2, False)
  End Function

'UDF to lookup DMs on Skills_Tables_DMs table
  Function RankDMs(WhichTable, Rank)
  Debug.Print "Which Table "; WhichTable, ""
    RankDMs = WorksheetFunction.HLookup(WhichTable, (Range(Cells(11, 38), Cells(31, 41))), (Rank + 1), False)
  End Function

'UDF to read skills from the six 't' tables (marked in pale blue and less pale blue on worksheet)
  Function tSpecTables(Top, Bottom, LeftCol, lLoopControl)
    Temp3 = Cells(lLoopControl, LeftCol + 1)
    tSpecTables = WorksheetFunction.VLookup(Temp3, Range("Skills_Lookup"), 2, False)
  End Function

Sub MainOne()
'This is the 'main' Sub, providing the flow control and decision making structure for the rest,
'which are organised as other subs

Randomize

'Loop back to this point to begin generation of a new character
'NOTE: Replace this with a proper loop structure
CharacterNumber = CharacterNumber + 1

Call Merc01
'Clear and initialise arrays and variables

Call Merc02
'Handles the roll up of UPP, enlistment and first year of service

'There is NO Merc03()!!

Debug.Print
Debug.Print "Char No "; Merc(100)
Debug.Print "<Call04"

Call Merc04
'Generate General Assignment

  If GenAssignment <> "Special" Then

Debug.Print "<Call05"

    Call Merc05
    'Determine Unit Assignment

Debug.Print "<Call06"

    Call Merc06
    'Resolve Unit Assignment - Survival

Debug.Print "<Call07"

    Call Merc07
    'Resolve Unit Assignment - Decoration

Debug.Print "<Call08"

    Call Merc08
    'Resolve Unit Assignment - Promotion

Debug.Print "<Call09"

    Call Merc09
    'Resolve Unit Assignment - Skills

  Else 'If Special Assignment

Debug.Print "<Call10"

    Call Merc10
    'Generate Special Assignment

      If Year = 4 Then 'End of term procedure
      ' To be replaced by a proper control structure

      End If
  End If

    'Year = Year + 1

Debug.Print "<Call11"

    Call Merc11
    'DISPLAY BLOCK'

End Sub

Sub Merc01()

'Clear and initialise arrays and variables
  For iLoopControl = 1 To 100
    Merc(iLoopControl) = 0
  Next

  For iLoopControl = 63 To 78
    OfficerPromotion(iLoopControl) = 0
  Next

'NOTE: Check that only those variablea that need to be initialised are, and that THEY all are
  ArmOfService = 0
  GenAssignment = 0
  Merc(98) = 1
  SpecAssignmentSwitchEnd = 0
  TechLevel = 0
  Term = 1
  Year = 1

End Sub

Sub Merc02()
'Handles the roll up of UPP, enlistment and first year of service

'Generate a character's UPP and allocate it as both current and original scores
  For jLoopControl = 1 To 6
    Merc(jLoopControl) = Dice(2, 6)
    Merc(jLoopControl + 56) = Merc(jLoopControl)
    TestCount = TestCount + 1 'Test
  Next

'Insert Character No. in array
  Merc(100) = CharacterNumber

'Generate Tech Level 12+ and insert in array?
  TechLevel = Dice(1, 2) '1-Tech Level 11 or less, 2-Tech Level 12+
  Merc(80) = TechLevel

'Roll to enlist in the Army
  Roll = Dice(2, 6)
    If Merc(2) >= 6 Then Roll = Roll + 1
    If Merc(3) >= 5 Then Roll = Roll + 2
    If Roll < 5 Then Call MainOne

'Basic Training - Gun Cmbt
  Merc(22) = 1

'Generate Arm of Service
  ArmOfService = Dice(1, 4) '2-Art, 3-Cav, 4-Inf, 6-Spt, [7-Com]
    If ArmOfService = 4 Then
      ArmOfService = ArmOfService + 2
    Else: ArmOfService = ArmOfService + 1
    End If
  Merc(63) = ArmOfService 'Record ArmOfService for first term

'Advanced Training
  Temp = MOSSkill(ArmOfService, TechLevel)
  Merc(Temp) = Merc(Temp) + 1

End Sub

Sub Merc04()
'Generate General Assignment

  Roll = Dice(1, 6)
    If Merc(4) >= 8 And GenAssignmentSwitchInt = 1 Then Roll = Roll + 1
    If Merc(98) >= 11 And GenAssignmentSwitchOff = 1 Then Roll = Roll - 1
  GenAssignment = WorksheetFunction.VLookup(Roll, (Range(Cells(14, 2), Cells(21, 8))), ArmOfService, True)
  Merc(79) = GenAssignment

'Arrange this on the GUI so that either Int or Off are selectable, not both

End Sub

Sub Merc05()
'Determine Unit Assignment

  Roll = Dice(2, 6)
  UnitAssignment = WorksheetFunction.VLookup(Roll, (Range(Cells(26, 2), Cells(36, 8))), ArmOfService, False)
  Merc(81) = UnitAssignment

End Sub

Sub Merc06()
'Resolve Unit Assignment - Survival

' Find roll needed for survival
  Roll = Dice(2, 6)
  LineIncrement = ArmOfService - 5
    If LineIncrement < 0 Then LineIncrement = 0
  SurvivalRollNeeded = WorksheetFunction.HLookup(UnitAssignment, Range(Cells(23 + (LineIncrement * 7), 10), Cells(24 + (LineIncrement * 7), 16)), 2, False)

' Make survival roll
  SurvivalRollMade = Dice(2, 6)
    If ArmOfService = 2 And (Merc(14) > 1 Or Merc(16) > 1 Or Merc(18) > 1 Or Merc(20) > 1 Or Merc(28) > 1 Or Merc(36) > 1) Then SurvivalRollMade = SurvivalRollMade + 1
    If ArmOfService = 3 And (Merc(14) > 1 Or Merc(24) > 1 Or Merc(28) > 1 Or Merc(36) > 1) Then SurvivalRollMade = SurvivalRollMade + 1
    If ArmOfService = 4 And (Merc(22) > 1 Or Merc(24) > 1 Or Merc(30) > 1 Or Merc(35) > 1 Or Merc(36) > 1) Then SurvivalRollMade = SurvivalRollMade + 1
    If ArmOfService = 6 And (Merc(12) > 1 Or Merc(14) > 1 Or Merc(16) > 1 Or Merc(28) > 1 Or Merc(29) > 1 Or Merc(36) > 1) Then SurvivalRollMade = SurvivalRollMade + 1
    If ArmOfService = 7 And (Merc(8) > 1 Or Merc(15) > 1 Or Merc(22) > 1 Or Merc(24) > 1 Or Merc(30) > 1 Or Merc(33) > 1) Then SurvivalRollMade = SurvivalRollMade + 1
    If Cells(85, 28) <> Cells(84, 28) Then Cells(86, 28) = 999 'Test that a MOS 2+ DM has been made

'Award Purple Heart if wounded
  If SurvivalRollMade = SurvivalRollNeeded Then Merc(84) = Merc(84) + 1

'Check for KIA
  If SurvivalRollMade < SurvivalRollNeeded Then Call MainOne 'Replace GoTo with something more elegant (probably a Do While on ALIVE=YES AND RETIRED=NO)

End Sub

Sub Merc07()
'Resolve Unit Assignment - Decoration
  DecorationRollMade = Dice(2, 6)
  LineIncrement = ArmOfService - 5
  If LineIncrement < 0 Then LineIncrement = 0
  DecorationRollNeeded = WorksheetFunction.HLookup(UnitAssignment, Range(Cells(23 + (LineIncrement * 7), 10), Cells(25 + (LineIncrement * 7), 16)), 3, False)

  If (DecorationRollMade >= (DecorationRollNeeded + 6)) Then Merc(87) = Merc(87) + 1 'Check for award of SEH
  If (DecorationRollMade >= (DecorationRollNeeded + 3)) And (DecorationRollMade < (DecorationRollNeeded + 6)) Then Merc(86) = Merc(86) + 1 'Check for award of MCG
  If (DecorationRollMade >= DecorationRollNeeded) And (DecorationRollMade < (DecorationRollNeeded + 3)) Then Merc(85) = Merc(85) + 1 'Check for award of MCUF

End Sub

Sub Merc08()
'Resolve Unit Assignment - Promotion
  PromotionRollMade = Dice(2, 6)
  PromotionRollNeeded = WorksheetFunction.HLookup(UnitAssignment, Range(Cells(23 + (LineIncrement * 7), 10), Cells(26 + (LineIncrement * 7), 16)), 4, False)

    If (ArmOfService < 5 And Merc(5) >= 7) Then PromotionRollMade = PromotionRollMade + 1 '+1 DM for Inf, Cav, Art
    If (ArmOfService = 6 And Merc(4) >= 8) Then PromotionRollMade = PromotionRollMade + 1 '+1 DM for Support
    If (ArmOfService = 7 And Merc(3) >= 8) Then PromotionRollMade = PromotionRollMade + 1 '+1 DM for Commandos

    If PromotionRollMade >= PromotionRollNeeded Then
      If Merc(98) < 9 Then Merc(98) = Merc(98) + 1
      If (Merc(98) > 10 And OfficerPromotion(Term + 62) = 0) And (UnitAssignment <> "Training" And UnitAssignment <> "Int Sec" And UnitAssignment <> "Garrison") Then
      Merc(98) = Merc(98) + 1
      OfficerPromotion(Term + 62) = 1 'Set Officer Promotion Flag
    End If
  End If

'Merc(98) = 2 'Test

End Sub

Sub Merc09()
'Resolve Unit Assignment - Skills

'SKILL CHECK
  SkillRollMade = Dice(2, 6)

  LineIncrement = ArmOfService - 5
  If LineIncrement < 0 Then LineIncrement = 0
  SkillRollNeeded = WorksheetFunction.HLookup(UnitAssignment, Range(Cells(23 + (LineIncrement * 7), 10), Cells(27 + (LineIncrement * 7), 16)), 5, False)

  Debug.Print "Made"; SkillRollMade, "Needed"; SkillRollNeeded, "AoS"; ArmOfService, "Mission "; UnitAssignment, "*"; GenAssignment 'Test

    If SkillRollMade >= SkillRollNeeded Then

'Which skill table
      WhichTable = WorksheetFunction.VLookup(Merc(98), Range(Cells(5, 39), Cells(8, 45)), Dice(1, 6) + 1, True)

      Select Case WhichTable
        Case "MOS Skills"
          Temp = MOSSkill(ArmOfService, TechLevel)
          Merc(Temp) = Merc(Temp) + 1
      Debug.Print "Temp(MOS): "; Temp,
      Debug.Print


        Case "Army Life"
          SkillColumn = 2
          Rank = Merc(98)
          Temp = SixTables(SkillColumn, Rank)
          Merc(Temp) = Merc(Temp) + 1
      Debug.Print "Temp(Army): "; Temp,
      Debug.Print

        Case "NCO Skills"
          SkillColumn = 4
          Rank = Merc(98)
          Temp = SixTables(SkillColumn, Rank)
          Merc(Temp) = Merc(Temp) + 1
      Debug.Print "Temp(NCO): "; Temp,
      Debug.Print

        Case "Officer Skills"
          If GenAssignment = "Command" Then SkillColumn = 5 Else SkillColumn = 6
          Rank = Merc(98)
          Temp = SixTables(SkillColumn, Rank)
          Merc(Temp) = Merc(Temp) + 1
      Debug.Print "Temp(Officer): "; Temp,
      Debug.Print


        Case Else

      End Select

    End If 'completed skill check and continue onto next part of the year's resolution

End Sub

Sub Merc10()
'Generate Special Assignment

  Merc(98) = 1 'Test
' Special Assignment - Enlisted men and NCOs
  If Merc(98) < 10 Then
    Roll = Dice(1, 6)
    'If Merc(3) >= 7 And SpecAssignmentSwitchEnd = 1 Then Roll = Roll + 1
    Select Case Roll
      Case 1: Call CrossTraining
      Case 2: Call SpecSchool
      Case 3: Call CommandoSchool
      Case 4: Call ProtForces
      Case 5: Call Recruiting
      Case 6 To 7: Call OCS
    End Select
  Else
    'Special Assignment - Officers

    Roll = Dice(1, 6)
    Select Case Roll
      Case 1: Call IntSchool
      Case 2: Call CommandCollege
      Case 3: Call StaffCollege
      Case 4: Call CommandoSchool
      Case 5: Call Recruiting
      Case 6: Call AttacheAide
    End Select
  End If

End Sub

Sub Merc11()
'DISPLAY BLOCK'

'Display all of Merc array in the worksheet

  For kLoopControl = 1 To 100
    Cells(kLoopControl + 2, 34) = Merc(kLoopControl)
  Next

End Sub

Sub AttacheAide()

Debug.Print "AttacheAide"

  Merc(6) = Merc(6) + 1 '+1 Social

  Roll = Dice(1, 6)
    If Roll <= 4 Then

'Military Attache
      Merc(45) = Merc(45) + 1 'Count Special Assignment
      Merc(84) = Merc(84) + 1 'Automatic Promotion
    Else
'General's Aide - [TO DO] WORK OUT Benefit of choosing next appointment
      Merc(42) = Merc(42) + 1 'Count Special Assignment
    End If
  'xx

End Sub

Sub CommandCollege()

Debug.Print "CommandCollege"

'Check for Instructor assignment
'Merc(38) = 1 'Test
'Merc(27) = 2 'Test
  If Merc(38) > 0 And (Merc(34) >= 2 Or Merc(27) >= 2 Or Merc(30) >= 2) Then
    Merc(39) = Merc(39) + 1
    Merc(25) = Merc(25) + 1

  Else

    If Dice(1, 6) >= 4 Then Merc(27) = Merc(27) + 1
    If Dice(1, 6) >= 4 Then Merc(30) = Merc(30) + 1
    If Dice(1, 6) >= 4 Then Merc(34) = Merc(34) + 1

  Merc(38) = Merc(38) + 1 'Count Special Assignment

  End If

End Sub

Sub CommandoSchool()

Debug.Print "CommandoSchool"

'Check for Instructor assignment
'Merc(9) = 2 'Test
'Merc(40) = 1 'Test
  If Merc(40) > 0 And (Merc(9) > 1 Or Merc(10) > 1 Or Merc(15) > 1 Or Merc(22) > 1 Or Merc(25) > 1 Or Merc(30) > 1 Or Merc(33) > 1 Or Merc(35) > 1) Then
    Merc(41) = Merc(41) + 1
    Merc(25) = Merc(25) + 1
  Else

    If Dice(1, 6) >= 5 Then Merc(9) = Merc(9) + 1
    If Dice(1, 6) >= 5 Then Merc(10) = Merc(10) + 1
    If Dice(1, 6) >= 5 Then Merc(15) = Merc(15) + 1
    If Dice(1, 6) >= 5 Then Merc(22) = Merc(22) + 1
    If Dice(1, 6) >= 5 Then Merc(25) = Merc(25) + 1
    If Dice(1, 6) >= 5 Then Merc(30) = Merc(30) + 1
    If Dice(1, 6) >= 5 Then Merc(33) = Merc(33) + 1
    If Dice(1, 6) >= 5 Then Merc(35) = Merc(35) + 1

    Merc(40) = Merc(40) + 1 'Count Special Assignment

  End If

End Sub

Sub CrossTraining()

Debug.Print "CrossTraining"

'Select Arm of Service for X-training
  Do
    XTrainedArm = Dice(1, 4)
    If XTrainedArm = 4 Then XTrainedArm = 6 Else XTrainedArm = XTrainedArm + 1 '2-Art, 3-Cav, 4-Inf, 6-Spt
  Loop Until XTrainedArm <> ArmOfService

'Generate skill gained from X-Training
  Temp = MOSSkill(XTrainedArm, TechLevel)
  Merc(Temp) = Merc(Temp) + 1

'Increment attendance
  If XTrainedArm = 6 Then XTrainedArm = 4 Else XTrainedArm = XTrainedArm - 1
  Merc(52 + XTrainedArm) = Merc(52 + XTrainedArm) + 1

End Sub

Sub IntSchool()

Debug.Print "IntSchool"

  'Check for Instructor assignment
  If Merc(43) > 0 And (Merc(11) > 1 Or Merc(19) > 1 Or Merc(26) > 1 Or Merc(32) > 1) Then

    Merc(44) = Merc(44) + 1
    Merc(25) = Merc(25) + 1

  Else

    'Generate skills
    If Dice(1, 6) >= 4 Then Merc(11) = Merc(11) + 1
    If Dice(1, 6) >= 4 Then Merc(19) = Merc(19) + 1
    If Dice(1, 6) >= 4 Then Merc(26) = Merc(26) + 1
    If Dice(1, 6) >= 4 Then Merc(32) = Merc(32) + 1


      Merc(43) = Merc(43) + 1 'Count Special Assignment

  End If

End Sub

Sub OCS()
  ''Commission as 2nd Lt

Debug.Print "OCS"

  Merc(98) = 11

  ''Generate one MOS skill
  Temp = MOSSkill(ArmOfService, TechLevel)
  Merc(Temp) = Merc(Temp) + 1

    ''Generate one Staff Skill
    Select Case Dice(1, 6)
      Case 1: Merc(13) = Merc(13) + 1
      Case 2: Merc(16) = Merc(16) + 1
      Case 3: Merc(20) = Merc(20) + 1
      Case 4: Merc(25) = Merc(25) + 1
      Case 5: Merc(28) = Merc(28) + 1
      Case 6: Merc(29) = Merc(29) + 1
    End Select

    ''Generate one Command Skill
    Select Case Dice(1, 6)
      Case 1: Merc(3) = Merc(3) + 1
      Case 2: Merc(22) = Merc(22) + 1
      Case 3: Merc(24) = Merc(24) + 1
      Case 4: Merc(27) = Merc(27) + 1
      Case 5: Merc(34) = Merc(34) + 1
      Case 6: Merc(36) = Merc(36) + 1
    End Select

End Sub

Sub ProtForces()

Debug.Print "ProtForces"

  'Check for Instructor assignment
  If Merc(46) > 0 And (Merc(35) > 1 Or Merc(37) > 1) Then
    Merc(47) = Merc(47) + 1
    Merc(25) = Merc(25) + 1
  Else

    'Generate skills
    If Dice(1, 6) >= 3 Then Merc(35) = Merc(35) + 1
    If Dice(1, 6) >= 3 Then Merc(37) = Merc(37) + 1


  Merc(46) = Merc(46) + 1 'Count Special Assignment

  End If

End Sub
'
Sub Recruiting()

Debug.Print "Recruiting"

        Merc(31) = Merc(31) + 1

  Merc(48) = Merc(48) + 1 'Count Special Assignment

End Sub

Sub SpecSchool()

Debug.Print "SpecSchool"

  'Check for Instructor assignment
  If Merc(49) > 0 And (Merc(7) > 1 Or Merc(13) > 1 Or Merc(14) > 1 Or Merc(16) > 1 Or Merc(28) > 1 Or Merc(29) > 1) Then
    Merc(50) = Merc(50) + 1 'Increment Spec School*
    Merc(25) = Merc(25) + 1 'Instructor skill
  Else

    'Generate skills
    Select Case Dice(1, 6)
      Case 1: Merc(7) = Merc(7) + 1
      Case 2: Merc(13) = Merc(13) + 1
      Case 3: Merc(14) = Merc(14) + 1
      Case 4: Merc(16) = Merc(16) + 1
      Case 5: Merc(28) = Merc(28) + 1
      Case 6: Merc(29) = Merc(29) + 1
    End Select

    Merc(49) = Merc(49) + 1 'Count Special Assignment
  End If

End Sub

Sub StaffCollege()

Debug.Print "StaffCollege"

  'Check for Instructor assignment
  If Merc(51) > 0 And (Merc(7) > 1 Or Merc(12) > 1 Or Merc(14) > 1) Then
    Merc(52) = Merc(52) + 1
    Merc(25) = Merc(25) + 1
  Else

    'Generate skills
    If Dice(1, 6) >= 4 Then Merc(7) = Merc(7) + 1
    If Dice(1, 6) >= 4 Then Merc(12) = Merc(12) + 1
    If Dice(1, 6) >= 4 Then Merc(14) = Merc(14) + 1

    Merc(51) = Merc(51) + 1 'Count Special Assignment

  End If

End Sub

1 个答案:

答案 0 :(得分:1)

Merc02Merc06在某些情况下都会调用MainOne。我不认为这会产生你想要的行为

如果我们从调用MainOne的{​​{1}}开始(调用此#1),而Merc02又调用MainOne(称之为#2),我们现在有两个单独版本的{ {1}}。当MainOne#2完成后,控件会返回MainOne(从Merc02行开始),然后最终返回Merc(22) = 1#1(在MainOne#1后面的行呼叫Merc02,在调试之后,调用Merc04

由于大多数控制是通过模块级变量完成的,MainOne#1最终使用MainOne#2完成时留下的值。具体来说,我们不会调用Merc01将变量重置回其初始状态

不要从MainOneMerc02内部调用Merc06,而是考虑将这两者都变成函数。如果我们需要重置内容,请从函数返回False并让MainOne自行排序。

MainOne

这样的片段会更好
Dim goodToContinue As Boolean

CharacterNumber = CharacterNumber + 1

goodToContinue = False

Do
    'Clear and initialise arrays and variables
    Merc01

    'Handles the roll up of UPP, enlistment and first year of service
    goodToContinue = Merc02
Loop Until (goodToContinue)

(您可以直接测试Merc02的返回值,但我使用了一个单独的变量来使事情更清晰。不需要Call

Merc02中,我们会改变:

Sub Merc02()

' other stuff

If Roll < 5 Then Call MainOne

' more stuff

End Sub

为:

Function Merc02() As Boolean

' other stuff

If Roll < 5 Then
    Merc02 = False
    Exit Function
End If

' more stuff

Merc02 = True

End Function

Merc06的逻辑更复杂(正如您在代码中的注释中所指出的那样)但使用Function的想法,返回True或False以及MainOne中的控件结构来处理事情仍然是一样的