VBA Excel查找字符串中的最后一个特定实例

时间:2016-02-12 10:09:47

标签: string excel vba

我在excel中有一个字符串列表:

ngChange

我想从每个字符串中提取最后一个c或最后一个d,无论哪个,

e.g

a>b>b>d>c>a

a>b>c>d

b>b>b>d>d>a

我如何使用VBA(或者如果可能的话,直接excel)这样做?

5 个答案:

答案 0 :(得分:2)

您可以使用excel公式,如下所示

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

首先找出c

的出现次数
= LEN(A1) - LEN(SUBSTITUTE(A1,"c","")

使用此位置用唯一字符($作为示例)替换最后一个c

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

接下来找到这个独特的角色

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

这给出了最后一个c的位置,现在你可以在mid函数中使用它来返回最后一个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)

答案 1 :(得分:2)

假设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

一般解决方案:

?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

答案 2 :(得分:2)

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

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

在点击ctrl+shift时按住enter输入数组公式。如果您正确执行此操作,Excel将在公式栏中显示大括号{...}

如果字符串中既没有#VALUE!也没有c,则公式将返回d错误。

enter image description here

编辑:从您的一些评论中看到您可能想要使用多个单字字,我会提供以下用户定义函数。它允许你使用任何长度的单词,而且你不仅限于两个单词 - 你可以使用任意数量的单词。

您可以输入以下公式:

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

=LastOne(A8,$I1:$I2)

其中I1和I2包含您要检查的单词。

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

构造正则表达式(正则表达式),其由管道分隔的|单词或短语列表组成。正则表达式中的管道|OR相同。正则表达式开头和结尾的\b表示单词边界 - 即数字或字母与非数字或非字母或字符串的开头或结尾相邻的点。因此,实际的分隔符无关紧要,只要它不是字母或数字即可。

所有比赛都放在比赛中;我们只需要查找比赛中的最后一项。将有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

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

以下是截图示例:

请注意,缺少WordList字会导致空白单元格。如果这是可取的,可能会产生错误。

enter image description here

答案 3 :(得分:1)

假设你的字符串在单元格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",""))

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

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

现在我们知道c出现在字符串中的次数了,我们 用波形符替换最后一次出现的c(这里我们假设波形符号不在字符串中使用)。

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

然后我们在字符串中找到波浪号的位置,这相当于字符串中最后一个c的位置。

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

IFERROR中包含此内容可确保我们不会在公式中出现错误 - 如果不存在c,则将值设置为0可确保我们仍能获得正确答案字符串包含c但不包含d(反之亦然)。

然后我们将相同的计算应用于d并比较两者以查看哪个稍后出现在我们的字符串中。注意:如果字符串中既没有c也没有d,则会给出错误答案。

答案 4 :(得分:1)

在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