J'ai écrit un code pour la fonction personnalisée pour ajouter des nombres (supérieurs à 15 chiffres) dans Excel VBA. Cela fonctionne bien si j'exécute cette fonction pendant 1 fois mais donne une erreur lorsqu'elle est utilisée plusieurs fois. Je suis nouveau dans ce domaine, donc TOUTE AIDE SERAIT VRAIMENT APPRÉCIÉE.

J'ai déjà écrit le code. Regardez ceci, s'il vous plaît.

Public Function AddBigNumbers(n1 As String, n2 As String) As String
i1 = 0
i2 = 0
i3 = Int(Log(n1) / Log(10))
i4 = Int(Log(n2) / Log(10))
i5 = 0
i6 = 0

If i3 = i4 Then
    Dim Ad() As Long
    ReDim Ad(1 To i3 + 1) As Long
        For i2 = 1 To i3 + 1 Step 1
            Ad(i2) = (Mid(n1, i2, 1))
        Next i2

i1 = 0
i2 = 0
     Dim Bd() As Long
     ReDim Bd(1 To i3 + 1) As Long
        For i2 = 1 To i3 + 1 Step 1
            Bd(i2) = (Mid(n2, i2, 1))
        Next i2

Dim D() As Long
ReDim D(1 To i3 + 1) As Long

i1 = 0
     For i1 = 1 To i3 + 1 Step 1
        If Bd(i1) > Ad(i1) Then
            D(i1) = 1
        End If
     Next i1
i1 = 0
    For i1 = 1 To i3 + 1 Step 1
        If Bd(i1) = Ad(i1) Then
            D(i1) = 0
        End If
    Next i1
i1 = 0
    For i1 = 1 To i3 + 1 Step 1
        If Bd(i1) < Ad(i1) Then
            D(i1) = -1
        End If
    Next i1

i1 = 0
    For i1 = 1 To i3 + 1 Step 1
        If D(i1) > 0 Then i5 = n2 And i1 = i3 + 1 Else If D(i1) = 0 Then i1 = i1 Else i5 = n1
    Next i1
i1 = 0
    For i1 = 1 To i3 + 1 Step 1
        If D(i1) > 0 Then i6 = n1 And i1 = i3 + 1 Else If D(i1) = 0 Then i1 = i1 Else i6 = n2
    Next i1
End If

If i3 > i4 Then i5 = n1 Else i5 = n2
If i3 > i4 Then i6 = n2 Else i6 = n1


i7 = Int(Log(i5) / Log(10))
i8 = Int(Log(i6) / Log(10))

i1 = 0
i2 = 0
Dim A() As Long
ReDim A(1 To i7 + 1) As Long
    For i2 = 1 To i7 + 1 Step 1
        A(i2) = (Mid(i5, i2, 1))
    Next i2
i1 = 0
i2 = 0
    Dim B() As Variant
    ReDim B(1 To i7 + 1) As Variant
        If i7 > i8 Then
            For i1 = 1 To i7 - i8 Step 1
                B(i1) = 0
            Next i1

            For i2 = i7 - i8 + 1 To i7 + 1 Step 1
                B(i2) = Mid(i6, i2 - i7 + i8, 1)
            Next i2
        End If

         If i7 = i8 Then
             For i2 = 1 To i7 + 1 Step 1
                 B(i2) = Mid(i6, i2, 1)
             Next i2
         End If
i1 = 0
i2 = 0
    Dim C() As Variant
    ReDim C(1 To i7 + 1) As Variant
        For i2 = 1 To i7 + 1 Step 1
            C(i2) = CInt(A(i2)) + B(i2)
        Next i2

i1 = 0
i2 = 0
        For i2 = i7 + 1 To 2 Step -1
            C(i2 - 1) = C(i2 - 1) + Int(C(i2) / 10)
            C(i2) = C(i2) - 10 * Int(C(i2) / 10)
        Next i2
i9 = 0
i9 = Join(C, "")
'i9 = WorksheetFunction.Concat("'", Join(C, ""))
AddBigNumbers = i9
i1 = 0
i2 = 0
End Function

Cela fonctionne bien si je l'exécute pour une seule fois (c'est-à-dire si je l'utilise pour une fois) mais plusieurs fois, cela donne une erreur "#Value".

0
Vineet Mangal 27 janv. 2019 à 11:13

5 réponses

Meilleure réponse

La faille est en deux lignes:

