Как извлечь текст в текстовой строке - PullRequest
16 голосов
/ 17 августа 2011

У меня есть простая проблема, которую я надеюсь решить без использования VBA, но если это единственный способ ее решить, пусть будет так.

У меня есть файл с несколькими строками (все в одном столбце).Каждая строка имеет данные, которые выглядят примерно так:

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 ги цифр, для других это будет просто один.

Я надеюсь, что результат будет выглядеть примерно так:

297848936,297338191

168010496

и т. Д.

Ответы [ 4 ]

43 голосов
/ 17 августа 2011

Вот очень гибкий ответ 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
6 голосов
/ 17 августа 2011

Вот оно (при условии, что данные в столбце 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 чисел, изучите шаблон и повторите процедуру вручную в формуле. ЭТО будет долго!

2 голосов
/ 17 августа 2011

Как другие парни представили решение без 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
2 голосов
/ 17 августа 2011

Я бы, вероятно, сначала разбил данные по разделителю |, используя мастер преобразования текста в столбцы. В Excel 2007 на вкладке Данные , Группа инструментов данных и затем выберите Текст в столбцы . Укажите Прочее: и | в качестве разделителя.

Исходя из опубликованных вами примеров данных, после того, как вы это сделаете, все числа будут в одинаковых столбцах, поэтому вы можете просто удалить ненужные столбцы.

...