2011-11-16 1 views
38

Sto provando a scrivere una funzione per Excel 2010 che prenderà una cella di testo non strutturato, cercare qualcosa chiamato valore sdi e, se trovato, restituire quel numero. Il valore sdi apparirà come sdi ####. Quello che voglio è quello di restituire sdi ei numeri sepecific che lo seguono, quindi, se la cella contiene "un testo sdi 1234 ancora un po 'di testo" la funzione restituirà sdi 1234.Restituzione di una corrispondenza regolare in VBA (excel)

Questa è la mia funzione:

Function SdiTest(LookIn As String) As String 
    Dim temp As String 
    Dim STA As Object 
    temp = "" 

    Set SDI = CreateObject("VBScript.RegExp") 
    SDI.IgnoreCase = True 
    SDI.Pattern = "sdi [1-9]*" 
    SDI.Global = True 

    If SDI.Test(LookIn) Then 
    temp = SDI.Execute(LookIn) 
    End If 

    SdiTest = temp 
End Function 

Se non c'è alcun numero SDI non entra mai nella dichiarazione if e restituisce doverosamente la stringa vuota. Se c'è un numero sdi ottengo #VALORE!

Cosa mi manca?

Sì, VBScript è abilitato. Inoltre, trovo frustrante usare regex in VBA e difficile trovare informazioni utili online. I collegamenti a buone risorse online sarebbero apprezzati.

Grazie

risposta

61

È necessario accedere alle partite al fine di ottenere il numero SDI. Ecco una funzione che lo farà (supponendo che ci sia solo 1 numero SDI per cella).

Per la regex, ho usato "sdi seguito da uno spazio e uno o più numeri". Hai avuto "sdi seguito da uno spazio e zero o più numeri". Puoi semplicemente cambiare il + in * nel mio pattern per tornare a quello che avevi.

Function ExtractSDI(ByVal text As String) As String 

Dim result As String 
Dim allMatches As Object 
Dim RE As Object 
Set RE = CreateObject("vbscript.regexp") 

RE.pattern = "(sdi \d+)" 
RE.Global = True 
RE.IgnoreCase = True 
Set allMatches = RE.Execute(text) 

If allMatches.count <> 0 Then 
    result = allMatches.Item(0).submatches.Item(0) 
End If 

ExtractSDI = result 

End Function 

Se una cella può avere più di un numero SDI che si desidera estrarre, qui è la mia funzione RegexExtract. È possibile passare in un terzo paramter per separare ogni partita (come loro da virgole separati), e inserire manualmente il pattern nella chiamata di funzione reale:

Ex) =RegexExtract(A1, "(sdi \d+)", ", ") 

Ecco:

Function RegexExtract(ByVal text As String, _ 
         ByVal extract_what As String, _ 
         Optional seperator As String = "") As String 

Dim i As Long, j As Long 
Dim result As String 
Dim allMatches As Object 
Dim RE As Object 
Set RE = CreateObject("vbscript.regexp") 

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 & seperator & allMatches.Item(i).submatches.Item(j) 
    Next 
Next 

If Len(result) <> 0 Then 
    result = Right(result, Len(result) - Len(seperator)) 
End If 

RegexExtract = result 

End Function 

* Si prega di si noti che ho rimosso "RE.IgnoreCase = True" dal mio RegexExtract, ma è possibile aggiungerlo nuovamente o aggiungerlo come parametro facoltativo 4 se lo si desidera.

+0

Ottima risposta, grazie per la funzione! –

+0

Grazie Issun - la tua funzione funziona meravigliosamente – TheoRose

+0

+1 ben fatto Issun – brettdj