Pesquisar e substituir texto em apresentações PowerPoint em JavaScript

Visão geral

Aspose.Slides for Node.js via Java pode pesquisar, realçar e substituir texto em um único quadro de texto ou em toda a apresentação. Cada operação também pode notificar um aplicativo sobre cada correspondência por meio de um callback de resultado. Isso permite atualizar uma apresentação e, simultaneamente, construir um registro de auditoria contendo o texto correspondido, seu contexto, posição, quadro de texto e número do slide.

Esses recursos são úteis para revisões, remoção de conteúdo, verificação de terminologia, limpeza de modelos e fluxos de trabalho de relatórios automatizados.

Nos primeiros exemplos abaixo, usamos um arquivo chamado “sample.pptx”, que contém uma única caixa de texto no primeiro slide com o seguinte texto:

Texto de exemplo

Escolher o escopo da pesquisa

Use os métodos em TextFrame para limitar uma operação a um quadro de texto. Use os métodos em Presentation para processar todo o texto aplicável na apresentação.

Operação Um quadro de texto Apresentação inteira
Realçar texto literal TextFrame.highlightText Presentation.highlightText
Realçar correspondências de expressão regular TextFrame.highlightRegex Presentation.highlightRegex
Substituir texto literal TextFrame.replaceText Presentation.replaceText
Substituir correspondências de expressão regular TextFrame.replaceRegex Presentation.replaceRegex

Configurar correspondência de texto

Para operações de texto literal, use TextSearchOptions para controlar a correspondência:

Operações de expressão regular usam um Pattern Java, portanto regras de correspondência como sensibilidade a maiúsculas/minúsculas e limites de palavra são definidas pela expressão e suas flags.

Identificar o proprietário de um quadro de texto

Fluxos de trabalho genéricos de processamento de texto costumam receber um TextFrame enquanto pesquisam, substituem, validam ou exportam texto. Use TextFrame.getParentShape e TextFrame.getParentCell para determinar qual objeto da apresentação possui o quadro de texto.

Os valores esperados dependem do proprietário:

Proprietário do quadro de texto getParentShape getParentCell
Um AutoShape ou outra forma que contém texto A Shape proprietária null
Uma célula de tabela null A Cell proprietária

Ambos os métodos fornecem navegação somente leitura. Chamá‑los não move o quadro de texto nem altera seu proprietário. Código genérico deve verificar ambos os valores quanto a null e tratar a possibilidade de que nenhum proprietário esteja disponível.

O exemplo a seguir usa SlideUtil.getAllTextFrames para iterar pelos quadros de texto em uma apresentação. Para formas, ele relata o nome da forma, o tipo de tempo de execução Java e o slide contendo. Para células de tabela, ele relata as coordenadas de coluna e linha baseadas em zero e o slide contendo.

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

function getSlideLabel(baseSlide) {
    if (java.instanceOf(baseSlide, "com.aspose.slides.Slide")) {
        return "slide " + baseSlide.getSlideNumber();
    }

    if (java.instanceOf(baseSlide, "com.aspose.slides.NotesSlide")) {
        return "notes for slide " + baseSlide.getParentSlide().getSlideNumber();
    }

    return baseSlide.getClass().getSimpleName();
}

const presentation = new aspose.slides.Presentation("presentation.pptx");
try {
    const textFrames = aspose.slides.SlideUtil.getAllTextFrames(presentation, false);

    for (let index = 0; index < textFrames.length; index++) {
        const textFrame = textFrames[index];
        const ownerShape = textFrame.getParentShape();
        if (ownerShape !== null) {
            const shapeName = ownerShape.getName() === "" ? "(unnamed)" : ownerShape.getName();
            const shapeType = ownerShape.getClass().getSimpleName();
            const slideLabel = getSlideLabel(ownerShape.getSlide());
            console.log("Shape: " + shapeName + "; type: " + shapeType + "; " + slideLabel);
            continue;
        }

        const ownerCell = textFrame.getParentCell();
        if (ownerCell !== null) {
            const slideLabel = getSlideLabel(ownerCell.getSlide());
            console.log("Table cell: column " + ownerCell.getFirstColumnIndex() + ", row " + ownerCell.getFirstRowIndex() + "; " + slideLabel);
            continue;
        }

        console.log("The text frame owner is not available as a shape or table cell.");
    }
} finally {
    presentation.dispose();
}

