将 5 位数字从一列提取到另一列

Extract 5-digit number from one column to another

在 Excel 2010 年,我需要帮助将 5 位数字从一列提取到另一列。这些数字可以位于字符串的任何位置(字符串的开头、中间的任何位置,或在最后)。它们可以在方括号或引号内,例如:

(15478) or "15478" or '15478' or [15478]

我需要忽略任何少于 5 位的数字,包括以 1 个或多个前导零开头的数字(如 00052、00278 等),并确保将前导零复制到下一列。有人可以帮我创建公式或 UDF 吗?

我刚刚为您编写了这个 UDF,很基础但会做到...

它会找到一个字符串中的前 5 个连续数字,非常粗略的错误检查,所以如果有任何不对它就说错误

Public Function GET5DIGITS(value As String) As String
    Dim sResult As String
    Dim iLen As Integer
    sResult = ""
    iLen = 0

    For i = 1 To Len(value)       
        If IsNumeric(Mid(value, i, 1)) Then
            sResult = sResult & Mid(value, i, 1)
            iLen = iLen + 1
        Else
            sResult = ""
            iLen = 0
        End If
        If iLen = 5 Then Exit For
    Next

    If iLen = 5 Then
        GET5DIGITS = Format(sResult, "00000")
    Else
        GET5DIGITS = "Error"
    End If
End Function

这是一个基于公式的替代方法,它将提取单元格 A1 中找到的前 5 位数字。在大多数情况下,我倾向于更喜欢相当简单的公式解决方案而不是 VBA,因为公式更便于携带。该公式是一个数组公式,因此必须使用 Ctrl+Shift+Enter 输入。这个想法是将字符串分成每一个可能的 5 个字符块并测试每个字符和 return 第一个匹配项。

=MID(A1,MIN(IF(NOT(ISERROR(("1"&MID(A1,ROW(INDIRECT("R1C[1]:R"&(LEN(A1)-4)&"C[1]",FALSE)),5)&".1")*1))*ISERROR(MID(A1,ROW(INDIRECT("R1C[1]:R"&(LEN(A1)-4)&"C[1]",FALSE))+5,1)*1)*ISERROR(MID(A1,ROW(INDIRECT("R1C[1]:R"&(LEN(A1)-4)&"C[1]",FALSE))-1,1)*1),ROW(INDIRECT("R1C[1]:R"&(LEN(A1)-4)&"C[1]",FALSE)),9999999999)),5)

我们来分解一下。首先,我们有一个表达式,我用了两次 return 一个数字数组,从 1 到 4 小于初始文本的长度。因此,如果您有一个长度为 10 的字符串,则以下内容将 return {1,2,3,4,5,6}。以下公式将被称为rowlist。我使用 R1C1 符号来避免潜在的循环引用。

ROW(INDIRECT("R1C[1]:R"&(LEN(A1)-4)&"C[1]",FALSE))

接下来我们将使用该数组将文本拆分为 5 个字母块的数组并测试每个块。正在执行的测试是在前面加上“1”并附加“.1”,然后验证块是否为数字。 prepend 和 append 消除了白色 space 或小数的可能性。然后我们可以检查前面的字符和后面的字符以确保它们不是数字。以下公式将被称为 isnumarray.

NOT(ISERROR(("1"&MID(A1,rowlist,5)&".1")*1))
*ISERROR(MID(A1,rowlist+5,1)*1)
*ISERROR(MID(A1,rowlist-1,1)*1)

接下来我们需要通过 return 从 rowlist 公式和 returning 大量的不匹配项。然后我们可以使用 MIN 函数来获取第一个匹配项。以下简称为minindex.

MIN(IF(isnumarray,rowlist,9999999999))

最后,我们需要获取由 MIN 函数编辑的从索引 return 开始的数字字符串。

MID(A1,minindex,5)

以下 UDF 将 return 字符串中的前五位数字,包括任何前导零。如果您需要检测是否有一个以上的五位数字,则修改是微不足道的。如果没有五位数,它将 return 出现 #VALUE! 错误。

Option Explicit
Function FiveDigit(S As String, Optional index As Long = 0) As String
    Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
With RE
    .Pattern = "(?:\b|\D)(\d{5})(?:\b|\D)"
    .Global = True
        FiveDigit = .Execute(S)(index).submatches(0)
End With
End Function

正如您从 Mark 和我之间的讨论中看到的那样,您的一些规格不清楚。但是如果你想排除小数,当小数部分有五位数字时,那么我上面代码中的正则表达式模式应该改变:

.Pattern = "(?:\d+\.\d+)|(?:\b|\D)(\d{5})(?:\b|\D)"