If D(i1) > 0 Then i5 = n2 And i1 = i3 + 1 Else If D(i1) = 0 Then i1 = i1 Else i5 = n1

If D(i1) > 0 Then i6 = n1 And i1 = i3 + 1 Else If D(i1) = 0 Then i1 = i1 Else i6 = n2

En tenant compte du premier et en le traduisant dans la syntaxe simple If, il donnerait:

    If D(i1) > 0 Then
        i5 = n2 And i1 = i3 + 1
    Else
        If D(i1) = 0 Then
            i1 = i1
        Else
            i5 = n1
        End If
    End If

Qui, selon votre commentaire, devrait se lire:

    If D(i1) > 0 Then
        i5 = n2
        i1 = i3 + 1 ' to end loop
    Else
        If D(i1) = 0 Then
            i1 = i1
        Else
            i5 = n1
        End If
    End If

En outre:

  • pour quitter la boucle que vous souhaitez utiliser l'instruction Exit For
  • ces deux For i1 = 1 To i3 + 1 Step 1 boucles peuvent être fusionnées
  • i1 = i1 ne fait rien

Et vous pouvez donc réécrire ces deux boucles en une seule boucle:

    For i1 = 1 To i3 + 1 Step 1
        If D(i1) > 0 Then
            i5 = n2
            i6 = n1
            Exit For
        ElseIf D(i1) < 0 Then
            i5 = n1
            i6 = n2
        End If
    Next i1

Enfin, en ajoutant une déclaration de variables explicites et quelques autres optimisations, l'ensemble du code aboutirait à ce qui suit:

Public Function AddBigNumbers(n1 As String, n2 As String) As String
    Dim i1 As Long, i2 As Long, i3 As Long, i4 As Long
    Dim i5 As Variant, i6 As Variant
    Dim i7 As Long, i8 As Long

    i3 = Int(Log(n1) / Log(10))
    i4 = Int(Log(n2) / Log(10))
    i5 = 0
    i6 = 0

    Select Case True
        Case i3 = i4
            ReDim Ad(1 To i3 + 1) As Long
            ReDim Bd(1 To i3 + 1) As Long
            For i2 = 1 To i3 + 1 Step 1
                Ad(i2) = (Mid(n1, i2, 1))
                Bd(i2) = (Mid(n2, i2, 1))
            Next

            For i1 = 1 To i3 + 1
                If Bd(i1) > Ad(i1) Then
                    i5 = n2
                    i6 = n1
                    Exit For
                ElseIf Bd(i1) <= Ad(i1) Then
                    i5 = n1
                    i6 = n2
                End If
            Next

        Case i3 > i4
            i5 = n1
            i6 = n2

        Case Else
            i5 = n2
            i6 = n1
    End Select


    i7 = Int(Log(i5) / Log(10))
    i8 = Int(Log(i6) / Log(10))

    Dim A() As Long
    ReDim A(1 To i7 + 1) As Long
    For i2 = 1 To i7 + 1
        A(i2) = (Mid(i5, i2, 1))
    Next

    Dim B() As Variant
    ReDim B(1 To i7 + 1) As Variant
    Select Case True
        Case i7 > i8
            For i1 = 1 To i7 - i8
                B(i1) = 0
            Next

            For i2 = i7 - i8 + 1 To i7 + 1
                B(i2) = Mid(i6, i2 - i7 + i8, 1)
            Next
        Case i7 = i8
            For i2 = 1 To i7 + 1
                B(i2) = Mid(i6, i2, 1)
            Next
    End Select

    Dim C() As Variant
    ReDim C(1 To i7 + 1) As Variant
    For i2 = 1 To i7 + 1
        C(i2) = CInt(A(i2)) + B(i2)
    Next

    For i2 = i7 + 1 To 2 Step -1
        C(i2 - 1) = C(i2 - 1) + Int(C(i2) / 10)
        C(i2) = C(i2) - 10 * Int(C(i2) / 10)
    Next

    AddBigNumbers = Join(C, "")

End Function
0
DisplayName 27 janv. 2019 à 11:09

Si vous diminuez i1 .. i9 en tant qu'entier, vous constaterez que votre algorithme se brise dans une limite entière. Chaque fois que vous affectez les chaînes d'entrée n1 ou n2 à l'une des variables ix, vous risquez de casser votre code (vous perdez la possibilité d'ajouter des nombres plus grands).

