给你第一版吧,只是把文本表达式转换为 VBA表达式。
我认为最有效率的应该是把 数组传过去 马上运算,所以那个会是第二版。
不过这两版都是耗点资源的,regexp 已经是非常高效的文本处理器,但是如果你会做非常强大的“编译器”的话,一段文本的处理是错误的!
正确应该是一个一个字符读入,处理当前的“语法错误”,和使用堆栈来运算 “当前值”的。
Function ggg(str As String)
Dim re As RegExp, m As MatchCollection, sm As SubMatches, vs() As Variant, vsqty As Long
vsqty = 0
Set re = New RegExp
re.Global = True
re.IgnoreCase = True
re.Multiline = True
ReDim vs(vsqty)
re.Pattern = "(\w+)\(([\w\d]+)\((\d+),(\d+)\)\:([\w\d]+)\((\d+),(\d+)\)\)"
ggg = str
Set m = re.Execute(str)
Do While m.Count > 0
Set sm = m(0).SubMatches
vsqty = 0
ReDim vs(0)
vs(0) = "[SyntaxError]"
If InStr("sum average", sm(0)) Then
If sm(1) = sm(4) Then
sti = IIf(sm(2) < sm(5), 1, -1)
stj = IIf(sm(3) < sm(6), 1, -1)
For i = sm(2) To sm(5) Step sti
For j = sm(3) To sm(6) Step stj
ReDim Preserve vs(vsqty)
vs(vsqty) = sm(1) & "(" & i & "," & j & ")"
vsqty = vsqty + 1
Next
Next
End If
If sm(0) = "sum" Then
rep = "(" & Join(vs, "+") & ")"
ElseIf sm(0) = "average" Then
rep = "(" & Join(vs, "+") & ")/" & vsqty
End If
End If
ggg = Replace(ggg, m(0), rep, 1, 1)
Set m = re.Execute(ggg)
Loop
End Function
第一版执行结果:
? ggg("round(sum(v(1,2):v(2,4))/5,2)+average(v(1,2):v(2,3))*3")
round((v(1,2)+v(1,3)+v(1,4)+v(2,2)+v(2,3)+v(2,4))/5,2)+(v(1,2)+v(1,3)+v(2,2)+v(2,3))/4*3
这个版本让你把表达式转换成为 VBA 表达式,自己eval 吧!
第二版,需要做再说吧!
第三版,单字节处理版,付费的可以帮你做个动态语法编译器出来的!
给你第一版吧,只是把文本表达式转换为 VBA表达式。
我认为最有效率的应该是把 数组传过去 马上运算,所以那个会是第二版。
不过这两版都是耗点资源的,regexp 已经是非常高效的文本处理器,但是如果你会做非常强大的“编译器”的话,一段文本的处理是错误的!
正确应该是一个一个字符读入,处理当前的“语法错误”,和使用堆栈来运算 “当前值”的。
Function ggg(str As String)
Dim re As RegExp, m As MatchCollection, sm As SubMatches, vs() As Variant, vsqty As Long
vsqty = 0
Set re = New RegExp
re.Global = True
re.IgnoreCase = True
re.Multiline = True
ReDim vs(vsqty)
re.Pattern = "(\w+)\(([\w\d]+)\((\d+),(\d+)\)\:([\w\d]+)\((\d+),(\d+)\)\)"
ggg = str
Set m = re.Execute(str)
Do While m.Count > 0
Set sm = m(0).SubMatches
vsqty = 0
ReDim vs(0)
vs(0) = "[SyntaxError]"
If InStr("sum average", sm(0)) Then
If sm(1) = sm(4) Then
sti = IIf(sm(2) < sm(5), 1, -1)
stj = IIf(sm(3) < sm(6), 1, -1)
For i = sm(2) To sm(5) Step sti
For j = sm(3) To sm(6) Step stj
ReDim Preserve vs(vsqty)
vs(vsqty) = sm(1) & "(" & i & "," & j & ")"
vsqty = vsqty + 1
Next
Next
End If
If sm(0) = "sum" Then
rep = "(" & Join(vs, "+") & ")"
ElseIf sm(0) = "average" Then
rep = "(" & Join(vs, "+") & ")/" & vsqty
End If
End If
ggg = Replace(ggg, m(0), rep, 1, 1)
Set m = re.Execute(ggg)
Loop
End Function
第一版执行结果:
? ggg("round(sum(v(1,2):v(2,4))/5,2)+average(v(1,2):v(2,3))*3")
round((v(1,2)+v(1,3)+v(1,4)+v(2,2)+v(2,3)+v(2,4))/5,2)+(v(1,2)+v(1,3)+v(2,2)+v(2,3))/4*3
这个版本让你把表达式转换成为 VBA 表达式,自己eval 吧!
第二版,需要做再说吧!
第三版,单字节处理版,付费的可以帮你做个动态语法编译器出来的!