我在excel中有一个字符串列表:
ngChange
等
我想从每个字符串中提取最后一个c或最后一个d,无论哪个,
e.g
a>b>b>d>c>a
a>b>c>d
b>b>b>d>d>a
我如何使用VBA(或者如果可能的话,直接excel)这样做?
答案 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
错误。
编辑:从您的一些评论中看到您可能想要使用多个单字字,我会提供以下用户定义函数。它允许你使用任何长度的单词,而且你不仅限于两个单词 - 你可以使用任意数量的单词。
您可以输入以下公式:
=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字会导致空白单元格。如果这是可取的,可能会产生错误。
答案 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")
修改强>
在回应评论时,这里解释了它是如何工作的。我已经把这个公式稍微重新整理了一下。 c
和d
的两个公式是相同的,因此解释适用于两者。所以,向外工作
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