vba堆栈空间不足(错误28) - 递归过程

时间:2016-05-04 08:32:47

标签: vba excel-vba recursion ip excel

我是主题VBA的新手。

我想将IP范围设为正则表达式。 这段代码应该使数字范围的开始(a)和结束(b)成为正则表达式,例如a = 111,b = 114,result =(1(1 [1-4]))。 / p>

Function IPAll(a As String, b As String) As String
    Dim Dot1%, Dot2%, Dot3%
    Dim LowIP(3) As Variant
    Dot1 = InStr(1, a, ".")
    Dot2 = InStr(Dot1 + 1, a, ".")
    Dot3 = InStr(Dot2 + 1, a, ".")

    If Dot1 <> 0 Then
        LowIP(0) = Mid(a, 1, Dot1 - 1)
        If Dot2 <> 0 Then
            LowIP(1) = Mid(a, Dot1 + 1, Dot2 - Dot1 - 1)
            If Dot3 <> 0 Then
                LowIP(2) = Mid(a, Dot2 + 1, Dot3 - Dot2 - 1)
                LowIP(3) = Mid(a, Dot3 + 1, Dot3 - 1)
            Else
                LowIP(2) = Mid(a, Dot2 + 1, Dot2 - 1)
            End If
        Else
            LowIP(1) = Mid(a, Dot1 + 1, Dot1 - 1)
            If LowIP(1) = "" Then                   'Fehler bei "" *1 abfangen
                LowIP(1) = 0
            End If
        End If
    Else
        LowIP(0) = a
        LowIP(1) = 0
    End If


    Dim HighIP(3) As Variant
    Dot1 = InStr(1, b, ".")
    Dot2 = InStr(Dot1 + 1, b, ".")
    Dot3 = InStr(Dot2 + 1, b, ".")

    If Dot1 <> 0 Then
        HighIP(0) = Mid(b, 1, Dot1 - 1)
        If Dot2 <> 0 Then
            HighIP(1) = Mid(b, Dot1 + 1, Dot2 - Dot1 - 1)
            If Dot3 <> 0 Then
                HighIP(2) = Mid(b, Dot2 + 1, Dot3 - Dot2 - 1)
                HighIP(3) = Mid(b, Dot3 + 1, Dot3 - 1)
            Else
                HighIP(2) = Mid(b, Dot2 + 1, Dot2 - 1)
            End If
        Else
            HighIP(1) = Mid(b, Dot1 + 1, Dot1 - 1)
             If HighIP(1) = "" Then
                HighIP(1) = 0
            End If
        End If
    Else
        HighIP(0) = b
        HighIP(1) = 0
    End If

    Dim splita As Variant: splita = LowIP
    Dim splitb As Variant: splitb = HighIP

    Dim zeros$: zeros = ""
    Dim twofivefives$: twofivefives = ""
    Dim j%
    Dim len_splita%: len_splita = (UBound(Split(a, ".")) + 1)
    For j = 0 To len_splita                  'je nach länge von a wird zeros zu z.B. 0.0.0.0. und twofivefives zu z.B 255.255.255.255.
        zeros = zeros & "0."
        twofivefives = twofivefives & "255."
    Next j
    zeros = Mid(zeros, 1, Len(zeros) - 1)       'wegnehmen des letzten Punktes
    twofivefives = Mid(twofivefives, 1, Len(twofivefives) - 1)



    If splita(0) = splitb(0) And len_splita = 1 Then                                                                                    'wenn erste Zahl gleich und Länge beider =1
        IPAll = splita(0)                                                                                                                   'return: erste Zahl
    ElseIf splita(0) = splitb(0) Then                                                                                                   'wenn erste Zahl gleich
        IPAll = splita(0) & "\." & IPAll(Mid(a, InStr(a, ".") + 1, Len(a)), Mid(b, InStr(b, ".") + 1, Len(b)))                              'return: erste Zahl, "\." IPAll( rest von a, rest von b)
    ElseIf len_splita = 1 Then                                                                                                          'wenn a nur eine Zahl
        IPAll = "(" & IPGen(a, b) & ")"                                                                                                     'return: "(", IPGen(a, b), ")"
    ElseIf splita(1) = 0 And splitb(1) = 255 Then                                                                                       'wenn zweite Zahl a =0 und zweite zahl b =255
        IPAll = "(" & IPGen(splita(0), splitb(0)) & ")\." & IPAll(Mid(a, InStr(a, ".") + 1, Len(a)), Mid(b, InStr(b, ".") + 1, Len(b)))     'return: "(", IPGen(erste Zahl a, erste Zahl b), ")\.", IPAll(alles nach ersten . aus a, alles nach ersten . aus b)
    ElseIf splita(1) <> 0 And splitb(1) <> 255 And (splita(1) * 1 + 1) = (splitb(1) * 1) Then                                           'wenn zweite zahl a !=0 und zweite zahl b != 255 und (zweite zahl a) +1 gleich zweite zahl b
        IPAll = "(" & splita(0) & "\." & IPAll(Mid(a, InStr(a, ".") + 1, Len(a)), twofivefives)                                             'return: "(", erste zahl a, "\.", IPAll(alles nach ersten . aus a, twofivefives)
        IPAll = IPAll & "|" & splitb(0) & "\." & IPAll(CStr(zeroes), Mid(b, InStr(b, ".") + 1, Len(b))) & ")"                               'return: "|", erste zahl a, "\.", IPAll(zeroes, alles nach ersten . aus b), ")"
    ElseIf splita(1) <> 0 And splitb(1) <> 255 Then                                                                                     'wenn zweite zahl a !=0 und zweite zahl b !=255
        IPAll = "(" & splita(0) & "\." & IPAll(Mid(a, InStr(a, ".") + 1, Len(a)), twofivefives)                                             'return: "(", erste zahl a, "\.", IPAll(alles nach ersten . aus a, twofivefives)
        IPAll = IPAll & "|(" & IPAll((splita(0) * 1 + 1) & "." & zeroes, (splitb(0) * 1 - 1) & "." & twofivefives) & ")"                    'return: "|(", IPAll(erste Zahl a +1 und "." und zeroes, erste zahl b -1 und "." und twofivefives), ")"
        IPAll = IPAll & "|" & splitb(0) & "\." & IPAll(CStr(zeroes), Mid(b, InStr(b, ".") + 1, Len(b))) & ")"                               'return: "|", erste Zahl b, "\.", IPAll(zeroes, alles nach ersten . aus b), ")"
    ElseIf splita(1) <> 0 Then                                                                                                          'wenn zweite zahl a !=0
        IPAll = "(" & splita(0) & "\." & IPAll(Mid(a, InStr(a, ".") + 1, Len(a)), twofivefives)                                             'return: "(", erste zahl, "\.", IPAll(alles nach ersten . aus a, twofivefives)
        IPAll = IPAll & "|" & IPAll((splita(0) * 1 + 1) & "." & zeroes, (splitb(0) * 1) & "." & twofivefives) & ")"                         'return: "|", IPAll(erste zahl a +1 und "." und zeroes, erste zahl b und "." und twofivefives), ")"         <-warum nicht b -1 ?
    ElseIf splitb(1) <> 255 Then                                                                                                        'wenn zweite zahl b !=255
        IPAll = "(" & IPAll(splita(0) & "." & zeros, (splitb(0) * 1 - 1) & "." & twofivefives)                                              'return: "(", IPAll(erste zahl a und "." und zeroes, erste zahl b -1 und "." und twofivefives)
        IPAll = IPAll & "|" & splitb(0) & "\." & IPAll(CStr(zeroes), Mid(b, InStr(b, ".") + 1, Len(b))) & ")"                               'return: "|", erste zahl b, "\.", IPAll(zeroes, alles nach ersten . aus b), ")"
    End If

