jueves, 16 de septiembre de 2021

VBA: El objeto VbScript.RegExp

Estos días pasados he tenido que lidiar, dura pugna!, con el tratamiento y/o recuperación de ciertas partes de uns textos, o cadenas de textos...
Y por desgracia, aplicar la formulación estándar en la hoja de cálculo se hacía extremadamente complejo :-'(

Me acordé entonces de un objeto que se emplea habitualmente a la hora de construir código HTML y páginas web (seguramente en otros campos también), hablo del objeto VbScript.RegExp

Así pues, te recomiendo en primer lugar te familiarices con las Regular Expressions (RegEx o RegExp).
Hay muchas web explicativas, e incluso web para hacer tus test...
Yo te recomiendo esta página de Microsoft.
Allí podrás encontrar bastante documentación y ejemplos para empezar...
Pero mucho más importante.. nos habla de las propiedades, métodos, colecciones del objeto dentro de VBA para Excel.
En el post de hoy te proporcionaré dos ejemplos, aplicados en VBA mediante UDF (funciones personalizadas.

En el primer ejemplo limpiaremos de un código HTML básico todas aquellas etiquetas que NO tienen cierre...
Seguramente sabes que el HTML es un 'lenguaje' (muchos dicen que no lo es) basado en nodos, definidos por inicios y fin de etiquetas.. aunque hay una lista más o menos corta de etiquetas que no se cierran. A modo de ejemplo:
img, br, hr, input, meta, link, html

Y sobre esta lista se basa la primera UDF, ya que deseo eliminar éstas para poder luego dar un tratamiento con objetos de lectura de XML (otro 'lenguaje' similar basado en nodos... pero que siempre finalizan sus etiquetas!).
Por tanto, después de analizar el código HTML, y comprobar que nada relevante aportan esas etiquetas 'especiales', decido eliminarlas... con la siguiente UDF insertada en un módulo estándar del editor de VBA de Excel:
Function QuitaEtiquetasHTMLsinFinal(cadena As String) As String
Dim RegEx As Object
Set RegEx = CreateObject("VbScript.RegExp")

With RegEx
    .Global = True
    .IgnoreCase = True
    .MultiLine = True
    'identificamos cualquiera de las etiquetas de la lista indicada
    'son algunas de las etiquetas (no todas) más frecuentes que nos encontramos
    'en HTML que no tienen fin </...>
    .pattern = "<(br|hr)+>|<(img|br|hr|input|meta|link|html).+>?"
End With

'aplica el método Replace
QuitaEtiquetasHTMLsinFinal = RegEx.Replace(cadena, "")
Set RegEx = Nothing
End Function
Si aplicamos la función sobre el contenido de una celda veríamos...
VBA: El objeto VbScript.RegExp

La explicación del modelo de 'Regular Expressions' empleado en el ejemplo:
"<(br|hr)+>|<(img|br|hr|input|meta|link|html).+>?"
nos dice que identifica o bien el conjunto de las etiquetas:
"<(br|hr)+>
br o hr sin más, entre los símbolos de menor-mayor..
o también el conjunto:
<(img|br|hr|input|meta|link|html).+>?"
que recoge la lista de esas etiquetas que comienzan por < seguidas de cualquier cosa (atributos de cualquier clase)...

En el siguiente ejemplo aplicaremos de manera opcional el método Replace o el método Execute del objeto VbScript.RegEx.
VBA: El objeto VbScript.RegExp

Y el código de la función personalizada, dentro del editor de VBA, en un módulo estándar:
Function TransformaCadenasTexto(cadena As String, modelo As String, Optional Metodo As String)
Dim RegEx As Object
Set RegEx = CreateObject("VbScript.RegExp")

With RegEx
    .Global = True
    .IgnoreCase = True
    .MultiLine = True
    .pattern = modelo
End With

Dim arrDatos() As Variant
'método Execute para obtener una lista de todas las coincidencias...
If IsMissing(Metodo) Or Metodo = "" Or LCase(Metodo) = "execute" Then
    Set coincidencias = RegEx.Execute(cadena)
    'listamos las coincidencias en una array
    For Each Match In coincidencias
        x = x + 1
        ReDim Preserve arrDatos(1 To x) As Variant
        arrDatos(x) = Match.Value
    Next Match
    'para finalmente devolver la array a la función,
    'será por tanto una fórmula matricial..
    TransformaCadenasTexto = arrDatos()
ElseIf LCase(Metodo) = "replace" Then
    'reemplazamos por el mismo valor, pero añadiendo el menor y mayor al inicio y final
    TransformaCadenasTexto = RegEx.Replace(cadena, "<$&>")
    'o sencillamente 'reemplazar por nada' o eliminar... el clásico
    'TransformaCadenasTexto = RegEx.Replace(cadena, "")
Else

End If

Set RegEx = Nothing
End Function
La función permite personalizar como argumento la expresión que necesitemos... y de igual modo, como argumento opcional indicar qué tipo de método emplear...

Las expresiones empleadas en los dos casos siguientes;
- en E7: "i.*?f" identifica subcadenas entre la i y la f
- en E10: "i.*?f" que identifica cualquier otro caracter no contenido en subcadenas entre una i y una f

En E7 la primera función emplea el método Execute, por lo que tras identificar todas las coincidencias las lista... tras pasarla por una array.
En E10 usamos el método Replace para reemplazar esas subcadenas por la expresión "<$&>" que representa cada elemento de la lista de coincidencias...

Una buena ayuda para el tratamiento de textos.
Un último comentario... recomendado activar/habilitar la librería correspondiente: Microsoft VBScript Regular Expressions 5.5 desde el menú del editor de VB, en Herramientas > Referencias

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.