Niedawno pisałem pewne makro. Czasami makro się wykrzaczało gdyż wyskakiwał błąd Run-time error 6: Overflow.
Błąd ten oznacza, że chcę do zmiennej przypisać zbyt dużą liczbę. Przykładowo jeśli bym zadeklarował zmienną jako Byte (zmienna tego typu może przyjmować tylko wartości od 0 do 255) a próbował przypisać jej wartość 5 000 to wyskoczy wspomniany błąd. Jednak czasami ten błąd pojawia się zupełnie niespodziewanie. Przeanalizujmy taki oto kod:
Sub TestMnozenia()
Dim Wynik As Long
Wynik = 200 * 200
MsgBox Wynik
End Sub
Efekt?
Skąd się bierze ten błąd? Otóż w VBA jeśli mamy proste mnożenie to VBA tak jakby wynik tego mnożenia „wkłada tak jakby do zmiennej typu Integer” a dopiero potem zawartość tej „tymczasowej zmiennej” przypisuje do mojej zmiennej Wynik, która jest typu Long.
Iloczyn liczb 200*200 daje nam 40 000 a jak wiemy zmienna typu Integer może przyjmować tylko w wartości z zakresu od -32 768 do 32 767. Z kolei w przypadku naszej wynikowej zmiennej typu Long wynik 40 000 spokojnie mieści się w zakresie od -2 147 483 648 do 2 147 483 647.
Uwaga: O dziwo podczas mojego śledztwa okazało się, że w przypadku VB6 (Visual Basic 6) oraz VB.NET wszystko działa tak jak powinno (nie ma tego dziwactwa).
Jak temu zapobiegać?
No cóż musimy jakoś poinformować edytor VBA, że chcemy operować na zmiennych większych niż Integer. Można to zrobić na kilka sposobów:
Użycie „zbyt dużych” typów dla liczb:
Sub TestMnozenia2()
'zamiast:
'Dim a As Integer, b As Integer
'dajmy
Dim a As Long, b As Long
Dim Wynik As Long
a = 200
b = 200
Wynik = a * b
MsgBox Wynik
End Sub
Niejawna konwersja na Long przynajmniej jednego czynnika naszego mnożenia (poprzez dopisanie znaku & za liczbą):
Sub TestMnozenia3()
Dim Wynik As Long
Wynik = 200& * 200
MsgBox Wynik
End Sub
Użycie funkcji CLng
Ja natomiast osobiście zamiast znaku & za liczbą wolę jawnie użyć funkcji CLng, która konwertuje daną liczbę na liczbę typu Long (wystarczy, że tylko jeden z czynników mnożenia będzie opakowany wewnątrz funkcji CLng, to wtedy cały wynik zostaje zwrócony jako wynik typu Long)
Sub TestMnozenia4()
Dim Wynik As Long
Dim a As Integer, b As Integer
a = 200
b = 200
Wynik = a * CLng(b)
MsgBox Wynik
End Sub
A czy Ty znasz jakieś inne dziwactwa języka VBA?