Buscar y reemplazar texto en presentaciones de PowerPoint en .NET

Visión general

Aspose.Slides for .NET puede buscar, resaltar y reemplazar texto en un único cuadro de texto o en toda una presentación. Cada operación también puede notificar a una aplicación sobre cada coincidencia mediante una devolución de resultados. Esto permite actualizar una presentación y, simultáneamente, crear una pista de auditoría que contiene el texto coincidente, su contexto, posición, cuadro de texto y número de diapositiva.

Estas capacidades son útiles para la revisión, la redacción, la comprobación de terminología, la limpieza de plantillas y los flujos de trabajo de generación de informes automáticos.

En los primeros ejemplos a continuación, usamos un archivo llamado “sample.pptx”, que contiene un único cuadro de texto en la primera diapositiva con el siguiente texto:

Texto de ejemplo

Seleccionar el ámbito de la búsqueda

Utilice los métodos de ITextFrame para limitar una operación a un único cuadro de texto. Utilice los métodos de Presentation para procesar todo el texto aplicable en la presentación.

Operación Un cuadro de texto Presentación completa
Resaltar texto literal ITextFrame.HighlightText Presentation.HighlightText
Resaltar coincidencias de expresiones regulares ITextFrame.HighlightRegex Presentation.HighlightRegex
Reemplazar texto literal ITextFrame.ReplaceText Presentation.ReplaceText
Reemplazar coincidencias de expresiones regulares ITextFrame.ReplaceRegex Presentation.ReplaceRegex

Configurar la coincidencia de texto

Para operaciones de texto literal, utilice TextSearchOptions para controlar la coincidencia:

Las operaciones con expresiones regulares utilizan un Regex de .NET, por lo que reglas de coincidencia como la sensibilidad a mayúsculas y los límites de palabra se definen mediante la expresión y sus opciones.

Identificar el propietario de un cuadro de texto

Los flujos de trabajo genéricos de procesamiento de texto a menudo reciben un [ITextFrame] al buscar, reemplazar, validar o exportar texto. Utilice ITextFrame.ParentShape y ITextFrame.ParentCell para determinar qué objeto de la presentación es el propietario del cuadro de texto.

Los valores esperados dependen del propietario:

Propietario del cuadro de texto ParentShape ParentCell
Una AutoShape u otra forma que contenga texto El IShape propietario null
Una celda de tabla null El ICell propietario

Ambas propiedades son de solo lectura y de navegación. Leerlas no mueve el cuadro de texto ni cambia su propietario. El código genérico debe comprobar ambos valores para null y manejar la posibilidad de que ninguno de los propietarios esté disponible.

El siguiente ejemplo utiliza SlideUtil.GetAllTextFrames para iterar sobre los cuadros de texto de una presentación. Para las formas, informa del nombre de la forma, el tipo de forma y la diapositiva contenedora. Para las celdas de tabla, informa de las coordenadas de columna y fila basadas en cero y de la diapositiva contenedora.

using System;
using Aspose.Slides;
using Aspose.Slides.Util;

using var presentation = new Presentation("presentation.pptx");

var textFrames = SlideUtil.GetAllTextFrames(presentation, false);

foreach (var textFrame in textFrames)
{
    var ownerShape = textFrame.ParentShape;
    if (ownerShape != null)
    {
        var shapeName = string.IsNullOrEmpty(ownerShape.Name) ? "(unnamed)" : ownerShape.Name;
        var shapeType = GetShapeType(ownerShape);
        var slideLabel = GetSlideLabel(ownerShape.Slide);
        Console.WriteLine($"Shape: {shapeName}; type: {shapeType}; {slideLabel}");

        continue;
    }

    var ownerCell = textFrame.ParentCell;
    if (ownerCell != null)
    {
        var slideLabel = GetSlideLabel(ownerCell.Slide);
        Console.WriteLine($"Table cell: column {ownerCell.FirstColumnIndex}, row {ownerCell.FirstRowIndex}; {slideLabel}");
        continue;
    }

    Console.WriteLine("The text frame owner is not available as a shape or table cell.");
}

