这是一个理论问题,而不是其他任何东西,如果可能的话,我可以使用它。
我在互联网上看,却一无所获。
excel是否有办法跟踪Sub已运行的内容,然后在if
语句中使用此信息?
即。
假设我们有Sub 1,Sub 2,Sub 3,Sub 4& Sub 5
子调用next sub取决于结果。我需要很多子,因为用法将涉及UserForms以及模块。
如果
Sub 1 - > Sub 2 - > Sub 3 - > Sub 5
但是如果Sub 3被调用,Sub 5将不会运行。
所以
Sub 1 - > Sub 2 - > Sub 4 - > Sub 5 - 但现在是5次运行。
这是否有意义/是否可能(我需要更强大的语言吗?)?
答案 0 :(得分:3)
您基本上想要在模块/项目中创建状态引擎。此状态引擎将处于全局级别,并且每个函数/子例程将在运行时更改状态。
我会考虑每个函数/例程都应该在进入和离开时触发事件。您的状态机将监听每个事件并相应地修改状态。
如果在继续操作之前有依赖于特定状态的函数/例程,则添加其他代码以查询当前状态。解决此问题的另一种方法是在尝试触发函数/子例程之前进行状态查询。取决于您希望代码执行的操作以及在尝试执行无效代码分支时您希望它如何响应。
答案 1 :(得分:1)
是的,你可以做到!请按照以下步骤操作:
例如:
Sub TrackSubroutines
If Function1(parameters) Then
If Functions2(parameters) Then
'... and so on
End If
End If
End Sub
Function1(parameters) As Boolean
Function1 = True/False
End Function
Function2(parameters) As Boolean
Function1 = True/False
End Function
您可以在MSDN找到更多内容:Calling Sub and Function Procedures
答案 2 :(得分:1)
通过日志变量State
使用Type
变量将跟踪代码存储在日志变量中,向您展示一种可行的方法。我建议在额外的代码模块中将其声明为公共类型模式“TLog”,例如: “modGlobals”。
使用全局变量的额外模块中的声明头
Option Explicit
Public Type TLog ' <~~ declare Public Type TLog e.g. in module 'modGlobals'
nTimes As Integer
State As String
End Type
代码模块中的声明头
您可以在这里定义自己的日志,例如: log1
基于TLog
类型。
此外,您添加一个常量代码字符串“124”,定义触发sub5的后续subs(sub1 + sub2 + sub4)。
Option Explicit ' declaration head in your code module
Dim log1 As TLog ' module log book comprising state code and times executed
Const MYCOND As String = "124" ' code string for condition: sub1 + sub2 + sub4
方式强>
任何过程调用都会运行用户定义的跟踪过程,其中包含三个主要任务:
log1.State
)(警告:如果你想记录超过9个后续的潜艇,你必须调整记录方法,只为每个潜艇加上一位数)
注意强>
我弃权使用(优选的)类方法以向您展示方式。当然你可以在SO找到一些想法。
如何在相关潜艇中使用跟踪程序
只需在任何相关程序中调用Track 1
,Track 2
等等(跟踪潜艇并默认检查严格的订单)。但是,我提出了通过将第二个参数设置为False
来选择任何顺序的可能性。
Sub sub1()
track 1
' ...
End Sub
Sub sub2()
track 2
' ...
End Sub
Sub sub3()
track 3
' ...
End Sub
Sub sub4()
track 4
' ...
End Sub
Sub sub5()
' Purpose: run code only after sub1 + sub2 + sub4
' ...
Beep
End Sub
示例电话
Sub test()
' Purpose: Testing wanted series of procedures
sub1
sub2
sub4 ' << if modified to sub3, there will be no execution
End Sub
跟踪程序的代码示例
在代码注释中写入解释:
Sub track(ByVal i As Integer, Optional bStrictOrder As Boolean = True)
' Purpose: track procedures sub1 to sub4 and run sub5 if the logged state string has a defined order (without sub3)
' Method: the state code is logged in a declared TYPE variable, e.g. log1
' Extra: an additional execution counter nTimes
' Note: the constant string MYCOND "124" codes the sequence sub1 + sub2 + sub4
Dim bExecProc As Boolean ' flag to procede in code
Dim yn As VbMsgBoxResult ' yes/no answer to messagebox question
' (0) log only first 4 procedures as precondition to execute sub5
If i >= 5 Then Exit Sub ' just in case of additional track statements in higher subs
' -------------------------------------------------------
' (1) track procedures by adding digit code to log1.State
' (reinitiate log1 after procedure sub1)
' -------------------------------------------------------
log1.State = IIf(i = 1 And bStrictOrder, "", log1.State) & Format(i, "0")
' note: might demand further code to avoid subsequent calls of the same procedure
'
' -------------------------------------------
' (2) Check defined condition code
' -------------------------------------------
If bStrictOrder Then
' (2a) sub1 + sub2 + sub4 have run before in defined ORDER
If log1.State = MYCOND Then bExecProc = True
Else
' (2b) alternative: sub1, sub2 and sub4 have run in ANY order
If Arrange(log1.State) = MYCOND Then bExecProc = True
End If
' -------------------------------------------
' (3) Execute procedure sub5
' -------------------------------------------
If bExecProc Then
' optional security message if sub5 has been already executed before
If log1.nTimes = 0 Then
yn = vbYes
Else
yn = MsgBox("Sub5 has been executed already " & log1.nTimes & " time(s). " & _
"Do you want to procede?", vbQuestion + vbYesNo + vbDefaultButton2, "Attention")
End If
If yn = vbYes Then
' do it and reset state and execution counter
MsgBox "I'm calling sub5 now" & vbNewLine & " because " & vbNewLine & _
" log1.State code shows """ & log1.State & """" & vbNewLine & vbNewLine & _
" (log1.nTimes = " & log1.nTimes & " time(s) up till now)", vbInformation, "Just before running Sub5"
' ~~~~~~
sub5 ' <~~ execute procedure sub5
' ~~~~~~
log1.State = "" ' reset state
log1.nTimes = log1.nTimes + 1 ' increment execution counter
End If
End If
End Sub
在任何程序顺序的情况下帮助函数
辅助函数Arrange()
仅在您将所有Track
次调用设置为False
的第二个(可选)参数时使用,例如Track 1, False
。
Function Arrange(ByVal s As String) As String
' Purpose: Helper function to rearrange State code for logging (e.g. log1.State)
' caveat: limited to 9 subsequent subs with single digits
' Note: (admittedly code could be refined)
Dim i As Integer ' counter
ReDim v(1 To Len(s))
Dim d As Integer ' each digit in code s
' loop through State code characters so far
For i = 1 To Len(s)
v(i) = Val(Mid(s, i, 1))
Next i
SortAr v
' return rearranged code string
Arrange = Join(v, "")
End Function
Sub SortAr(arr())
' Purpose: sort one based 1-dim array
' cf: https://stackoverflow.com/questions/20721489/how-can-i-sort-dates-in-an-array-in-vba
Dim Temp
Dim i As Long, j As Long
For j = 1 To UBound(arr)
Temp = arr(j)
For i = j - 1 To 1 Step -1
If (arr(i) <= Temp) Then GoTo 10
arr(i + 1) = arr(i)
Next i
i = 0
10: arr(i + 1) = Temp
Next j
End Sub