从 Excel 单元格中提取固定长度的数字

dot*_*t12 3 excel vba excel-formula

一些类似命名的线程,但仍然无法解决我的问题。我需要从 Excel 字符串(在我的场景中为 8 位数字)中提取一个固定长度的 NUMBER 值。为此提供了以下 Excel 公式:

=MID(A1,FIND("--------",SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1,"0","-"),"1","-"),"2","-"),"3","-"),"4","-"),"5","-"),"6","-"),"7","-"),"8","-"),"9","-")),8)
Run Code Online (Sandbox Code Playgroud)

它可以完成这项工作,但是我对此有两个问题:

  1. 最重要的是 - 我正在寻找完全匹配。虽然它确实提取了它找到的第一个 8 位数字序列,但我真的只需要8 位数字,这意味着应该忽略 9 位(或更长)数字(因为 7 位数字已经是)。此公式还从较长的数字中提取前 8 位数字。

  2. 不太重要,但只查找以 1 开头的数字会很好。所以,真的只是想提取这个:1??????? 作为数值。因此,像“一12891212一”或“一12891212一”应该被提取,同时12891212 0A或23456789不应该。

如果合理可行,与 VBA 相比,我更喜欢基于 Excel 公式的方法。任何帮助深表感谢!

Jvd*_*vdV 5

这可以通过公式来完成,但这一切都取决于您的 Excel 版本:

在此处输入图片说明


1) Excel 2016,你仍然可以使用一个公式:

公式B1

=IFERROR(MID(A1,MAX((MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1)="1")*(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),8)))*(NOT(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1)))+8,1))))*(NOT(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1)))-1,1))))*(ROW(A$1:INDEX(A:A,LEN(A1))))),8),"Nothing found")
Run Code Online (Sandbox Code Playgroud)

注意:这是一个数组公式,需要通过CtrlShiftEnter


2) Excel 2019,使用CONCATFILTERXML

公式B1

=IFERROR(FILTERXML("<t><s>"&CONCAT(IF(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1)),MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1),"</s><s>"))&"</s></t>","//s[starts-with(., '1') and string-length(.) =8]"),"Nothing Found")
Run Code Online (Sandbox Code Playgroud)

注意:这是一个数组公式,需要通过CtrlShiftEnter


3) Excel 365,使用前面提到的功能,但包括SEQUENCE

公式B1

=IFERROR(FILTERXML("<t><s>"&CONCAT(IF(ISNUMBER(--MID(A1,SEQUENCE(LEN(A1)),1)),MID(A1,SEQUENCE(LEN(A1)),1),"</s><s>"))&"</s></t>","//s[starts-with(., '1') and string-length(.) =8]"),"Nothing Found")
Run Code Online (Sandbox Code Playgroud)

XPATH公式的一部分,以实际查询的照顾,寻找与“1”开始,是“8”,总长度的字符串。这甚至可以处理像'abc123456789abc12345678abc29876543'这样的字符串返回'12345678'。

如果您喜欢FILTERXMLXPATH,那么您可能会发现很有趣。


4) VBA:如果你必须使用 VBA,我想 UDF 是一个不错的选择。就像是:

Function GetStr(str As String, pat As String) As String

With CreateObject("vbscript.regexp")
    .Pattern = pat
    .Global = True
    If .Test(str) = True Then
        GetStr = .Execute(str)(0).Submatches(0)
    Else
        GetStr = "Nothing found"
    End If
End With

End Function
Run Code Online (Sandbox Code Playgroud)

您可以B1按照=GetStr(A1,"(?:^|\D)(1\d{7})(?:\D|$)"). 这是使用正则表达式。如果您有兴趣并想了解更多信息,那么对您来说很有趣。

我故意将模式留在 UDF 之外,您可能想要更改它。当前模式可以在这个在线Demo 中看到,引擎将从左到右寻找:

  • (?: - 第一个非捕获组
    • ^|\D - 起始字符串 ancor 或数字以外的任何内容。
    • ) - 关闭第一个非捕获组。
  • ( - 第一个捕获组。
    • 1\d{7} - 搜索文字 1 后跟 7 位数字。
    • ) - 关闭第一个捕获组。
  • (?: - 第二非捕获组
    • \D|$ - 除了数字或结束字符串 ancor 以外的任何内容。
    • ) - 关闭第二个非捕获组。

在此处输入图片说明