static string GetShapeType(IShape shape)
{
    if (shape is IGeometryShape geometryShape)
    {
        return geometryShape.ShapeType.ToString();
    }

    return shape.GetType().Name;
}

static string GetSlideLabel(IBaseSlide baseSlide)
{
    if (baseSlide is ISlide slide)
    {
        return $"slide {slide.SlideNumber}";
    }

    if (baseSlide is INotesSlide notesSlide)
    {
        return $"notes for slide {notesSlide.ParentSlide.SlideNumber}";
    }

    return baseSlide.GetType().Name;
}

Para el contenido de SmartArt, itere a través de las formas en ISmartArtNode.Shapes y acceda a cada ISmartArtShape.TextFrame. El cuadro de texto puede rastrearse a su forma asociada mediante ITextFrame.ParentShape, mientras que ITextFrame.ParentCell es null. Por lo tanto, la rama de forma en el ejemplo también maneja texto de nodos SmartArt.

Recopilar información de coincidencias con una devolución de llamada

Implemente IFindResultCallback para recibir una notificación por cada coincidencia. Su método IFindResultCallback.FoundResult proporciona el cuadro de texto relacionado, el texto fuente, el texto coincidente y la posición de la coincidencia.

La devolución de llamada no recibe directamente el número de diapositiva. La implementación a continuación lo deriva de la diapositiva padre y también gestiona texto encontrado en notas de diapositiva. Un número de diapositiva nullable permite que el mismo modelo de resultado represente texto asociado a otros tipos de diapositiva.

using System.Collections.Generic;
using Aspose.Slides;

public sealed class TextMatch
{
    public TextMatch(ITextFrame textFrame, string sourceText, string foundText, int textPosition, int? slideNumber)
    {
        TextFrame = textFrame;
        SourceText = sourceText;
        FoundText = foundText;
        TextPosition = textPosition;
        SlideNumber = slideNumber;
    }

    public ITextFrame TextFrame { get; }
    public string SourceText { get; }
    public string FoundText { get; }
    public int TextPosition { get; }
    public int? SlideNumber { get; }
}

public sealed class TextSearchCallback : IFindResultCallback
{
    public List<TextMatch> Results { get; } = new();

    public void FoundResult(ITextFrame textFrame, string sourceText, string foundText, int textPosition)
    {
        var slideNumber = GetSlideNumber(textFrame);
        var result = new TextMatch(textFrame, sourceText, foundText, textPosition, slideNumber);

        Results.Add(result);
    }

    private static int? GetSlideNumber(ITextFrame textFrame)
    {
        var parentSlide = textFrame.ParentShape?.Slide ?? textFrame.ParentCell?.Slide ?? textFrame.Slide;

        if (parentSlide is ISlide slide)
        {
            return slide.SlideNumber;
        }

        if (parentSlide is INotesSlide notesSlide)
        {
            return notesSlide.ParentSlide.SlideNumber;
        }

        return null;
    }
}

Para operaciones de reemplazo, FoundText contiene el texto coincidido original, de modo que la devolución de llamada puede registrar exactamente qué términos fueron reemplazados.

Resaltar texto

Utilice el método ITextFrame.HighlightText para resaltar coincidencias de texto literal en un cuadro de texto. Pase TextSearchOptions para controlar la búsqueda y una devolución de llamada para recopilar los detalles de la coincidencia.

El siguiente ejemplo de código resalta todas las apariciones de los caracteres “try” y luego resalta solo la palabra completa “to”. Ambas búsquedas informan sus coincidencias a la misma devolución de llamada.

using System;
using System.Drawing;
using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation("sample.pptx");

