2011-11-16 16 views
38

Estoy intentando escribir una función para Excel 2010 que tomará una celda de texto no estructurado, busque algo llamado valor de sdi y, si lo encuentra, devuelva ese número. El valor de sdi aparecerá como sdi ####. Lo que quiero es volver a los números que le siguen sepecific SDI y, por lo que si la celda contiene "un texto SDI 1234 algo más de texto" la función devolverá SDI 1234.Devolver una coincidencia de expresión regular en VBA (excel)

Ésta es mi función:

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 

Si no hay un número de serie, nunca ingresa la instrucción if y devuelve diligentemente la cadena vacía. ¡Si hay un número sdi, obtengo #VALUE!

¿Qué me estoy perdiendo?

Sí, VBScript está habilitado. Además, me resulta frustrante utilizar expresiones regex en VBA, y es difícil encontrar información útil en línea. Se apreciarán los enlaces a buenos recursos en línea.

Gracias

Respuesta

61

Es necesario acceder a los partidos con el fin de conseguir en el número SDI. Aquí hay una función que lo hará (suponiendo que solo haya 1 número SDI por celda).

Para la expresión regular, usé "sdi seguido de un espacio y uno o más números". Tuviste "sdi seguido de un espacio y cero o más números". Simplemente puede cambiar el + al * en mi patrón para volver a lo que tenía.

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 

Si una celda puede tener más de un número SDI que desea extraer, aquí está mi función RegexExtract. Puede pasar en un tercer parametro para separar cada partido (como comas separarlos), y que introducir manualmente el patrón de la llamada a la función:

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

Aquí está:

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 

* Por favor, tenga en cuenta que he sacado "RE.IgnoreCase = True" de mi RegexExtract, pero puede agregarlo de nuevo, o incluso agregarlo como un 4º parámetro opcional si lo desea.

+0

¡Gran respuesta, gracias por la función! –

+0

Gracias Issun - su función funciona maravillosamente – TheoRose

+0

+1 muy bien hecho Issun – brettdj

Cuestiones relacionadas