J'ai un problème simple que j'espère résoudre sans utiliser VBA, mais si c'est la seule façon de le résoudre, qu'il en soit ainsi.
J'ai un fichier avec plusieurs lignes (toutes une colonne). Chaque ligne contient des données qui ressemblent à ceci:
1 7.82E-13> gi | 297848936 | réf | XP_00 | 4-hydroxyde gi | 297338191 | fr | 23343 | aléatoire
2 5.09E-09> gi | 168010496 | réf | xp_00 | 2-pyruvate
etc...
Ce que je veux, c'est un moyen d'extraire la chaîne de nombres commençant par "gi |" et terminez par un "|". Pour certaines lignes, cela peut signifier jusqu'à 5 chiffres gi, pour d'autres, ce n'en sera qu'un.
J'espère que la sortie ressemblera à quelque chose comme:
297848936,297338191
168010496
etc...
Voici une réponse VBA très flexible utilisant l'objet regex. La fonction extrait toutes les correspondances de sous-groupes qu'elle trouve (éléments à l'intérieur de la parenthèse), séparés par la chaîne de votre choix (la valeur par défaut est ","). Vous pouvez trouver des informations sur les expressions régulières ici: http://www.regular-expressions.info/
Vous l'appeleriez comme ceci, en supposant que la première chaîne est en A1:
=RegexExtract(A1,"gi[|](\d+)[|]")
Puisque cela recherche toute occurrence de "gi |" suivi d'une série de chiffres puis d'un autre "|", pour la première ligne de votre question, cela vous donnerait ce résultat:
297848936, 297338191
Exécutez simplement cela dans la colonne et vous avez terminé!
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
La voici (en supposant que les données se trouvent dans la colonne A)
=VALUE(LEFT(RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2),
FIND("|",RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2)) -1 ))
Ce n'est pas la meilleure formule, mais cela fonctionnera pour extraire le nombre.
Je viens de remarquer que vous avez deux valeurs par ligne avec une sortie séparée par des virgules. Vous devrez vérifier s'il existe une deuxième correspondance, une troisième correspondance, etc. pour le faire fonctionner pour plusieurs numéros par cellule.
En référence à votre échantillon exact (en supposant 2 valeurs maximum par cellule), le code suivant fonctionnera:
=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 ))
Comment est-ce pour laid? Une solution VBA peut être meilleure pour vous, mais je vais laisser cela ici pour vous.
Pour aller jusqu'à 5 nombres, eh bien, étudiez le modèle et recursez manuellement dans la formule. Ça va devenir long!
Je diviserais probablement les données d'abord sur le |
délimiteur à l'aide de l'assistant de conversion de texte en colonnes. Dans Excel 2007 qui se trouve dans l'onglet Données, Outils de données puis choisissez Texte vers colonnes. Spécifiez Autre: et |
comme délimiteur.
À partir des exemples de données que vous avez publiés, il semble qu'après cela, les chiffres seront tous dans les mêmes colonnes afin que vous puissiez ensuite simplement supprimer les colonnes que vous ne voulez pas.
Comme les autres gars ont présenté la solution sans VBA ... je présenterai celle qui l'utilise. Maintenant, c'est votre appel à l'utiliser ou non.
Je viens de voir que @Issun a présenté la solution avec regex, très sympa! Quoi qu'il en soit, présentera une solution "modeste" à la question, en utilisant uniquement du VBA "simple".
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