我有一个简单的问题,我希望在不使用VBA的情况下解决,但如果这是解决问题的唯一方法,那就这样吧。
我有一个包含多行的文件(所有一列)。每行的数据如下所示:
1 7.82E-13> gi | 297848936 | ref | XP_00 | 4-氢氧化物gi | 297338191 | gb | 23343 | randomrandom
2 5.09E-09> gi | 168010496 | ref | xp_00 | 2 - 丙酮酸盐
等...
我想要的是一些提取以“gi |”开头的数字串的方法并以“|”结束。对于某些行,这可能意味着多达5个gi数字,而对于其他行,它只是一个。
我希望输出看起来像是:
297848936,297338191
168010496
等...
答案 0 :(得分:43)
这是一个使用regex对象的非常灵活的VBA答案。该函数所做的是提取它找到的每个子组匹配(括号内的东西),用你想要的任何字符串分隔(默认为“,”)。您可以在此处找到有关正则表达式的信息:http://www.regular-expressions.info/
假设第一个字符串在A1:
中,你会这样称呼它=RegexExtract(A1,"gi[|](\d+)[|]")
因为这会查找“gi |”的所有出现然后是一系列数字,然后是另一个“|”,对于你问题的第一行,这会给你这个结果:
297848936, 297338191
只需在列中运行即可完成所有操作!
Function RegexExtract(ByVal text As String, _
ByVal extract_what As String, _
Optional separator As String = ", ") As String
Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
Dim i As Long, j As Long
Dim result As String
RE.pattern = extract_what
RE.Global = True
Set allMatches = RE.Execute(text)
For i = 0 To allMatches.count - 1
For j = 0 To allMatches.Item(i).submatches.count - 1
result = result & (separator & allMatches.Item(i).submatches.Item(j))
Next
Next
If Len(result) <> 0 Then
result = Right$(result, Len(result) - Len(separator))
End If
RegexExtract = result
End Function
答案 1 :(得分:6)
这是(假设数据在A列中)
=VALUE(LEFT(RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2),
FIND("|",RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2)) -1 ))
不是最好的公式,但它可以提取数字。
我刚注意到,因为每行有两个值,输出用逗号分隔。您需要检查是否存在第二个匹配,第三个匹配等,以使其适用于每个单元格的多个数字。
参考您的确切样本(假设每个单元格最多2个值),以下代码将起作用:
=IF(ISNUMBER(FIND("gi|",$A1,FIND("gi|", $A1)+1)),CONCATENATE(LEFT(RIGHT($A1,LEN($A1)
- FIND("gi|",$A1) - 2),FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2)) -1 ),
", ",LEFT(RIGHT($A1,LEN($A1) - FIND("gi|",$A1,FIND("gi|", $A1)+1)
- 2),FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1,FIND("gi|", $A1)+1) - 2))
-1 )),LEFT(RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2),
FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2)) -1 ))
丑陋怎么样? VBA解决方案对您来说可能更好,但我会留在这里为您服务。
最多可以输入5个数字,然后研究模式并在公式中手动递归。 IT会很长!
答案 2 :(得分:2)
我可能首先使用convert text to columns向导在|
分隔符上拆分数据。
在数据选项卡,数据工具组中的Excel 2007中,然后选择文本到列。指定其他:和|
作为分隔符。
从您发布的示例数据看起来,在执行此操作之后,数字将全部位于相同的列中,因此您可以删除不需要的列。
答案 3 :(得分:2)
正如其他人提出没有VBA的解决方案......我会展示一个有用的解决方案。现在,您是否打算使用它。
刚看到@Issun用正则表达式提供了解决方案,非常好!无论哪种方式,只会使用“普通”VBA来提出问题的“适度”解决方案。
Option Explicit
Option Base 0
Sub findGi()
Dim oCell As Excel.Range
Set oCell = Sheets(1).Range("A1")
'Loops through every row until empty cell
While Not oCell.Value = ""
oCell.Offset(0, 1).Value2 = GetGi(oCell.Value)
Set oCell = oCell.Offset(1, 0)
Wend
End Sub
Private Function GetGi(ByVal sValue As String) As String
Dim sResult As String
Dim vArray As Variant
Dim vItem As Variant
Dim iCount As Integer
vArray = Split(sValue, "|")
iCount = 0
'Loops through the array...
For Each vItem In vArray
'Searches for the 'Gi' factor...
If vItem Like "*gi" And UBound(vArray) > iCount + 1 Then
'Concatenates the results...
sResult = sResult & vArray(iCount + 1) & ","
End If
iCount = iCount + 1
Next vItem
'And removes trail comma
If Len(sResult) > 0 Then
sResult = Left(sResult, Len(sResult) - 1)
End If
GetGi = sResult
End Function