Поиск и замена текста в презентациях PowerPoint на .NET
Обзор
Aspose.Slides for .NET может выполнять поиск, выделение и замену текста в отдельном текстовом фрейме или во всей презентации. Каждая операция также может уведомлять приложение о каждом совпадении через обратный вызов результата. Это позволяет обновлять презентацию и одновременно создавать журнал аудита, содержащий найденный текст, его контекст, позицию, текстовый фрейм и номер слайда.
Эти возможности полезны для рецензирования, редактирования, проверки терминологии, очистки шаблонов и автоматизированных процессов генерации отчетов.
В первых примерах ниже мы используем файл с именем “sample.pptx”, содержащий один текстовый блок на первом слайде со следующим текстом:

Выберите область поиска
Используйте методы интерфейса [ITextFrame] для ограничения операции одним текстовым фреймом. Используйте методы класса [Presentation] для обработки всего применимого текста в презентации.
| Операция | Один текстовый фрейм | Вся презентация |
|---|---|---|
| Выделить дословный текст | ITextFrame.HighlightText | Presentation.HighlightText |
| Выделить совпадения регулярного выражения | ITextFrame.HighlightRegex | Presentation.HighlightRegex |
| Заменить дословный текст | ITextFrame.ReplaceText | Presentation.ReplaceText |
| Заменить совпадения регулярного выражения | ITextFrame.ReplaceRegex | Presentation.ReplaceRegex |
Настройка сопоставления текста
Для операций с дословным текстом используйте [TextSearchOptions] для управления сопоставлением:
- TextSearchOptions.WholeWordsOnly ограничивает совпадения полными словами.
- TextSearchOptions.CaseSensitive управляет тем, должно ли учитываться регистр символов.
- TextSearchOptions.IncludeNotes включает заметки слайдов в поиск, замену и выделение на уровне презентации.
Операции с регулярными выражениями используют .NET Regex, поэтому правила сопоставления, такие как чувствительность к регистру и границы слов, задаются выражением и его параметрами.
Определение владельца текстового фрейма
Общие рабочие процессы обработки текста часто получают объект [ITextFrame] при поиске, замене, проверке или экспорте текста. Используйте [ITextFrame.ParentShape] и [ITextFrame.ParentCell], чтобы определить, какой объект презентации владеет этим текстовым фреймом.
Ожидаемые значения зависят от владельца:
| Владелец текстового фрейма | ParentShape |
ParentCell |
|---|---|---|
| Автофигура или другая фигура, содержащая текст | The owning IShape | null |
| Ячейка таблицы | null |
The owning ICell |
Оба свойства являются навигационными только для чтения. Их чтение не перемещает текстовый фрейм и не меняет его владельца. Общий код должен проверять оба значения на null и учитывать возможность, что ни один владелец недоступен.
В следующем примере используется SlideUtil.GetAllTextFrames для перебора текстовых фреймов в презентации. Для фигур он выводит имя фигуры, тип фигуры и содержащий слайд. Для ячеек таблицы он выводит нулевые координаты столбца и строки и содержащий слайд.
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;
}
Для содержимого SmartArt перебирайте фигуры в ISmartArtNode.Shapes и получайте доступ к каждому ISmartArtShape.TextFrame. Текстовый фрейм можно отследить к связанной фигуре через ITextFrame.ParentShape, тогда как ITextFrame.ParentCell равно null. Поэтому ветка фигур в примере также обрабатывает текст из узлов SmartArt.
Сбор информации о совпадениях с помощью обратного вызова
Реализуйте IFindResultCallback чтобы получать уведомление о каждом совпадении. Его метод IFindResultCallback.FoundResult предоставляет связанный текстовый фрейм, исходный текст, найденный текст и позицию совпадения.
Обратный вызов не получает номер слайда напрямую. Реализация ниже выводит его из родительского слайда и также обрабатывает текст, найденный в заметках слайда. nullable номер слайда позволяет одной модели результата представлять текст, связанный с другими типами слайдов.
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;
}
}
Для операций замены FoundText содержит исходный найденный текст, поэтому обратный вызов может точно зафиксировать, какие термины были заменены.
Выделение текста
Используйте метод ITextFrame.HighlightText для выделения совпадений дословного текста в текстовом фрейме. Передайте TextSearchOptions для управления поиском и обратный вызов для сбора деталей совпадений.
Пример кода ниже выделяет все вхождения символов “try”, а затем выделяет только полное слово “to”. Оба поиска передают свои совпадения в один и тот же обратный вызов.
using System;
using System.Drawing;
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 substringSearchOptions = new TextSearchOptions
{
CaseSensitive = false
};
// Выделить каждое вхождение "try" в текстовом фрейме.
shape.TextFrame.HighlightText("try", Color.LightBlue, substringSearchOptions, callback);
var wholeWordSearchOptions = new TextSearchOptions
{
WholeWordsOnly = true,
CaseSensitive = false
};
// Выделить только полное слово "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);
Результат:

