VBAを使用せずに解決したい単純な問題がありますが、それが解決できる唯一の方法である場合は、そうしてください。
複数行(すべて1列)のファイルがあります。各行には、次のようなデータがあります。
1 7.82E-13> gi | 297848936 | ref | XP_00 | 4-水酸化GI | 297338191 | GB | 23343 |ランダムランダム
2 5.09E-09> gi | 168010496 | ref | xp_00 | 2-ピルビン酸塩
等...
「gi |」で始まる数字の文字列を抽出する方法が欲しい「|」で終了します。一部の行では、これは5桁もの数字を意味する場合がありますが、他の行では1つだけになります。
出力が次のようになることを望みます:
297848936,297338191
168010496
等...
これは、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
ここにあります(データが列Aにあると想定)
=VALUE(LEFT(RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2),
FIND("|",RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2)) -1 ))
最も良い式ではありませんが、数値を抽出するのに役立ちます。
カンマで区切られた出力を持つ行ごとに2つの値があるため、私はちょうど気づきました。セルごとに複数の数値で機能するようにするには、2番目の一致、3番目の一致などがあるかどうかを確認する必要があります。
正確なサンプルを参照して(セルごとに最大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は長くなります!
テキストを列に変換ウィザードを使用して、最初に|
区切り文字でデータを分割します。 Dataタブ、Data ToolsグループにあるExcel 2007では、次にText to Columnsを選択します。区切り文字としてその他:および|
を指定します。
投稿したサンプルデータから、これを実行すると、すべての列が同じ列になるため、不要な列を削除できます。
他の人たちが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