如何在Excel中从具有特定条件的string中查找子string
我有这样的logging
A Result Hello AP#12/22 Welcome AP#12 Thanks AP#123-21 AP#123 No problem AP#111 AP#111
所以你可以看到我需要从string的AP代码。 它不能包含 – 或/部分。
注意:
AP代码可以是任何数字的数字
它可以出现在最后或开始
AP代码可以跟随/或 – 或任何其他特殊符号,如:或任何其他。
所以我需要一个通用的公式,而不是检查每个特殊字符(/, – ,:)来获取AP代码。
我想实现这一点,而不使用VB。
可能不是最有效的解决scheme…但这是一种没有VBA的方法:(为了可读性,添加了换行符)
= "AP#"&MID(MID(A1,FIND("AP#",A1)+3,999),1, MAX((ISNUMBER(MID(MID(A1,FIND("AP#",A1)+3,999),{1,2,3},1)+0)+0)*{1,2,3}))
编辑
稍微好一些的解决scheme:
= MID(A1,FIND("AP#",A1), MAX(ISNUMBER(MID(MID(A1,FIND("AP#",A1)+3,999),{1,2,3},1)+0)*{1,2,3})+3)
编辑 (再次)
正如在评论中指出的,这并没有考虑到AP#1-1
这样的东西。 这里是更新的公式,将考虑到这一点:
= MID(A1,FIND("AP#",A1),IFERROR(MATCH(FALSE, ISNUMBER(MID(MID(A1,FIND("AP#",A1)+3,3),{1,2,3},1)+0),0),4)+2)
按照要求,这是这个公式的工作原理。 我会一步一步分解它。 这是一个相当长的解释,但如果你只是一步一个脚印,我认为你应该能够理解整个公式。 我将从内部解释发生了什么事情。
FIND("AP#",A1)
返回FIND("AP#",A1)
的字符索引号,其中AP#
的第一个实例出现在A1
。
为了简单起见,我将在下一步中将FIND("AP#",A1)
称为<x1>
。
MID(A1,<x1>+3,3)
返回在AP#
后立即出现的A1
中的3个字符。 它只返回3个字符,因为从原来的问题,你说最多3个号码可以出现在AP#
。
(快速注意:本来我把公式的这部分作为MID(A1,<x1>+3,999)
但做了这个解释之后,我意识到999
可以减less到MID(A1,<x1>+3,999)
仍然可以工作,只是3
更简单使配方更有效。)
我将在下一步中将这个值MID(A1,<x1>+3,3)
称为<x2>
。
MID(<x2>,{1,2,3},1)
实质上是将3个字符的string<x2>
转换为3个string的数组 ,每个string1个字符长。 换句话说,如果<x2>
是(例如) "1-2"
,则意味着MID(<x2>,{1,2,3},1)
是{"1","-","2"}
。 为了分别分析每个字符,需要将3个字符的string转换为1×3的单个字符数组。
我将在下一步中将MID(<x2>,{1,2,3},1)
称为<x3>
。
看起来像一个简单的步骤,但这里有很多事情要做。 请记住, <x3>
仍然是一个string数组,而不是数字 (即使它们看起来像数字)。 +0
会将所有看起来像数字的string转换为数字,并将所有看起来不像数字的string转换为错误值。 (在这种情况下, #VALUE!
)
坚持我们同样的例子, {"1","-","2"}+0
将等于{1,#VALUE!,2}
。
我将在下一步中将<x3>+0
称为<x4>
。
MATCH(FALSE,ISNUMBER(<x4>),0)
返回<x4>
的第一个索引,它不是一个数字。 这里的想法是find第一个非数字的索引,然后包括所有索引(减一)。
坚持我们的例子, MATCH(FALSE,ISNUMBER({1,#VALUE!,2}),0)
将返回2
,因为{1,#VALUE!,2}
中的第二个索引是第一个索引一个号码。
我将在下一步中将MATCH(FALSE,ISNUMBER(<x4>),0)
称为<x5>
。
<x4>
中的所有值都可能是数字,在这种情况下<x5>
将返回错误,因为它找不到非数字的匹配。 IFERROR(<x5>,4)
解决了这个问题。 如果<x5>
中的所有值都是数字,则返回值4
。 返回4
的原因是因为我们基本上说AP#
后面的所有3个字符都是数字,所以AP#
之后我们不考虑的第一个索引就是第四个索引。
我将在下一步中将IFERROR(<x5>,4)
称为<x6>
。
<x6>+2
可能看起来像一个奇怪的计算,它是,所以我会写一个不同的方式,会更有意义: (<x6>-1)+3
请记住<x6>
代表的是:这是AP#
后 3个string中出现的第一个非数字的索引。 因此, <x6>-1
是在AP#
之后包含的字符数。
现在,为什么要添加3? (<x6>-1)+3
必须在AP#
本身包含3个字符。 这将在下一步中有意义。
我将在下一步中将<x6>+2
称为<x7>
。
MID(A1,FIND(AP#,A1),<x7>)
返回stringA1
的一部分,从AP#
中的A
开始,跨越<x7>
字符。 而且<x7>
多大? 然而, AP#
代码中有很多数字,再加上3(再次,我们必须加3来包含3个AP#
字符本身在计算中。)
这是整个计算。
想想看,你可能想要在整个计算过程中包装一个IFERROR
,以处理在string中找不到AP#
的情况,例如:
= IFERROR(MID(A1,FIND("AP#",A1),IFERROR(MATCH(FALSE, ISNUMBER(MID(MID(A1,FIND("AP#",A1)+3,3),{1,2,3},1)+0),0),4)+2),"no match")
但是真的那是你的电话。 我不确定这是否有必要。
考虑以下用户定义的function:
Public Function FindAPcode(s As String) As String Dim L As Long, CH As String, i As Long, j As Long FindAPcode = "" L = Len(s) If L = 0 Then Exit Function j = InStr(1, s, "AP#") + 3 If j = 3 Then Exit Function FindAPcode = "AP#" For i = j To L CH = Mid(s, i, 1) If IsNumeric(CH) Then FindAPcode = FindAPcode & CH Else Exit Function End If Next i End Function
用户定义的函数(UDF)非常易于安装和使用:
- ALT-F11调出VBE窗口
- ALT-I ALT-M打开一个新的模块
- 粘贴东西,closuresVBE窗口
如果保存工作簿,则UDF将随之保存。 如果您在2003年以后使用的是Excel版本,则必须将该文件另存为.xlsm而不是.xlsx
要删除UDF:
- 如上所示调出VBE窗口
- 清除代码
- closuresVBE窗口
从Excel中使用UDF:
= myfunction的(A1)
要了解有关macros的更多信息,请参阅:
http://www.mvps.org/dmcritchie/excel/getstarted.htm
和
http://msdn.microsoft.com/en-us/library/ee814735(v=office.14).aspx
有关UDF的具体信息,请参阅:
http://www.cpearson.com/excel/WritingFunctionsInVBA.aspx
macros必须启用这个工作!