-
Notifications
You must be signed in to change notification settings - Fork 1
/
RuleEngine.cls
139 lines (118 loc) · 4.39 KB
/
RuleEngine.cls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "RuleEngine"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Public rules As New Collection
Public Rows As New Collection
Public Sub Apply()
Dim row As RowInfo
Dim rule As rule
For Each row In Rows ' goes through all rows
' Test all rules against selected row
Call ResetRules
For Each rule In rules
TestRule row, rule ' takes 1 row and apply 1 rule to it
Next
Next
End Sub
Sub TestRule(row As RowInfo, rule As rule)
Dim ruleCol As RuleColumn
Dim FoundMatch As Boolean: FoundMatch = False ' match in overall rule
Dim NewMatch As Boolean: NewMatch = False ' match in current rule column
Dim Link As String: Link = "" ' Link with next condition in the rule
Dim SkipFor As Boolean
Dim rule1value As Boolean
Dim rule2value As Boolean
'Debug.Print row.Columns("Name")
Dim ruleCounter As Integer
ruleCounter = 0
For Each ruleCol In rule.RuleColumns
'Debug.Print row.RowNumber
ruleCounter = ruleCounter + 1
rule1value = False
rule2value = False
Dim strRowVal As String
Dim numRowVal As Double
Dim strRuleVal As String
Dim numRuleVal As Double
Dim IsNum As Boolean
If IsNumeric(ruleCol.Value) Then
numRowVal = Val(row.Columns(ruleCol.Name))
numRuleVal = Val(ruleCol.Value)
IsNum = True
Else
strRowVal = row.Columns(ruleCol.Name)
strRuleVal = ruleCol.Value
IsNum = False
End If
If SkipFor Then GoTo ContinueFor
Select Case ruleCol.Operator
Case Operators.Eq
If IsNum Then NewMatch = (numRowVal = numRuleVal) Else NewMatch = (strRowVal = strRuleVal)
Case Operators.Gt
If IsNum Then NewMatch = (numRowVal > numRuleVal) Else NewMatch = (strRowVal > strRuleVal)
Case Operators.Lt
If IsNum Then NewMatch = (numRowVal < numRuleVal) Else NewMatch = (strRowVal < strRuleVal)
Case Operators.NoEQ
If IsNum Then NewMatch = (numRowVal <> numRuleVal) Else NewMatch = (strRowVal <> strRuleVal)
Case Operators.GtEq
If IsNum Then NewMatch = (numRowVal >= numRuleVal) Else NewMatch = (strRowVal >= strRuleVal)
Case Operators.LtEq
If IsNum Then NewMatch = (numRowVal <= numRuleVal) Else NewMatch = (strRowVal <= strRuleVal)
Case Operators.And
' Get Success value of given rule
' E.g. RuleI = True And RuleII = False
rule1value = IsRuleSuccess(ruleCol.Name)
rule2value = IsRuleSuccess(ruleCol.Value)
NewMatch = rule1value And rule2value
Case Operators.Or
rule1value = IsRuleSuccess(ruleCol.Name)
rule2value = IsRuleSuccess(ruleCol.Value)
NewMatch = rule1value Or rule2value
End Select
' Evaluate results
If Link = "AND" Then
If FoundMatch And NewMatch Then
row.Category = rule.Category
rule.Success = True
End If
ElseIf Link = "OR" Then
If FoundMatch Or NewMatch Then
row.Category = rule.Category
rule.Success = True
End If
Else
If NewMatch Then
row.Category = rule.Category
rule.Success = True
End If
End If
FoundMatch = NewMatch
Link = ruleCol.Link ' Link for next rule column in for loop.
ContinueFor:
Next
End Sub
Function IsRuleSuccess(ruleName As String) As Boolean
Dim r As rule
Dim result As Boolean
For Each r In rules
If ruleName = "Rule" & r.RuleID Then
result = r.Success
If result Then
'Debug.Print result
End If
End If
Next
IsRuleSuccess = result
End Function
Sub ResetRules()
Dim r As rule
For Each r In rules
r.Success = False
Next
End Sub