VBA Excel查找string中的最后一个特定实例

我在excel中有一个string列表,如下所示:

a>b>b>d>c>a a>b>c>d b>b>b>d>d>a 

等等

我想从每个string中提取最后一个c或最后一个d,

例如

 a>b>b>d>c>a = C a>b>c>d = d b>b>b>d>d>a = d 

我将如何使用VBA(或者只是在可能的情况下直接使用excel)?

这里是一个数组公式来做同样的事情。 (改变公式以避免“Eh”培根等级指出的原始问题)

 =MID(A1,MAX((MID(A1,ROW(INDIRECT("1:"&LEN(A1))),1)={"c","d"})*ROW(INDIRECT("1:"&LEN(A1)))),1) 

在按下enter同时按住ctrl+shift进入数组公式。 如果你做得正确,Excel会在你可以在配方栏中看到的公式放置大括号{...}

该公式将返回一个#VALUE! 错误,如果在string中既没有c也没有d

在这里输入图像说明

编辑:从你的一些意见,你可能想要使用多个单个字符的话,我提出了以下用户定义函数。 它允许你使用任何长度的单词,而且你也不仅限于两个单词 – 你可以使用任意数量的单词。

你会input一个公式,如:

 =LastOne(A8,"Charlie","Delta") 

要么

 =LastOne(A8,$I1:$I2) 

其中I1和I2包含你想检查的单词。

单词需要用一个既不是字母也不是数字的分隔符分开。

构造一个正则expression式(正则expression式),它由pipe道分隔的| 单词或短语的列表。 pipe道| 在一个正则expression式中,与一个OR相同。 正则expression式开始和结束处的\b表示一个字边界,即数字或字母与非数字或非字母相邻的点,或string的开始或结尾。 因此,实际的分隔符不重要,只要它不是字母或数字。

所有的比赛都放在比赛集合中; 而我们只需要查找比赛中的最后一项。 将有MC.Count匹配,因为这个计数是零基础,我们减去一个来获得最后一场比赛。 这里是代码:

===========================================

 Option Explicit Function LastOne(sSearch As String, ParamArray WordList() As Variant) As String Dim RE As Object, MC As Object Dim sPat As String Dim RNG, C For Each RNG In WordList If IsArray(RNG) Or IsObject(RNG) Then For Each C In RNG sPat = sPat & "|" & C Next C Else sPat = sPat & "|" & RNG End If Next RNG sPat = "\b(?:" & Mid(sPat, 2) & ")\b" Set RE = CreateObject("vbscript.regexp") With RE .Global = True .Pattern = sPat .ignorecase = True If .test(sSearch) = True Then Set MC = .Execute(sSearch) LastOne = MC(MC.Count - 1) End If End With End Function 

===========================================

这里是一个示例截图:

请注意,缺lessWordList单词将导致空白单元格。 如果可以的话,可能会产生一个错误。

在这里输入图像描述

你可以使用如下的Excel公式

为了有助于解释将从一个字母开始,然后将在最后显示完整的公式。

首先findc的出现次数

 = LEN(A1) - LEN(SUBSTITUTE(A1,"c","") 

使用这个位置来replace最后一个唯一的字符($作为例子)

 =SUBSTITUTE(A1,"c","$",LEN(A1) - LEN(SUBSTITUTE(A1,"c",""))) 

接下来find这个独特的人物

 = FIND("$",SUBSTITUTE(A1,"c","$",LEN(A1) - LEN(SUBSTITUTE(A1,"c","")))) 

这给出了最后一个c的位置,现在你可以在中间函数中使用它来返回最后一个c

 = MID(A1,FIND("$",SUBSTITUTE(A1,"c","$",LEN(A1) - LEN(SUBSTITUTE(A1,"c","")))),1) 

最后要考虑到c和d,用max来带回最后一个

 = MID(A1,MAX(IFERROR(FIND("$",SUBSTITUTE(A1,"c","$",LEN(A1) - LEN(SUBSTITUTE(A1,"c","")))),0),IFERROR(FIND("$",SUBSTITUTE(A1,"d","$",LEN(A1) - LEN(SUBSTITUTE(A1,"d","")))),0)),1) 

假设c / d只是例子:

 ?LastEither("b>b>b>d>d>a", "c", "d") d 

运用

 Function LastEither(testStr As String, find1 As String, find2 As String) As String Dim p1 As Long: p1 = InStrRev(testStr, find1) Dim p2 As Long: p2 = InStrRev(testStr, find2) If (p1 > p2) Then LastEither = find1 ElseIf (p2 > 0) Then LastEither = find2 End If End Function 

一般解决scheme

 ?FindLastMatch("b>b>b>d>d>a>q>ZZ", ">", "c", "d") d ?FindLastMatch("b>b>b>d>d>a>q>ZZ", ">", "c", "d", "q") q ?FindLastMatch("b>b>b>d>d>a>q>ZZ>ppp", ">", "c", "d", "ZZ", "q") ZZ 

运用

 Function FindLastMatch(testStr As String, delimiter As String, ParamArray findTokens() As Variant) As String Dim tokens() As String, i As Long, j As Long tokens = Split(testStr, delimiter) For i = UBound(tokens) To 0 Step -1 For j = 0 To UBound(findTokens) If tokens(i) = findTokens(j) Then FindLastMatch = tokens(i) Exit Function End If Next Next End Function 

在VBA中,您可以使用以下简单的逻辑来执行此操作。

 Dim str As String str = "a>b>b>d>c>a" Dim Cet Cet = split(str,">") Dim i as Integer For i= Ubound(Cet) to Lbound(Cet) If Cet(i) = "c" or "d" or "C" or "D" then MsgBox Cet(i) Exit For End if Next i 

假定您的string位于单元格A1中,并且没有使用代字符(〜)字符,则可以在工作表中使用以下代码:

 =IF(IFERROR(FIND("~",SUBSTITUTE(A1,"c","~",LEN(A1)-LEN(SUBSTITUTE(A1,"c","")))),0)>IFERROR(FIND("~",SUBSTITUTE(A1,"d","~",LEN(A1)-LEN(SUBSTITUTE(A1,"d","")))),0),"c","d") 

编辑:
在回应评论时,下面是对这个如何工作的解释。 我也稍微回顾了一下这个公式。 cd的两个公式是相同的,所以两者的解释都适用。 所以,向外工作

 LEN(A1)-LEN(SUBSTITUTE(A1,"c","")) 

这里我们从string中删除c所有实例。 通过比较计算的string和原始string的长度,我们计算出现在原始string中的次数。

 SUBSTITUTE(A1,"c","~",LEN(A1)-LEN(SUBSTITUTE(A1,"c",""))) 

现在我们知道c出现在string中的次数,我们用波浪字符replacec的最后一个出现(这里我们假设在string中没有使用波形符号)。

 FIND("~",SUBSTITUTE(A1,"c","~",LEN(A1)-LEN(SUBSTITUTE(A1,"c","")))) 

然后我们在string中find代字符的位置,这相当于string中最后一个c的位置。

 IFERROR(FIND("~",SUBSTITUTE(A1,"c","~",LEN(A1)-LEN(SUBSTITUTE(A1,"c","")))),0) 

IFERROR包装这个确保我们没有通过公式的错误 – 如果不存在c则将值设置为0,以确保如果我们的string包含c但不包含d (反之亦然),我们仍然得到正确的答案。

然后,我们对d应用相同的计算,并比较两者,看看哪一个会出现在我们的string中。 注意:如果string中既没有c也没有d ,这将给出不正确的答案。