2011-08-16 14 views
14

Ho un semplice problema che spero di risolvere senza usare VBA ma se è l'unico modo che può essere risolto, così sia.Come estrarre il testo in una stringa di testo

Ho un file con più righe (tutte una colonna). Ogni riga contiene dati simili a questa:

1 7.82E-13> gi | 297848936 | ref | XP_00 | 4-idrossido gi | 297338191 | gb | 23343 | randomrandom

2 5.09E-09> gi | 168010496 | ref | xp_00 | 2-piruvato

ecc ...

Quello che voglio è un modo per estrarre la stringa di numeri che iniziano con "gi |" e termina con un "|". Per alcune righe questo potrebbe significare fino a 5 numeri gi, per altri sarà solo uno.

Quello che mi auguro l'output sarà simile sarebbe qualcosa di simile:

297848936,297338191

ecc ...

risposta

31

Ecco una risposta VBA molto flessibile utilizzando l'oggetto regex. Quello che fa la funzione è estrarre ogni singolo sottogruppo che trova (roba all'interno della parentesi), separato da qualunque stringa tu voglia (il default è ",").È possibile trovare informazioni sulle espressioni regolari qui: http://www.regular-expressions.info/

Si potrebbe chiamare in questo modo, supponendo che prima stringa è in A1:

=RegexExtract(A1,"gi[|](\d+)[|]") 

Poiché questo sembra per tutti occorrenza di "gi |" seguito da una serie di numeri e poi un altro "|", per la prima linea nella sua interrogazione, questo darebbe questo risultato:

297848936, 297338191 

basta eseguire questo in giù la colonna e il gioco è tutto fatto!

+4

Oh uomo, questo è bello. Assolutamente favoloso. Seriamente, perché lo fai? È così utile, ma sono solo curioso di sapere perché le persone danno il loro tempo per qualcosa di simile? È meravigliosamente caritatevole di tutti voi. – Brandon

+15

Sei il benvenuto! Per quanto riguarda il motivo per cui prendo tempo: lo faccio perché gli altri lo fanno. Penso che sia più come la cosa "pagando avanti". Aiuta gli altri per un giorno, mi aiuteranno con un po 'di codice, e le persone che aiuto aiuteranno gli altri, ecc. :) – aevanko

+2

Regex è un ottimo modo per andare. +1 Per me, rispondo alle domande perché è divertente e un ottimo modo per imparare/esercitarsi. Inoltre, come dice Issun, nel corso degli anni ho ottenuto un aiuto straordinario da persone generose e di grande talento nei newsgroup e in altri forum. –

5

Qui è (supponendo dati sono in colonna A)

=VALUE(LEFT(RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2), 
FIND("|",RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2)) -1)) 

Non la più bella formula, b ut lavorerà per estrarre il numero.

Ho appena notato poiché hai due valori per riga con output separati da virgole. Dovrai controllare se c'è una seconda partita, una terza partita ecc. Per farlo funzionare per più numeri per cella.

In riferimento al vostro campione esatto (assumendo 2 valori massimi per cella) il seguente codice funzionerà:

=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)) 

si che è brutto? Una soluzione VBA potrebbe essere migliore per te, ma lascerò questo qui per te.

Per andare fino a 5 numeri, beh, studiare il modello e recurse manualmente nella formula. Ci vorrà molto!

+0

Haha ha funzionato meravigliosamente. Grazie per l'aiuto. Hai ragione, questo diventerà brutto velocemente. Forse dovrei restare con VBA allora? Non mi dispiace davvero, ho solo pensato che le persone potessero trovare le risposte VBA troppo ingombranti: P Ad essere onesti, non sono sicuro di avere idea di cosa stia succedendo in quel codice che hai incluso! Non sono sicuro di dove avrei bisogno di apportare modifiche per poter arrivare a 5 o 7 numeri. – Brandon

+0

Se si sceglie questo approccio, utilizzare al meglio la funzione MID() anziché LEFT e RIGHT. Ciò renderebbe il codice più leggibile. –

2

Probabilmente avrei diviso i dati prima sul delimitatore | utilizzando la procedura guidata Converti testo in colonne. In Excel 2007 che si trova nella scheda Dati, Strumenti dati gruppo e quindi scegliere Testo su colonne. Specificare Altro: e | come delimitatore.

Dai dati di esempio che hai postato sembra che dopo aver fatto questo i numeri saranno tutti nelle stesse colonne in modo da poter quindi eliminare solo le colonne che non vuoi.

+0

Inizialmente l'ho pensato, ma dovrei ricordare che ci sono dei momenti in cui dopo la colonna gb ci sono anche i numeri. Quindi all'interno della stringa di esempio che ho elencato, potresti anche ottenere qualcosa come "randomrandomrandom gb | 13151414 |" Ho appena cambiato il mio post originale per riflettere questo. – Brandon

2

Come gli altri ragazzi hanno presentato la soluzione senza VBA ... presenterò quello che utilizza. Ora, è la tua chiamata a usarlo o no.

Ho appena visto che @Issun ha presentato la soluzione con regex, molto bella! Ad ogni modo, presenterà una soluzione 'modesta' per la domanda, usando solo 'semplice' 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 
+0

Ah ah, anche questo è fantastico. Vedo che VBA può essere un approccio davvero fluido a questo quindi, non me ne sono reso conto. Grazie ancora per il vostro aiuto! – Brandon

Problemi correlati