Выделение текста с помощью регулярных выражений
Метод ITextFrame.HighlightRegex выделяет совпадения текста, найденные регулярным выражением, в текстовом фрейме.
Следующий код выделяет все слова, содержащие семь или более символов, и собирает каждое совпадение:
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);
Результат:

Выделение текста по всей презентации
Используйте Presentation.HighlightText и Presentation.HighlightRegex для поиска во всех применимых текстовых фреймах презентации. В следующем примере выделяется дословный термин и все адреса электронной почты, при этом сохраняются отдельные коллекции результатов для двух поисков.
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);
Замена текста в текстовом фрейме
Используйте ITextFrame.ReplaceText для дословного текста и ITextFrame.ReplaceRegex для замены по шаблону. Эти методы обновляют найденный текст в существующем текстовом фрейме, сохраняя форматирование окружающих частей, вместо пересоздания фрейма из обычной строки.
В следующем примере стандартизируется вариант написания, а затем заменяются метки версий. Один и тот же обратный вызов фиксирует исходные термины, найденные обеими операциями.
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);
Если одно совпадение охватывает части с разным форматированием, проверьте результат, чтобы подтвердить, какое форматирование должно применяться к заменяемому тексту.
Замена текста по всей презентации
Используйте Presentation.ReplaceText и Presentation.ReplaceRegex для применения тех же операций ко всей презентации. Это полезно для очистки шаблонов, обновления терминологии и редактирования.
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);
Группировка совпадений для отчётности
Поскольку каждый результат хранит номер слайда и текстовый фрейм, приложения могут группировать совпадения для аудита, отчётности или процессов проверки. В следующем примере собираемые результаты группируются сначала по слайду, затем по текстовому фрейму:
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}'");
}
}
}
Часто задаваемые вопросы
Как выполнить поиск только в одном текстовом поле вместо всей презентации?
Получите текстовый фрейм фигуры и вызовите ITextFrame.HighlightText, ITextFrame.HighlightRegex, ITextFrame.ReplaceText или ITextFrame.ReplaceRegex для этого фрейма. Методы уровня презентации обрабатывают все применимые текстовые фреймы.
Как сопоставить полные слова с правильным регистром?
Установите TextSearchOptions.WholeWordsOnly и TextSearchOptions.CaseSensitive в true и передайте параметры методу выделения или замены дословного текста. Для регулярных выражений определяйте границы слов и чувствительность к регистру непосредственно в .NET Regex.
Можно ли включить поиск и замену текста в заметках слайдов?
Да. Установите TextSearchOptions.IncludeNotes в true при использовании дословной операции на уровне презентации. Реализация обратного вызова, показанная выше, сопоставляет совпадение в слайде заметок с номером его родительского слайда.
Как создать отчёт без повторного сканирования презентации?
Передайте реализацию IFindResultCallback в операцию выделения или замены. Обратный вызов получает каждое совпадение во время выполнения операции, поэтому приложение может сохранять исходный текст, найденный текст, позицию, текстовый фрейм и выведенный номер слайда для последующей группировки или экспорта.
Сохраняет ли замена текста его форматирование?
ITextFrame.ReplaceText и ITextFrame.ReplaceRegex изменяют найденный текст внутри существующего текстового фрейма и сохраняют форматирование окружающих частей. Если совпадение охватывает участки с разным форматированием, проверьте результат, чтобы убедиться, что замена использует требуемый стиль.