Code Library

M · UDF

fnNuvemDePalavras

Limpa um texto em português para nuvem de palavras: remove pontuação e palavras sem valor analítico (stopwords) e preserva as negações.

Categoria: TextoTipo: UDFVersão: v3.0Fonte: Paulo André Jesus — OfficeTuningAtualizado em: 27/09/2026
Documentação completa na Function Library →

Sintaxe

fnNuvemDePalavras(texto as nullable text) as nullable text

Argumentos

NomeTipoObrigatórioDescrição
textonullable textSimTexto livre (comentário, pesquisa, descrição).

Retorno

nullable text

Código completo

let
    fnNuvemDePalavras = (texto as nullable text) as nullable text =>
        let
            // Pontuação e espaços viram delimitadores num único Text.SplitAny; o hífen fica dentro da palavra
            vDelimitadores =
                "!.:;,?@#$%^&*()[]{}\/_+=<>|""“”…'´`~–—"
                & " #(tab)#(cr)#(lf)#(00A0)",
            // Negações NÃO são stopwords: elas se juntam à palavra seguinte
            vNegacoes = {"não", "nao", "nunca", "nem", "jamais"},
            // Amplie a lista conforme o assunto analisado
            vStopWords = {
                "a", "à", "às", "ao", "aos", "as", "o", "os", "um", "uma", "uns", "umas",
                "de", "da", "das", "do", "dos", "em", "na", "nas", "no", "nos", "num", "numa",
                "para", "pra", "pro", "pelo", "pela", "pelos", "pelas", "por", "com", "sem", "sobre", "entre",
                "e", "ou", "mas", "porém", "porque", "pq", "que", "q", "se", "como", "também", "tb", "tbm", "então", "sim",
                "é", "foi", "fui", "ser", "sido", "será", "são", "era", "eram", "está", "estão", "estou", "estava", "estavam",
                "ter", "tem", "têm", "tenho", "tive", "teve", "tinha", "há", "havia",
                "eu", "me", "mim", "você", "vc", "ele", "ela", "eles", "elas", "nós", "lhe", "lhes",
                "seu", "sua", "seus", "suas", "meu", "minha", "meus", "minhas", "teu", "tua", "teus", "tuas",
                "esse", "essa", "esses", "essas", "este", "esta", "estes", "estas",
                "aquele", "aquela", "aqueles", "aquelas", "isto", "isso", "aquilo",
                "muito", "muita", "muitos", "muitas", "mais", "bem", "já", "só", "ainda", "tudo", "todo", "toda"
            },
            vTokens = List.Select(
                Text.SplitAny(Text.Lower(texto), vDelimitadores),
                each _ <> "" and _ <> "-" and not List.Contains(vStopWords, _)
            ),
            // "não recomendo" → "não-recomendo"; negação no fim do texto fica sozinha
            vEstado = List.Accumulate(
                vTokens,
                [Lista = {}, Pendente = null],
                (estado, palavra) =>
                    if List.Contains(vNegacoes, palavra) then
                        [Lista = estado[Lista],
                         Pendente = if estado[Pendente] = null then palavra else estado[Pendente] & "-" & palavra]
                    else
                        [Lista = estado[Lista] & {if estado[Pendente] = null then palavra else estado[Pendente] & "-" & palavra},
                         Pendente = null]
            ),
            vPalavras = if vEstado[Pendente] = null then vEstado[Lista] else vEstado[Lista] & {vEstado[Pendente]}
        in
            if texto = null then null else Text.Combine(vPalavras, " "),

    fnNuvemDePalavrasTipo = type function (
        texto as (type nullable text meta [
            Documentation.FieldCaption = "Texto",
            Documentation.FieldDescription = "Comentário livre (ex.: feedback de pesquisa). Null retorna null."
        ])
    ) as nullable text meta [
        Documentation.Name = "fnNuvemDePalavras",
        Documentation.Description = "Limpa um texto para nuvem de palavras, preservando negações.",
        Documentation.LongDescription = "Converte para minúsculas, quebra por pontuação e espaços, remove artigos, preposições, pronomes, verbos auxiliares e intensificadores do português e junta negações (não, nunca, nem, jamais) à palavra seguinte com hífen, para que 'não recomendo' não vire 'recomendo'. A lista vStopWords pode ser ampliada.",
        Documentation.Category = "Texto",
        Documentation.Author = "Paulo André Jesus",
        Documentation.Version = "3.0",
        Documentation.Examples = {
            [Description = "Negação preservada", Code = "fnNuvemDePalavras(""Não recomendo, tive uma experiência negativa."")", Result = """não-recomendo experiência negativa"""],
            [Description = "Negação após stopword", Code = "fnNuvemDePalavras(""Não estou satisfeito com o suporte."")", Result = """não-satisfeito suporte"""],
            [Description = "Só stopwords", Code = "fnNuvemDePalavras(""O que é isso?"")", Result = """"""]
        }
    ]
in
    Value.ReplaceType(fnNuvemDePalavras, fnNuvemDePalavrasTipo)

Exemplos

fnNuvemDePalavras("Não recomendo, tive uma experiência negativa.")
// "não-recomendo experiência negativa"

fnNuvemDePalavras("Não estou satisfeito com o suporte.")
// "não-satisfeito suporte"

fnNuvemDePalavras("O que é isso?")
// ""

Dicas e observações

⚠️ Na versão 2.0, "não" era stopword: "Não recomendo" virava "recomendo" e a nuvem dos detratores mostrava elogios. Num modelo NPS real, 595 comentários (186 de detratores) perdiam a negação. 💡 A negação espera a próxima palavra que não é stopword: "não estou satisfeito" vira "não-satisfeito". 💡 O hífen mantém a expressão como um único termo no visual de nuvem; hífen dentro da palavra também é mantido (guarda-chuva). 💡 Para contar termos por conceito, cliente ou período, expanda a saída numa tabela com uma linha por palavra (Text.Split + Table.ExpandListColumn). 💡 A saída vem em minúsculas. Amplie vStopWords com termos do assunto analisado.