我在如何验证IBAN上找到了维基百科的解释。由于转换生成的数字会导致VBA中可用的所有数据类型溢出,所以我使用了String。
我想让别人审查一下。提前感谢!
维基百科:
Public Function isValidIBAN(IBAN As String) As Boolean
isValidIBAN = False
Dim Country As String
Dim CountryLenght As Integer
Dim tempStr As String
Dim c As String
Dim o As Long
Dim newStr As Variant
Const Modder As Integer = 97
If IBAN = vbNullString Then Exit Function
Country = Left(IBAN, 2)
CountryLenght = 0
On Error Resume Next
CountryLenght = Application.WorksheetFunction.VLookup(Country, Foglio3.Range("A:D"), 4, 0) 'This Search in a table --- Country|someVal|someVal|IBAN lenght
On Error GoTo 0
If Len(IBAN) <> CountryLenght Then Exit Function
'move first 4 chars to right
tempStr = Right(IBAN, Len(IBAN) - 4) & Left(IBAN, 4)
'loop throught single char in tempStr and if not numeric return 10 based number from letter
'use string in place of number to store new-generated "IBAN"
For o = 1 To Len(tempStr)
c = Mid(tempStr, o, 1)
If Not IsNumeric(c) Then
newStr = newStr & CStr(Range(c & 1).Column + 9)
Else
newStr = newStr & CStr(c)
End If
Next o
c = vbNullString
' perform primary school' style division - digit by digit
For o = 1 To Len(newStr)
c = c & Mid(newStr, o, 1)
myStr = myStr & CStr(Int(CLng(c) / Modder))
'if is the last char in str check if mod is 1 - Only fired once
If o = Len(str) Then
isValidIBAN = ((CLng(c) Mod Modder) = 1)
Exit Function
End If
c = IIf(CLng(c) < Modder, c, CLng(c) Mod Modder)
Next o
End Function发布于 2020-02-18 18:56:44
乍一看,您的代码看起来相当短。然而,不管代码有多短,总有一些需要改进的地方。
功能名称和签名都很完美。我想把字符串作为ByVal传递,但这可能不太有效,因为那时可能必须复制字符串。
在开始时将函数的返回值初始化为False是一种很好的方式。对于验证某项内容的函数,任何意外返回都应该说“无效”。这是一个常见的模式,特别是在与安全相关的代码中。
一些变量名以大写字母开头,另一些以小写字母开头。我看不出有什么理由把这两种风格混在一起。您应该用大写字母开始所有变量名,或者用小写字母开始所有变量名。
错误:Lenght应该改为Length。微软IDE似乎缺少拼写检查器。这一点真的应该在微软这一边解决。
变量名tempStr没有说明该变量的用途。更好的名字是ReorderedIBAN。
变量名o也很奇怪。对于这里这样的情况,变量名i更常见。这个名称是index的缩写。
变量名newStr令人困惑,因为它的类型不是String,而是Variant。
在每一行包含Exit Function之后,我会放一个空行,开始一个新的段落。这更符合逻辑地对代码行进行分组。
不幸的是,这个简单的函数需要一个完整的电子表格来根据国家名称查找IBAN长度。我宁愿用一个字符串来编码所有长度要求,如下所示:
' See https://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country
LengthByCountry = "AL28 AN24 AT20 AZ28 BH22 ..."给定这个字符串,您可以这样搜索:
LengthIndex = Index(LengthByCountry, Left(IBAN, 2))
If LengthIndex Mod 5 <> 1 Then Exit Function
CountryLength = Mid(LengthByCountry, LengthIndex + 2, 2)
If Len(IBAN) <> CountryLength Then Exit Function如果您做到了这一点,还可以验证IBAN是否与Wikipedia文章中给出的BBAN格式相匹配。
当循环遍历ReorderedIBAN的字符时,再次使用电子表格查找。我确信VBA有一个内置函数,用于从字符串的第一个字符中获取字符代码,但我找不到它。通常叫做ASC,ORD,CODE。
您也可以在转换数字时直接对数字进行Mod 97计算,而不是一直创建新字符串。这样做的目的是:
Result = 0
For i = 1 To Len(ReorderedIBAN)
ch = Mid(ReorderedIBAN, i, 1)
If IsNumeric(ch) Then
n = Asc(ch) - Asc("0")
Else
n = Asc(ch) - Asc("A") + 10
If n < 1 Or n > 26 Then Exit Function
End If
If Result < 10 Then
Result = (10 * Result + n) Mod 97
Else
Result = (100 * Result + n) Mod 97
End If
Next i上面的代码注意不使用字符串,而是只使用简单的算术操作,因为后者通常比字符串操作更快。
您的代码当前可能正确处理小写字母,也可能不正确处理小写字母。这取决于您从问题中漏掉的Excel电子表格中的部分。如果有疑问,只需在UCase上调用ReorderedIBAN,然后再遍历它。
为了确保代码按预期工作,您应该在代码旁边放置一个Sub TestIsValidIban,其中包含示例IBANs,以及它们是否有效。如果其中任何一个没有验证,就会发生错误。还是VBA有一个单元测试框架?那就用这个代替。看看这个罗塞塔代码的示例代码,它包含一个半自动测试;您仍然需要手动检查它的输出。
https://codereview.stackexchange.com/questions/237492
复制相似问题