这是一个复杂的公式
- 将字符串拆分为单个单词的数组,由
space 或underscore 分隔
- 查找与模式
nnnxnnn 匹配的单词,该模式定义为:
- 以数字开头
- 后跟小写
x(如果 x 可能是任何一种情况,请在下面的公式中将 FIND 替换为 SEARCH)
- 以数字结尾
- 该函数将返回字符串中与该模式匹配的最后一个单词。
公式包括几个“子公式”
我们将字符串按space 和underscore 拆分成一个单词数组:
=TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99))
在上面SEQ是一个命名公式:(Formulas ► Define Name)
=IF((ROW(INDEX(Sheet1!$1:$65536,1,1):INDEX(Sheet1!$1:$65536,255,1))-1)*99=0,1,(ROW(INDEX(Sheet1!$1:$65536,1,1):INDEX(Sheet1!$1:$65536,255,1))-1)*99)
该公式生成一系列数字1,99,198,297, ...,这为第一个公式中的MID 函数提供了一个很好的起点。
然后我们使用 LEFT 和 MID 函数来查找包含 x 并且在 x 之前和之后有数字的单词
ISNUMBER(-LEFT(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))-1))
ISNUMBER(-MID(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))+1,99)))
将这两个公式相乘将返回一个由 0 和 1 组成的数组,表示匹配或不匹配模式的单词。
1/(...)
然后将返回一个包含1 或DIV/0 错误的数组。
使用LOOKUP 的向量形式将返回我们的字符串数组中的值,该值与我们的模式匹配数组中的匹配位置相同。
=LOOKUP(2,1/(ISNUMBER(-LEFT(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))-1))*ISNUMBER(-MID(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))+1,99))),TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))
我会注意到,使用 VBA 和正则表达式,相同的模式可以表示为 \d+x\d+
用户定义的函数可以用来完成同样的事情,一旦你流利了,只需要一小部分时间来设计;
Option Explicit
Function ExtractMeasure(S As String) As String
Dim RE As Object, MC As Object
Set RE = CreateObject("vbscript.regexp")
With RE
.Pattern = "\d+x\d+"
.Global = False
.ignorecase = False 'Case Sensitive
If .test(S) = True Then
Set MC = .Execute(S)
ExtractMeasure = MC(0)
End If
End With
End Function