...
If D(i1) > 0 Then i5 = n2 And i1 = i3 + 1 Else If D(i1) = 0 Then i1 = i1 Else i5 = n1  'line 47
...
If D(i1) > 0 Then i6 = n1 And i1 = i3 + 1 Else If D(i1) = 0 Then i1 = i1 Else i6 = n2  'line 51
...
If i3 > i4 Then i5 = n1 Else i5 = n2                                                   'line 55
If i3 > i4 Then i6 = n2 Else i6 = n1                                                   'line 56
...

Si vous souhaitez simplement résoudre un problème (jusqu'à 200 chiffres): utilisez xnumbers (https: // en. wikipedia.org/wiki/XNUMBERS)

Si vous voulez apprendre à coder: utilisez "Option Explicit" et utilisez beaucoup de lignes debug.print.
par exemple Debug.Print "Step x: "; i1; " "; i2; " "; i3; " "; i4; " "; i5; " "; i6; " "; i7; " "; i8; " "; i9

Pourquoi n'ajoutez-vous pas simplement les chaînes d'entrée caractère par caractère?
(Ad (ix) + Bd (iX) et gérer le débordement)

0
simple-solution 27 janv. 2019 à 10:40

Veuillez essayer le code ci-dessous.

Function SumBigNumbers(s1 As String, s2 As String) As String

    Dim n1 As Double, n2 As Double

    n1 = CDbl(s1)
    n2 = CDbl(s2)
    SumBigNumbers = CStr(n1 + n2)
End Function

Le code convertit simplement les deux chaînes de nombres longs en nombres réels, les additionne et convertit le résultat en chaîne. VBA renverra une chaîne d'un nombre en notation scientifique. Notez, cependant, que ce n'est qu'à des fins d'affichage. En interne, c'est un nombre normal (s'il est long).

La conversion en quelque chose de lisible a donc lieu après le calcul du résultat, c'est-à-dire dans la procédure d'appel.

Private Sub CallSum()

    With ActiveSheet.Cells(16, 1)
        .Value = SumBigNumbers("12345678987654321", "34567890123987654")
        .NumberFormat = "0.00"
    End With
End Sub

Il s'avère qu'un simple NumberFormat fera l'affaire. Je me demande simplement si cela fonctionnera avec des nombres beaucoup plus importants comme dans mon exemple.

0
Variatus 28 janv. 2019 à 00:50

Le "théorème d'addition" selon votre image https://drive.google.com/file / d / 1Hny1dCMWUIUwQ19lX82sJ0GaggxydRKC / view en pseudocode:

    'step 1: add every digit of the input strings
    'step 2: for each result above 10:
    'step 3:    reduce by 10 and add 1 to the result of the neighbour

Votre algorithme rompt pour les chaînes plus longues (au-dessus d'environ 300 chiffres):

enter image description here

Public Function AddBig(n1 As String, n2 As String) As String

Dim A(10000) As Integer
Dim B(10000) As Integer
Dim r(10000) As Integer
Dim iCt As Integer
Dim lenCt As Integer
Dim DebugStr As String
Dim Plus1 As Boolean

'Dim n1 As String, n2 As String

'n1 = Range("b3")
'n2 = Range("b6")

    For iCt = Len(n1) To 1 Step -1
        A(iCt) = Mid(n1, Len(n1) - iCt + 1, 1)
    Next iCt

    For iCt = Len(n2) To 1 Step -1
        B(iCt) = Mid(n2, Len(n2) - iCt + 1, 1)
    Next iCt

    lenCt = Application.Max(Len(n1), Len(n2))

    For iCt = lenCt To 1 Step -1
        r(iCt) = A(iCt) + B(iCt)
    Next iCt

    For iCt = 1 To lenCt
        If r(iCt) > 9 Then
            r(iCt) = r(iCt) - 10
            r(iCt + 1) = r(iCt + 1) + 1
            If iCt = lenCt Then Plus1 = True
        End If
        resultStr = r(iCt) & resultStr
    Next iCt
    If Plus1 Then resultStr = "1" & resultStr
    Debug.Print resultStr
    AddBig = resultStr
End Function
0
simple-solution 27 janv. 2019 à 12:46

Le "théorème d'addition" selon votre image https://drive.google.com/file / d / 1Hny1dCMWUIUwQ19lX82sJ0GaggxydRKC / view en pseudocode:

    'step 1: add every digit of the input strings
    'step 2: for each result above 10:
    'step 3:    reduce by 10 and add 1 to the result of the neighbour
0
simple-solution 27 janv. 2019 à 10:55