// Obtener la primera forma de la primera diapositiva.
var shape = (IAutoShape)presentation.Slides[0].Shapes[0];
var callback = new TextSearchCallback();

var substringSearchOptions = new TextSearchOptions
{
    CaseSensitive = false
};

// Resaltar cada aparición de "try" en el cuadro de texto.
shape.TextFrame.HighlightText("try", Color.LightBlue, substringSearchOptions, callback);

var wholeWordSearchOptions = new TextSearchOptions
{
    WholeWordsOnly = true,
    CaseSensitive = false
};

// Resaltar solo la palabra completa "to".
shape.TextFrame.HighlightText("to", Color.Violet, wholeWordSearchOptions, callback);

foreach (var result in callback.Results)
{
    Console.WriteLine($"Found '{result.FoundText}' at position {result.TextPosition} on slide {result.SlideNumber}.");
}

presentation.Save("highlighted_text.pptx", SaveFormat.Pptx);

El resultado:

El texto resaltado

Resaltar texto usando expresiones regulares

El método ITextFrame.HighlightRegex resalta coincidencias de texto encontradas mediante una expresión regular en un cuadro de texto.

El siguiente código resalta todas las palabras que contienen siete o más caracteres y recopila cada coincidencia:

using System.Drawing;
using System.Text.RegularExpressions;
using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation("sample.pptx");

var shape = (IAutoShape)presentation.Slides[0].Shapes[0];
var callback = new TextSearchCallback();
var regex = new Regex(@"\b[^\s]{7,}\b");

shape.TextFrame.HighlightRegex(regex, Color.Yellow, callback);

presentation.Save("highlighted_text_using_regex.pptx", SaveFormat.Pptx);

El resultado:

El texto resaltado usando la expresión regular

Resaltar texto en toda la presentación

Utilice Presentation.HighlightText y Presentation.HighlightRegex para buscar en todos los cuadros de texto aplicables de una presentación. El siguiente ejemplo resalta un término literal y todas las direcciones de correo electrónico, manteniendo colecciones de resultados separadas para ambas búsquedas.

using System.Drawing;
using System.Text.RegularExpressions;
using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation("presentation.pptx");

var termCallback = new TextSearchCallback();
var searchOptions = new TextSearchOptions
{
    WholeWordsOnly = true,
    CaseSensitive = false
};

presentation.HighlightText("confidential", Color.Orange, searchOptions, termCallback);

var emailCallback = new TextSearchCallback();
var emailRegex = new Regex(@"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b", RegexOptions.IgnoreCase);

presentation.HighlightRegex(emailRegex, Color.Yellow, emailCallback);

presentation.Save("highlighted_presentation.pptx", SaveFormat.Pptx);

Reemplazar texto en un cuadro de texto

Utilice ITextFrame.ReplaceText para texto literal y ITextFrame.ReplaceRegex para reemplazo basado en patrones. Estos métodos actualizan el texto coincidente dentro del cuadro de texto existente, que conserva el formato de la parte circundante en lugar de reconstruir el cuadro de texto a partir de una cadena simple.

El siguiente ejemplo normaliza una variante ortográfica y luego reemplaza etiquetas de versión. La misma devolución de llamada registra los términos originales coincidentes en ambas operaciones.

using System.Text.RegularExpressions;
using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation("presentation.pptx");

var shape = (IAutoShape)presentation.Slides[0].Shapes[0];
var callback = new TextSearchCallback();
var searchOptions = new TextSearchOptions
{
    WholeWordsOnly = true,
    CaseSensitive = false
};

shape.TextFrame.ReplaceText("colour", "color", searchOptions, callback);

var versionRegex = new Regex(@"\bv\d+(?:\.\d+)*\b", RegexOptions.IgnoreCase);
shape.TextFrame.ReplaceRegex(versionRegex, "current version", callback);

presentation.Save("updated_text_frame.pptx", SaveFormat.Pptx);