Para conteúdo SmartArt, itere pelas formas em SmartArtNode.getShapes e acesse cada SmartArtShape.getTextFrame. O quadro de texto pode ser rastreado até sua forma associada através de TextFrame.getParentShape, enquanto TextFrame.getParentCell retorna null. Portanto, o ramo de forma no exemplo também trata texto de nós SmartArt.

Coletar informações de correspondência com um callback

Crie um proxy Java para o callback de resultado para receber uma notificação para cada correspondência. A função proxy recebe o quadro de texto relacionado, o texto de origem, o texto correspondido e a posição da correspondência.

O callback não recebe um número de slide diretamente. A implementação abaixo o deriva através da forma ou célula de tabela proprietária do quadro de texto, com TextFrame.getSlide como fallback. Ele também trata texto encontrado nas notas do slide.

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

function getSlideNumber(textFrame) {
    const parentShape = textFrame.getParentShape();
    const parentCell = textFrame.getParentCell();
    let parentSlide = textFrame.getSlide();
    if (parentShape !== null) {
        parentSlide = parentShape.getSlide();
    } else if (parentCell !== null) {
        parentSlide = parentCell.getSlide();
    }

    if (java.instanceOf(parentSlide, "com.aspose.slides.Slide")) {
        return parentSlide.getSlideNumber();
    }

    if (java.instanceOf(parentSlide, "com.aspose.slides.NotesSlide")) {
        return parentSlide.getParentSlide().getSlideNumber();
    }

    return null;
}

function createTextSearchCallback(results) {
    return java.newProxy("com.aspose.slides.IFindResultCallback", {
        foundResult: function(textFrame, sourceText, foundText, textPosition) {
            results.push({
                textFrame: textFrame,
                sourceText: sourceText,
                foundText: foundText,
                textPosition: textPosition,
                slideNumber: getSlideNumber(textFrame)
            });
        }
    });
}

Para operações de substituição, foundText contém o texto original correspondido, de modo que o callback pode registrar exatamente quais termos foram substituídos.

Realçar texto

Use o método TextFrame.highlightText para realçar correspondências de texto literal em um quadro de texto. Passe TextSearchOptions para controlar a pesquisa.

O exemplo de código abaixo realça todas as ocorrências dos caracteres “try” e depois realça apenas a palavra completa “to”.

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