End Function

Function IPGen(a As Variant, b As Variant) As Variant
         If a = "" Then      'Fehler bei "" * 1 abfangen
        a = 0
    End If
    If a * 1 > b * 1 Then
        Dim temp%: temp = a
        a = b
        b = temp
    End If
    If a = b Then
        IPGen = a
    ElseIf Mid(a, 1, 1) = Mid(b, 1, 1) And Len(a) = Len(b) And Len(a) = 3 Then                                  'wenn erste Zahl gleich und Länge beider =3
        IPGen = Mid(a, 1, 1) & "(" & IPGen(Mid(a, 2, Len(a)), Mid(b, 2, Len(b))) & ")"                              'return: erste Zahl a, "(", IPGen(rest, rest), ")"
    ElseIf Len(a) = Len(b) And Len(a) = 3 Then                                                                  'wenn Länge beider gleich 3
        IPGen = Mid(a, 1, 1) & "(" & IPGen(Mid(a, 2, Len(a)), 99) & ")|" & IPGen((Mid(a, 1, 1) * 1 + 1) & "00", b)  'return: erste Zahl a, "(", IPGen(rest, 99), ")|", IPGen( erste Zahl +1 und "00", b)
    ElseIf Len(b) = 3 Then                                                                                      'wenn Länge a =3
        IPGen = IPGen(a, 99) & "|" & IPGen(100, b)                                                                  'return: IPGen(a, 99), "|", IPGen(100, b)
    ElseIf Mid(a, 1, 1) = Mid(b, 1, 1) And Len(a) = Len(b) And Len(a) = 2 Then                                  'wenn erste Zahl gleich und Länger beider gleich 2
        IPGen = Mid(a, 1, 1) & ip_range(Mid(a, 2, 1), Mid(b, 2, 1))                                                 'return: erste Zahl a, ip_range(zweite Zahl a, zweite Zahl b)
    ElseIf Len(a) = Len(b) And Mid(a, 2, 1) = 0 And Mid(b, 2, 1) = 9 And Len(a) = 2 Then                        'wenn zweite Zahl a =0, zweite Zahl b =9 und Länge beider =2
        IPGen = ip_range(Mid(a, 1, 1), Mid(b, 1, 1)) & ip_range(Mid(a, 2, 1), Mid(b, 2, 1))                         'return: ip_range(erste Zahl a, erste Zahl b + ip_range(zweite Zahl a, zweite Zahl b))
    ElseIf Len(a) = Len(b) And Mid(a, 2, 1) <> 0 And Len(a) = 2 Then                                            'wenn zweite Zahl ungleich 0 und Länge beider =2
        IPGen = IPGen(a, Mid(a, 1, 1) & "9") & "|" & IPGen(Mid(a, 1, 1) * 1 + 1 & "0", b)                           'return: IPGen(a, erste Zahl a und "9"), "|", IPGen(erste Zahl + 1 und "0", b)
    ElseIf Len(a) = Len(b) And Mid(b, 2, 1) <> 9 And Len(b) = 2 Then                                            'wenn zweite Zahl b ungleich 9 und Länge beider =2
        IPGen = IPGen(a, (Mid(b, 1, 1) * 1 - 1) & "9") & "|" & IPGen(Mid(b, 1, 1) & "0", b)                         'return: IPGen(a, erste Zahl b -1 und "9"), "|", IPGen(erste Zahl b und "0", b)
    ElseIf Len(a) = 1 And Len(b) = 1 Then                                                                       'wenn Länge beider =1
        IPGen = ip_range(a, b)                                                                                      'return: ip_range(a, b)
    ElseIf Len(a) = 1 Then                                                                                      'wenn Länge a =1
        IPGen = ip_range(a, 9) & "|" & IPGen(10, b)                                                                 'return: ip_range(a, 9), "|", IPGen(10, b)
    End If