Si una coincidencia abarca partes con formato diferente, revise el resultado para confirmar qué formato debe aplicarse al texto de reemplazo.

Reemplazar texto en toda la presentación

Utilice Presentation.ReplaceText y Presentation.ReplaceRegex para aplicar las mismas operaciones en toda la presentación. Esto es útil para la limpieza de plantillas, la actualización de terminología y la redacción.

using System.Text.RegularExpressions;
using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation("presentation.pptx");

var callback = new TextSearchCallback();
var searchOptions = new TextSearchOptions
{
    WholeWordsOnly = true,
    CaseSensitive = true
};

presentation.ReplaceText("Contoso", "Example Corp", searchOptions, callback);

var accountNumberRegex = new Regex(@"\bACCT-\d{6}\b");
presentation.ReplaceRegex(accountNumberRegex, "ACCT-REDACTED", callback);

presentation.Save("updated_presentation.pptx", SaveFormat.Pptx);

Agrupar coincidencias para informes

Debido a que cada resultado almacena su número de diapositiva y cuadro de texto, las aplicaciones pueden agrupar coincidencias para auditorías, informes o flujos de trabajo de revisión. El siguiente ejemplo agrupa los resultados recopilados primero por diapositiva y luego por cuadro de texto:

using System;
using System.Linq;

var matchesBySlide = callback.Results.GroupBy(result => result.SlideNumber);

foreach (var slideGroup in matchesBySlide)
{
    var slideLabel = slideGroup.Key.HasValue ? slideGroup.Key.Value.ToString() : "Other";
    Console.WriteLine($"Slide: {slideLabel}");

    var matchesByTextFrame = slideGroup.GroupBy(result => result.TextFrame);
    foreach (var textFrameGroup in matchesByTextFrame)
    {
        Console.WriteLine($"  Text frame: {textFrameGroup.Key.Text}");

        foreach (var result in textFrameGroup)
        {
            Console.WriteLine($"    '{result.FoundText}' at position {result.TextPosition}; context: '{result.SourceText}'");
        }
    }
}

FAQ

¿Cómo puedo buscar solo en un cuadro de texto en lugar de en toda la presentación?

Obtenga el cuadro de texto de la forma y llame a ITextFrame.HighlightText, ITextFrame.HighlightRegex, ITextFrame.ReplaceText o ITextFrame.ReplaceRegex en ese cuadro de texto. Los métodos a nivel de presentación procesan todos los cuadros de texto aplicables.

¿Cómo puedo coincidir palabras completas con la capitalización correcta?

Establezca TextSearchOptions.WholeWordsOnly y TextSearchOptions.CaseSensitive en true, y pase las opciones a un método de resaltado o reemplazo de texto literal. Para expresiones regulares, defina los límites de palabras y la sensibilidad a mayúsculas en el propio Regex de .NET.

¿Puede la búsqueda y el reemplazo incluir texto en las notas de la diapositiva?

Sí. Establezca TextSearchOptions.IncludeNotes en true al usar una operación de texto literal a nivel de presentación. La implementación de la devolución de llamada mostrada arriba asigna una coincidencia en una diapositiva de notas al número de diapositiva padre.

¿Cómo puedo crear un informe sin volver a escanear la presentación?

Pase una implementación de IFindResultCallback a la operación de resaltado o reemplazo. La devolución de llamada recibe cada coincidencia mientras la operación se ejecuta, de modo que la aplicación puede almacenar el texto fuente, el texto coincidente, la posición, el cuadro de texto y el número de diapositiva derivado para su posterior agrupación o exportación.

¿El reemplazo de texto conserva su formato?

ITextFrame.ReplaceText y ITextFrame.ReplaceRegex modifican el texto coincidente dentro del cuadro de texto existente y conservan el formato de la parte circundante. Si una coincidencia abarca partes con formato diferente, inspeccione el resultado para asegurarse de que el reemplazo utilice el estilo deseado.