首页
学习
活动
专区
圈层
工具
发布

验证IBAN
EN

Code Review用户
提问于 2020-02-18 12:39:19
回答 1查看 365关注 0票数 8

我在如何验证IBAN上找到了维基百科的解释。由于转换生成的数字会导致VBA中可用的所有数据类型溢出,所以我使用了String

我想让别人审查一下。提前感谢!

维基百科:

  1. 检查IBAN总长度是否符合国家规定。如果不是,IBAN是无效的。
  2. 将四个初始字符移到字符串的末尾。
  3. 用两个数字替换字符串中的每个字母,从而扩展字符串,其中A= 10,B= 11,.,Z= 35。
  4. 将字符串解释为十进制整数,并计算该数字模97的剩余部分。
代码语言:javascript
复制
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
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-02-18 18:56:44

乍一看,您的代码看起来相当短。然而,不管代码有多短,总有一些需要改进的地方。

功能名称和签名都很完美。我想把字符串作为ByVal传递,但这可能不太有效,因为那时可能必须复制字符串。

在开始时将函数的返回值初始化为False是一种很好的方式。对于验证某项内容的函数,任何意外返回都应该说“无效”。这是一个常见的模式,特别是在与安全相关的代码中。

一些变量名以大写字母开头,另一些以小写字母开头。我看不出有什么理由把这两种风格混在一起。您应该用大写字母开始所有变量名,或者用小写字母开始所有变量名。

错误:Lenght应该改为Length。微软IDE似乎缺少拼写检查器。这一点真的应该在微软这一边解决。

变量名tempStr没有说明该变量的用途。更好的名字是ReorderedIBAN

变量名o也很奇怪。对于这里这样的情况,变量名i更常见。这个名称是index的缩写。

变量名newStr令人困惑,因为它的类型不是String,而是Variant

在每一行包含Exit Function之后,我会放一个空行,开始一个新的段落。这更符合逻辑地对代码行进行分组。

不幸的是,这个简单的函数需要一个完整的电子表格来根据国家名称查找IBAN长度。我宁愿用一个字符串来编码所有长度要求,如下所示:

代码语言:javascript
复制
' See https://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country
LengthByCountry = "AL28 AN24 AT20 AZ28 BH22 ..."

给定这个字符串,您可以这样搜索:

代码语言:javascript
复制
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有一个内置函数,用于从字符串的第一个字符中获取字符代码,但我找不到它。通常叫做ASCORDCODE

您也可以在转换数字时直接对数字进行Mod 97计算,而不是一直创建新字符串。这样做的目的是:

代码语言:javascript
复制
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有一个单元测试框架?那就用这个代替。看看这个罗塞塔代码的示例代码,它包含一个半自动测试;您仍然需要手动检查它的输出。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/237492

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档