【发布时间】:2023-04-02 06:39:01
【问题描述】:
鉴于一些 VBA 代码(存储在文本文件中)会根据条件调用规则,我想解析代码并创建生成该规则所需的所有内容的迷你代码片段(以便理解规则的本质更容易)。
我开始尝试在 python 中对一些规则进行正则表达式,但如果轮子存在,我不想重新创建它。我知道像Retrieving JSON objects from a text file (using Python) 这样的例子来覆盖一个基类来创建一个客户解析器。我不确定是否有任何最适合开始使用的包,并且没有任何运气找到一个。
背景是我想像这样“缩小”大约 5000 条规则,更简单地说明规则周围的逻辑,看看有多少规则受到某个变量的影响,等等。
输入:
Sub One(position As Long)
Dim y As Long
With TEMP_ARRAY(position)
'Comments
If .VAR_A = "A" And .VAR_B = "B" And .VAR_C = "C" Then
Call Some_Rule("Rule 1")
End If
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Call Some_Rule("Rule 2")
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
'Some more comments
For y = 0 To UBound(.SUB_ARRAY)
If .SUB_ARRAY(y, 2) = 1 Or .SUB_ARRAY(y, 2) = 2 Then Exit For
Next y
If y = UBound(.SUB_ARRAY, 1) + 1 Then
Call Some_Rule("Rule 3")
End If
Else
'Still more comments
Select Case .SUB_ARRAY(0, 2)
Case 3
Call Some_Rule("Rule 4")
Case 4
Call Some_Rule("Rule 5")
End Select
End If
End If
End If
End With
End Sub
所需的输出:
## RULE 1
Sub One(position As Long)
With TEMP_ARRAY(position)
'Comments
If .VAR_A = "A" And .VAR_B = "B" And .VAR_C = "C" Then
Call Some_Rule("Rule 1")
End If
End With
End Sub
## RULE 2
Sub One(position As Long)
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Call Some_Rule("Rule 2")
End If
End With
End Sub
## RULE 3
Sub One(position As Long)
Dim y As Long
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
'Some more comments
For y = 0 To UBound(.SUB_ARRAY)
If .SUB_ARRAY(y, 2) = 1 Or .SUB_ARRAY(y, 2) = 2 Then Exit For
Next y
If y = UBound(.SUB_ARRAY, 1) + 1 Then
Call Some_Rule("Rule 3")
End If
End If
End If
End If
End With
End Sub
## RULE 4
Sub One(position As Long)
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
Else
'Still more comments
Select Case .SUB_ARRAY(0, 2)
Case 3
Call Some_Rule("Rule 4")
End Select
End If
End If
End If
End With
End Sub
## RULE 5
Sub One(position As Long)
With TEMP_ARRAY(position)
'More Comments
If IsEmpty(.SUB_ARRAY) Then
Else
If .VAR_A = 2 Then
If .VAR_B <> "" Then
Else
'Still more comments
Select Case .SUB_ARRAY(0, 2)
Case 4
Call Some_Rule("Rule 5")
End Select
End If
End If
End If
End With
End Sub
编辑:这是我到目前为止所做的(更多代码,但这是它的核心)。基本上,找到以“Some_Rule”开头的行(使用正则表达式),然后从向上方向开始调用此函数。当它找到一个打开的标签时,它会改变方向并开始寻找它的结束标签,然后从它停止的地方重新开始,等等。我以这种方式成功地获得了规则 1,然后是凌晨 4 点,所以我去睡觉了 :) ...我现在正在折腾东西,所以仍然很草率,但想更新我的进度
def compile_rule(lines, j, direction, statement_open=False):
"""
lines : total lines in file
j : current position
direction : 1 is up, -1 is down
statement_open : vba syntax not yet closed ex: if without end if
"""
global rule
j -= direction
if line_type(lines[j]) in [0, 3] and not statement_open:
rule.append(lines[j], j, direction)
elif line_type(lines[j]) == 1 and not statement_open:
rule.append(lines[j], j, direction)
rule.start_looking_for(line_check(lines[j]))
statement_open = True
direction *= -1
elif line_type(lines[j]) == 2 and rule.looking_for() == line_check(lines[j]) and statement_open:
rule.append(lines[j], j, direction)
statement_open = False
direction *= -1
else:
rule.set_position(j, direction)
if (j > 0 and j < len(lines) - 1) or (j == 0 and statement_open):
compile_rule(lines, rule.get_position(direction), direction, statement_open)
【问题讨论】:
-
那么你有 1 条规则可以通过 hacking 来工作,还有 4999 条规则可以使用?
-
为什么“Python”是问题的基本部分?
-
没有理由——认为可能有一些更简单的 python 解析器可用。这些规则将(可能/最终)从 VBA 转移到 Python,以便具有 Python 经验的数据分析师可以维护这些规则。认为如果规则是单独的,它可能会更容易移动——这不是一个要求,所以不打算花太多时间在它上面。
-
我非常怀疑有人用 Python 构建了一个严肃的 VBA 解析器。所以你真正的问题是将VBA转换为Python?您要求的是 VBA 到 Python 的翻译器,除非您想手动完成。
-
是的,似乎是这样......不幸的是,我认为这部分必须由手工完成。这是过去 7 年(由许多不同的人)建立的规则集合,需要大量整合和清理。