const presentation = new aspose.slides.Presentation("sample.pptx");
try {
    const slide = presentation.getSlides().get_Item(0);
    const shape = slide.getShapes().get_Item(0);

    const substringSearchOptions = new aspose.slides.TextSearchOptions();
    substringSearchOptions.setCaseSensitive(false);
    const substringHighlightColor = java.getStaticFieldValue("java.awt.Color", "LIGHT_GRAY");

    // Realçar cada ocorrência de "try" no quadro de texto.
    shape.getTextFrame().highlightText(
        "try", substringHighlightColor, substringSearchOptions, null);

    const wholeWordSearchOptions = new aspose.slides.TextSearchOptions();
    wholeWordSearchOptions.setWholeWordsOnly(true);
    wholeWordSearchOptions.setCaseSensitive(false);
    const wholeWordHighlightColor = java.getStaticFieldValue("java.awt.Color", "MAGENTA");

    // Realçar apenas a palavra completa "to".
    shape.getTextFrame().highlightText(
        "to", wholeWordHighlightColor, wholeWordSearchOptions, null);

    presentation.save("highlighted_text.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

O resultado:

O texto realçado

Realçar texto usando expressões regulares

O método TextFrame.highlightRegex realça as correspondências de texto encontradas por uma expressão regular em um quadro de texto.

O código a seguir realça todas as palavras que contêm sete ou mais caracteres:

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const Pattern = java.import("java.util.regex.Pattern");

const presentation = new aspose.slides.Presentation("sample.pptx");
try {
    const slide = presentation.getSlides().get_Item(0);
    const shape = slide.getShapes().get_Item(0);
    const regex = Pattern.compile("\\b[^\\s]{7,}\\b");
    const highlightColor = java.getStaticFieldValue("java.awt.Color", "YELLOW");

    shape.getTextFrame().highlightRegex(regex, highlightColor, null);

    presentation.save(
        "highlighted_text_using_regex.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

O resultado:

O texto realçado usando a expressão regular

Realçar texto em toda a apresentação

Use Presentation.highlightText e Presentation.highlightRegex para pesquisar todos os quadros de texto aplicáveis em uma apresentação. O exemplo a seguir realça um termo literal e todos os endereços de e‑mail:

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const Pattern = java.import("java.util.regex.Pattern");

const presentation = new aspose.slides.Presentation("presentation.pptx");
try {
    const searchOptions = new aspose.slides.TextSearchOptions();
    searchOptions.setWholeWordsOnly(true);
    searchOptions.setCaseSensitive(false);
    const termHighlightColor = java.getStaticFieldValue("java.awt.Color", "ORANGE");

    presentation.highlightText(
        "confidential", termHighlightColor, searchOptions, null);

    const emailRegex = Pattern.compile(
        "\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b",
        Pattern.CASE_INSENSITIVE);
    const emailHighlightColor = java.getStaticFieldValue("java.awt.Color", "YELLOW");

    presentation.highlightRegex(emailRegex, emailHighlightColor, null);
    presentation.save("highlighted_presentation.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Substituir texto em um quadro de texto

Use TextFrame.replaceText para texto literal e TextFrame.replaceRegex para substituição baseada em padrão. Esses métodos atualizam o texto correspondido dentro do quadro de texto existente, preservando a formatação da porção circundante em vez de reconstruir o quadro a partir de uma string simples.

O exemplo a seguir padroniza uma variante ortográfica e depois substitui rótulos de versão:

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const Pattern = java.import("java.util.regex.Pattern");

const presentation = new aspose.slides.Presentation("presentation.pptx");
try {
    const slide = presentation.getSlides().get_Item(0);
    const shape = slide.getShapes().get_Item(0);
    const searchOptions = new aspose.slides.TextSearchOptions();
    searchOptions.setWholeWordsOnly(true);
    searchOptions.setCaseSensitive(false);

    shape.getTextFrame().replaceText(
        "colour", "color", searchOptions, null);

    const versionRegex = Pattern.compile(
        "\\bv\\d+(?:\\.\\d+)*\\b", Pattern.CASE_INSENSITIVE);
    shape.getTextFrame().replaceRegex(versionRegex, "current version", null);

    presentation.save("updated_text_frame.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Se uma correspondência abranger partes com formatações diferentes, revise o resultado para confirmar qual formatação deve ser aplicada ao texto substituído.

Substituir texto em toda a apresentação

Use Presentation.replaceText e Presentation.replaceRegex para aplicar as mesmas operações em toda a apresentação. Isso é útil para limpeza de modelos, atualizações de terminologia e remoção de conteúdo.

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const Pattern = java.import("java.util.regex.Pattern");

const presentation = new aspose.slides.Presentation("presentation.pptx");
try {
    const searchOptions = new aspose.slides.TextSearchOptions();
    searchOptions.setWholeWordsOnly(true);
    searchOptions.setCaseSensitive(true);

    presentation.replaceText(
        "Contoso", "Example Corp", searchOptions, null);

    const accountNumberRegex = Pattern.compile("\\bACCT-\\d{6}\\b");
    presentation.replaceRegex(accountNumberRegex, "ACCT-REDACTED", null);

    presentation.save("updated_presentation.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Agrupar correspondências para relatórios

Como cada resultado coletado armazena seu número de slide e quadro de texto, as aplicações podem agrupar correspondências para auditoria, relatórios ou fluxos de revisão. O exemplo a seguir agrupa os resultados primeiro por slide e depois por quadro de texto:

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

function getSlideNumber(textFrame) {
    const parentShape = textFrame.getParentShape();
    const parentCell = textFrame.getParentCell();
    let parentSlide = textFrame.getSlide();
    if (parentShape !== null) {
        parentSlide = parentShape.getSlide();
    } else if (parentCell !== null) {
        parentSlide = parentCell.getSlide();
    }

    if (java.instanceOf(parentSlide, "com.aspose.slides.Slide")) {
        return parentSlide.getSlideNumber();
    }

    if (java.instanceOf(parentSlide, "com.aspose.slides.NotesSlide")) {
        return parentSlide.getParentSlide().getSlideNumber();
    }

    return null;
}

const results = [];
const callback = java.newProxy("com.aspose.slides.IFindResultCallback", {
    foundResult: function(textFrame, sourceText, foundText, textPosition) {
        results.push({
            textFrame: textFrame,
            sourceText: sourceText,
            foundText: foundText,
            textPosition: textPosition,
            slideNumber: getSlideNumber(textFrame)
        });
    }
});

const presentation = new aspose.slides.Presentation("presentation.pptx");
try {
    const searchOptions = new aspose.slides.TextSearchOptions();
    searchOptions.setCaseSensitive(false);
    const highlightColor = java.getStaticFieldValue("java.awt.Color", "YELLOW");

    presentation.highlightText(
        "confidential", highlightColor, searchOptions, callback);

    const matchesBySlide = new Map();

    for (const result of results) {
        const slideLabel = result.slideNumber === null ? "Other" : result.slideNumber;

        if (!matchesBySlide.has(slideLabel)) {
            matchesBySlide.set(slideLabel, new Map());
        }

        const matchesByTextFrame = matchesBySlide.get(slideLabel);
        if (!matchesByTextFrame.has(result.textFrame)) {
            matchesByTextFrame.set(result.textFrame, []);
        }

        matchesByTextFrame.get(result.textFrame).push(result);
    }

    for (const [slideLabel, matchesByTextFrame] of matchesBySlide) {
        console.log("Slide: " + slideLabel);

        for (const [textFrame, textFrameMatches] of matchesByTextFrame) {
            console.log("  Text frame: " + textFrame.getText());

            for (const result of textFrameMatches) {
                console.log(
                    "    '" + result.foundText + "' at position " +
                    result.textPosition + "; context: '" + result.sourceText + "'");
            }
        }
    }
} finally {
    presentation.dispose();
}

Perguntas frequentes

Como posso pesquisar apenas uma caixa de texto em vez de toda a apresentação?

Obtenha o quadro de texto da forma e chame TextFrame.highlightText, TextFrame.highlightRegex, TextFrame.replaceText, ou TextFrame.replaceRegex nesse quadro de texto. Os métodos em nível de apresentação processam todos os quadros de texto aplicáveis.

Como posso corresponder palavras completas com a capitalização correta?

Defina TextSearchOptions.setWholeWordsOnly e TextSearchOptions.setCaseSensitive como true e passe as opções para um método de realce ou substituição de texto literal. Para expressões regulares, defina limites de palavra e sensibilidade a maiúsculas/minúsculas na própria Pattern Java.

A pesquisa e substituição podem incluir texto nas notas do slide?

Sim. Defina TextSearchOptions.setIncludeNotes como true ao usar uma operação literal de texto em nível de apresentação. A implementação de callback mostrada acima mapeia uma correspondência em um slide de notas para o número do slide pai.

Como posso criar um relatório sem escanear a apresentação uma segunda vez?

Passe um proxy Java de callback de resultado para a operação de realce ou substituição. O callback recebe cada correspondência enquanto a operação é executada, permitindo que a aplicação armazene o texto de origem, o texto correspondido, a posição, o quadro de texto e o número de slide derivado para posterior agrupamento ou exportação.

A substituição de texto preserva sua formatação?

TextFrame.replaceText e TextFrame.replaceRegex modificam o texto correspondido dentro do quadro de texto existente e mantêm a formatação da porção circundante. Se uma correspondência abranger partes com formatações diferentes, inspecione o resultado para garantir que a substituição use o estilo desejado.