End Function

Function ip_range(a As Variant, b As Variant) As Variant
    ip_range = "[" & a & "-" & b & "]"
End Function

但MS Ecel不喜欢递归程序,如果我使用函数MsgBox IPAll("10.6.24.1", "10.6.25.254"),它会说:&#34;堆栈空间不足(错误28)&#34;。我能做什么?我该如何解决?

编辑:它适用于子网掩码26,但如果使用22子网作为ip范围,我会收到错误。 我可以编辑堆栈空间的空间吗?

尊敬的。

2 个答案:

答案 0 :(得分:0)

对于a =&#34; abc&#34;,Mid(a,1)返回&#34; abc&#34; 我怀疑你想要Mid(a,1,1),它会返回&#34; a&#34;

例如

ElseIf Mid(a, 1, 1) = Mid(b, 1, 1) And Len(a) = Len(b) And Len(a) = 3 Then                                  'wenn erste Zahl gleich und Länge beider =3
        Debug.Print a, b, "|a| = |b| = 3; a(1)=b(1) "
        aa = Mid(a, 2, Len(a))
        bb = Mid(b, 2, Len(b))
        IPGen = Mid(a, 1, 1) & "(" & IPGen(aa, bb) & ")"                           'return: erste Zahl, "(", IPGen(rest, rest), ")"

答案 1 :(得分:0)

您也可以重写它,以便它不使用递归。最终的结果可能不那么优雅,但无疑会更快,并且会产生正常的表达式:

示例使用: MsgBox GenIP(122, 223)
制作: [12][0-9][0-9]

Function GenIP(a As Byte, b As Byte) As String

    Dim strA As String * 3
    Dim strB As String * 3
    Dim retV(1 To 3) As String

    strA = Format$(a, "000")
    strB = Format$(b, "000")

    If a = b Then
        GenIP = strA
    Else
        With WorksheetFunction
            retV(1) = Left$(IIf(.Min(a, b) = a, strA, strB), 1)
            retV(2) = Mid$(IIf(.Min(a, b) = a, strA, strB), 2, 1)
            retV(3) = Right$(IIf(.Min(a, b) = a, strA, strB), 1)

            For i = .Min(a, b) To .Max(a, b)
                If Right(retV(1), 1) <> Left$(Format$(i, "000"), 1) And Len(retV(1)) < 3 Then
                    retV(1) = retV(1) & Left$(Format$(i, "000"), 1)
                End If
                If Right(retV(2), 1) <> Mid$(Format$(i, "000"), 2, 1) And Len(retV(2)) < 10 Then
                    retV(2) = retV(2) & Mid$(Format$(i, "000"), 2, 1)
                End If
                If Right(retV(3), 1) <> Right$(Format$(i, "000"), 1) And Len(retV(3)) < 10 Then
                    retV(3) = retV(3) & Right$(Format$(i, "000"), 1)
                End If
            Next
        End With

        If Len(retV(1)) = 3 Then
            retV(1) = "0-2"
        End If
        If Len(retV(2)) = 10 Then
            retV(2) = "0-9"
        End If
        If Len(retV(3)) = 10 Then
            retV(3) = "0-9"
        End If

        GenIP = "[" & retV(1) & "][" & retV(2) & "][" & retV(3) & "]"
    End If

End Function