Saltar al contenido

Eliminar etiquetas HTML y extraer texto en Power Query

Eliminar etiquetas HTML y extraer texto en Power Query

Escrito por

en

,

Eliminar etiquetas HTML y extraer texto en Power Query

TL;DR: El método más confiable para eliminar etiquetas HTML en Power Query es Html.Table([Columna], {{"texto", ":root"}}){0}[texto], que usa el parser HTML nativo del motor M para extraer solo el texto visible. Para nulos o HTML malformado, envolvelo en try ... otherwise null. Los métodos basados en Text.Replace funcionan para casos simples, pero fallan con HTML anidado o entidades encodeadas.


No hemos podido validar tu suscripción.
Tu PDF va en camino — revisa tu correo

Tu guía de Power Query gratis

Cuando conectás Power BI a fuentes externas como SharePoint, Salesforce, Dynamics, sistemas de tickets o bases de datos heredadas, es habitual encontrar columnas de texto donde el contenido llegó desde un editor de texto enriquecido. El resultado en la fuente es algo así:

<div class="ExternalClass5796EA3C"><p><strong>Proyecto Alpha</strong> - Fase 2</p>
<p>Estado: <em>En revisión</em>. Fecha límite: 15/07/2026.&#160;</p>
<p>Contacto: <a href="mailto:ana@empresa.com">Ana García</a></p></div>

Lo que necesitás en tu modelo de Power BI es simplemente:

Proyecto Alpha - Fase 2. Estado: En revisión. Fecha límite: 15/07/2026. Contacto: Ana García

Acá van tres métodos, del más robusto al más simple.

Método 1: Html.Table con selector :root (recomendado)

Html.Table es una función nativa de M que toma una cadena de texto, la interpreta como HTML y extrae nodos usando selectores CSS. Para extraer todo el texto visible de cualquier bloque HTML, el selector :root captura el contenido de texto del nodo raíz completo:

Html.Table([Columna], {{"texto", ":root"}}){0}[texto]

Desglose: – {{"texto", ":root"}} — define una tabla resultado con una columna llamada «texto» que usa el selector :root{0}[texto] — toma la primera fila de esa tabla y devuelve el valor de la columna «texto»

Fórmula completa como columna personalizada

= Table.AddColumn(
    #"Paso anterior",
    "Contenido limpio",
    each try Html.Table([HtmlCol], {{"texto", ":root"}}){0}[texto] otherwise null,
    type text
)

El try...otherwise null es esencial: si la celda es null, está vacía o contiene HTML inválido, devuelve null sin detener la consulta.

Ventajas de este método

  • Elimina todas las etiquetas HTML, incluyendo anidadas y atributos
  • Decodifica entidades HTML como &#160; (espacio no separable), &amp;, &lt; automáticamente
  • Funciona con HTML complejo de cualquier origen

Limitación

Si el HTML tiene múltiples párrafos, Html.Table devuelve varias filas (una por nodo de texto). El {0} solo toma la primera. Para concatenar todos los párrafos:

Text.Combine(
    Html.Table([HtmlCol], {{"texto", ":root"}})[texto],
    " "
)

Método 2: función reutilizable para toda la consulta

Si necesitás limpiar HTML en varias columnas, definí una función al inicio de la consulta:

let
    LimpiarHTML = (html as nullable text) as nullable text =>
        if html = null or html = ""
        then null
        else try
            Text.Combine(
                Html.Table(html, {{"t", ":root"}})[t],
                " "
            )
        otherwise null,

    Origen = ..., // tu fuente de datos

    Limpio = Table.TransformColumns(
        Origen,
        {
            {"Descripcion", LimpiarHTML, type text},
            {"Comentarios", LimpiarHTML, type text},
            {"Notas",       LimpiarHTML, type text}
        }
    )
in
    Limpio

Esto aplica la misma limpieza a varias columnas en un solo paso con Table.TransformColumns.

Método 3: Text.Replace para HTML simple

Para casos donde el HTML es predecible y tiene pocas etiquetas (por ejemplo, solo <br> y <p>), podés usar reemplazos en cadena:

let
    SinBR  = Text.Replace([Columna], "<br>", " "),
    SinBR2 = Text.Replace(SinBR, "<br/>", " "),
    SinP   = Text.Replace(SinBR2, "</p>", " "),
    SinDiv = Text.Replace(SinP, "<div>", ""),
    // ... continuar para cada etiqueta conocida
    Limpio = Text.Trim(SinDiv)
in
    Limpio

Problema: este enfoque no escala. Cada etiqueta nueva que aparezca en los datos requiere un nuevo reemplazo. Con atributos (<p class="...">) el enfoque falla porque tenés que anticipar todos los valores posibles. No es recomendable para datos reales de SharePoint u otras fuentes ricas.

Caso práctico: datos de SharePoint con HTML

SharePoint almacena los campos de texto enriquecido con clases CSS propias (ExternalClass...) y entidades encodeadas (&#58; para :, &#160; para espacio no separable). El Método 1 maneja todo esto sin configuración adicional.

let
    // Conectar a lista de SharePoint
    Origen = SharePoint.Tables("https://tuempresa.sharepoint.com/sites/Proyectos"),
    Lista = Origen{[Name="Incidencias"]}[Data],

    // Limpiar columna Descripcion que viene con HTML
    Limpio = Table.AddColumn(
        Lista,
        "Descripcion_texto",
        each try
            Text.Combine(
                Html.Table([Descripcion], {{"t", ":root"}})[t],
                " "
            )
        otherwise null,
        type text
    ),

    // Opcional: eliminar la columna original con HTML
    Final = Table.RemoveColumns(Limpio, {"Descripcion"})
in
    Final

Cómo verificar que el texto quedó limpio

Después del paso de limpieza, añadí una columna de control:

= Table.AddColumn(
    Limpio,
    "Tiene HTML residual",
    each Text.Contains([Descripcion_texto] ?? "", "<"),
    type logical
)

Si alguna fila devuelve true, el HTML no se limpió completamente y necesitás revisar el caso.

Relación con HTML Content en Power BI

Si tu objetivo no es limpiar datos sino mostrar HTML como parte de un visual interactivo dentro del reporte, la herramienta correcta es el visual HTML Content de Power BI. Podés combinarlo con DAX para crear tarjetas con estilo, KPIs con iconos y semáforos de color. Mirá cómo construirlos en el artículo Creando cards visuales animados en Power BI con HTML Content.


Comparativa de métodos

Método HTML complejo Entidades (&#160;) Múltiples párrafos Recomendado para
Html.Table + :root Con Text.Combine Cualquier fuente real
Text.Replace ❌ (parcial) HTML muy simple y predecible
Función reutilizable Múltiples columnas HTML

El Método 1 con try...otherwise null es el que vas a querer tener guardado como snippet para la próxima vez que llegue una fuente con HTML.

Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *