Управление текстовыми полями в презентациях с помощью C++
Введение
В Aspose.Slides для C++ текст слайдов хранится в текстовых кадрах, принадлежащих фигурам. Интерфейс IAutoShape представляет наиболее распространённую форму, содержащую текст, и предоставляет доступ к её тексту через метод IAutoShape::get_TextFrame.
Note
Каждая автофигура реализует IShape, но не каждая фигура является автофигурой или поддерживает текстовый кадр. При обработке существующей презентации убедитесь, что фигура реализует IAutoShape перед доступом к её тексту.Создание текстового поля на слайде
Чтобы создать текстовое поле, добавьте автофигуру на слайд, добавьте текст в её текстовый кадр и сохраните презентацию. В следующем примере создаётся прямоугольное текстовое поле:
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <Export/SaveFormat.h>
#include <system/shared_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto textBox = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 150, 75, 300, 50);
textBox->AddTextFrame(u"Aspose TextBox");
presentation->Save(u"TextBox.pptx", SaveFormat::Pptx);
Координаты и размеры, передаваемые в IShapeCollection::AddAutoShape, измеряются в пунктах. IAutoShape::AddTextFrame инициализирует текстовый кадр переданным текстом.
Проверка, является ли фигура текстовым полем
Используйте метод IAutoShape::get_IsTextBox для определения, рассматривается ли автофигура как текстовое поле. Это полезно, когда презентация содержит как фигуры с текстом, так и чисто графические автофигуры.

В следующем примере проверяется каждая автофигура в презентации:
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/console.h>
#include <system/enumerator_adapter.h>
#include <system/object_ext.h>
#include <system/shared_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto textBox = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 10, 10, 120, 40);
textBox->AddTextFrame(u"Text box");
slide->get_Shapes()->AddAutoShape(ShapeType::Ellipse, 150, 10, 40, 40);
for (const auto& currentSlide : IterateOver(presentation->get_Slides()))
{
for (const auto& shape : IterateOver(currentSlide->get_Shapes()))
{
auto autoShape = AsCast<IAutoShape>(shape);
if (autoShape != nullptr)
{
Console::WriteLine(autoShape->get_IsTextBox() ? u"The shape is a text box." : u"The shape is not a text box.");
}
}
}
Новодобавленная автофигура не считается текстовым полем, пока в ней не будет непустого текста. Вы можете задать этот текст через IAutoShape::AddTextFrame или ITextFrame::set_Text. Добавление или присваивание пустой строки приводит к тому, что IAutoShape::get_IsTextBox возвращает false:
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/console.h>
#include <system/shared_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape1 = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 10, 10, 100, 40);
shape1->AddTextFrame(u"Shape 1");
Console::WriteLine(shape1->get_IsTextBox());
auto shape2 = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 10, 70, 100, 40);
shape2->get_TextFrame()->set_Text(u"Shape 2");
Console::WriteLine(shape2->get_IsTextBox());
auto shape3 = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 10, 130, 100, 40);
shape3->AddTextFrame(u"");
Console::WriteLine(shape3->get_IsTextBox());
auto shape4 = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 10, 190, 100, 40);
shape4->get_TextFrame()->set_Text(u"");
Console::WriteLine(shape4->get_IsTextBox());
Первые два условия возвращают true; последние два — false.
Найти фигуру, владеющую текстовым кадром
Общий код обработки текста может получать объект ITextFrame без знания, какой объект презентации его содержит. Используйте метод ITextFrame::get_ParentShape для перехода к его владелецу — IShape.
Для текстового кадра, принадлежащего автофигуре или другой фигуре с текстом, ITextFrame::get_ParentShape возвращает владельца, а ITextFrame::get_ParentCell — nullptr. Оба метода предоставляют только чтение. Проверьте возвращаемое значение на nullptr перед доступом. Чтобы определить как владельцев фигур, так и ячеек таблиц, включая фигуры, связанные с узлами SmartArt, см. Search and Replace Text.
Добавление колонок в текстовое поле
Метод ITextFrameFormat::set_ColumnCount делит текстовый кадр на колонки, а ITextFrameFormat::set_ColumnSpacing задаёт промежуток между колонками в пунктах. Оба метода принадлежат ITextFrameFormat и могут вызываться через текстовый кадр существующего текстового поля. Текст перераспределяется между колонками внутри одной фигуры; он не переходит в другую фигуру.
В следующем примере создаётся трёхколоночное текстовое поле с отступом 10 пунктов между колонками, сохраняется презентация и читаются сохранённые настройки из выходного файла:
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/ITextFrameFormat.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <Export/SaveFormat.h>
#include <system/console.h>
#include <system/object_ext.h>
#include <system/shared_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto textBox = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100, 100, 300, 200);
textBox->AddTextFrame(u"This text is distributed automatically across all columns in the text box.");
auto textFrameFormat = textBox->get_TextFrame()->get_TextFrameFormat();
textFrameFormat->set_ColumnCount(3);
textFrameFormat->set_ColumnSpacing(10);
presentation->Save(u"TextBoxColumns.pptx", SaveFormat::Pptx);
auto savedPresentation = MakeObject<Presentation>(u"TextBoxColumns.pptx");
auto savedTextBox = ExplicitCast<IAutoShape>(savedPresentation->get_Slide(0)->get_Shape(0));
auto savedFormat = savedTextBox->get_TextFrame()->get_TextFrameFormat();
Console::WriteLine(u"Columns: {0}; spacing: {1} points", savedFormat->get_ColumnCount(), savedFormat->get_ColumnSpacing());
Извлечение текста из отдельных колонок
Используйте ITextFrame::SplitTextByColumns для получения текста, присвоенного каждой визуальной колонке в существующем текстовом кадре. Метод возвращает одну строку для каждой колонки в порядке чтения по колонкам. Текстовый кадр с одной колонкой возвращает массив из одного элемента, а пустая колонка представлена пустой строкой. Строки содержат только простой текст; форматирование уровня частей не сохраняется.
Это полезно, когда необходимо:
- Извлечь текст, сохранив порядок чтения по колонкам.
- Индексировать или сравнить содержимое слайдов с несколькими колонками.
- Экспортировать каждую колонку в отдельный файл, поле базы данных или другое место назначения.
- Проанализировать, как текст перераспределяется после установки числа колонок с помощью ITextFrameFormat::set_ColumnCount или отступа с помощью ITextFrameFormat::set_ColumnSpacing, а также при изменении шрифта или размера текстового кадра.
Метод сообщает о тексте, распределённом внутри текущего ITextFrame; он не перенаправляет текст автоматически между отдельными фигурами или текстовыми полями. Распределение по колонкам может зависеть от доступных шрифтов и других настроек макета текста, поэтому убедитесь, что необходимые шрифты доступны, когда важна согласованность результатов.
В следующем примере загружается презентация, находится первая автофигура с несколькими колонками и текстовым кадром на первом слайде, читается её заданное количество колонок и записывается текст каждой колонки в отдельный файл. Фигуры без текстового кадра пропускаются.
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/ITextFrameFormat.h>
#include <DOM/Presentation.h>
#include <system/array.h>
#include <system/console.h>
#include <system/enumerator_adapter.h>
#include <system/io/file.h>
#include <system/object_ext.h>
#include <system/shared_ptr.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"MultiColumnText.pptx");
SharedPtr<IAutoShape> textBox = nullptr;
for (const auto& shape : IterateOver(presentation->get_Slide(0)->get_Shapes()))
{
auto autoShape = AsCast<IAutoShape>(shape);
if (autoShape != nullptr && autoShape->get_TextFrame() != nullptr)
{
auto columnCount = autoShape->get_TextFrame()->get_TextFrameFormat()->get_ColumnCount();
if (columnCount > 1)
{
textBox = autoShape;
break;
}
}
}
if (textBox == nullptr)
{
Console::WriteLine(u"No multi-column text frame was found.");
}
else
{
auto textFrame = textBox->get_TextFrame();
auto configuredColumnCount = textFrame->get_TextFrameFormat()->get_ColumnCount();
auto columnTexts = textFrame->SplitTextByColumns();
Console::WriteLine(u"Configured columns: {0}", configuredColumnCount);
for (auto columnIndex = 0; columnIndex < columnTexts->get_Length(); columnIndex++)
{
auto columnNumber = columnIndex + 1;
auto columnText = columnTexts->idx_get(columnIndex);
Console::WriteLine(u"Column {0}: {1}", columnNumber, columnText);
auto fileName = String::Format(u"Column-{0}.txt", columnNumber);
File::WriteAllText(fileName, columnText);
}
}
Обновление текста
Для обновления текста во всей презентации пройдитесь по слайдам и фигурам, выберите автофигуры и затем отредактируйте их текстовые части. Работа на уровне частей позволяет менять как текст, так и форматирование символов.
В следующем примере каждое вхождение years заменяется на months внутри отдельных частей текста автофигур, а каждую затронутую часть делают полужирной:
#include <DOM/IAutoShape.h>
#include <DOM/IParagraph.h>
#include <DOM/IParagraphCollection.h>
#include <DOM/IPortion.h>
#include <DOM/IPortionCollection.h>
#include <DOM/IPortionFormat.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/ITextFrame.h>
#include <DOM/NullableBool.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <system/enumerator_adapter.h>
#include <system/object_ext.h>
#include <system/shared_ptr.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
auto presentation = MakeObject<Presentation>(u"Text.pptx");
for (const auto& slide : IterateOver(presentation->get_Slides()))
{
for (const auto& shape : IterateOver(slide->get_Shapes()))
{
auto autoShape = AsCast<IAutoShape>(shape);
if (autoShape == nullptr || autoShape->get_TextFrame() == nullptr)
{
continue;
}
for (const auto& paragraph : IterateOver(autoShape->get_TextFrame()->get_Paragraphs()))
{
for (const auto& portion : IterateOver(paragraph->get_Portions()))
{
auto text = portion->get_Text();
if (!String::IsNullOrEmpty(text) && text.Contains(u"years"))
{
portion->set_Text(text.Replace(u"years", u"months"));
portion->get_PortionFormat()->set_FontBold(NullableBool::True);
}
}
}
}
}
presentation->Save(u"TextChanged.pptx", SaveFormat::Pptx);
Этот обход обновляет текст только в автофигурах. Текст, хранящийся в таблицах, диаграммах, SmartArt или сгруппированных фигурах, требует обхода соответствующих коллекций этих объектов.
Добавить текстовое поле с гиперссылкой
Гиперссылка может быть назначена конкретной части текста, поэтому только этот текст будет кликабельным. Используйте IHyperlinkManager::SetExternalHyperlinkClick для привязки части к внешнему URL.
В следующем примере создаётся связанный текст и сохраняется в презентацию:
#include <DOM/IAutoShape.h>
#include <DOM/IHyperlinkManager.h>
#include <DOM/IParagraph.h>
#include <DOM/IPortion.h>
#include <DOM/IPortionFormat.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <Export/SaveFormat.h>
#include <system/shared_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto textBox = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 150, 150, 200, 50);
textBox->AddTextFrame(u"Aspose.Slides");
auto textPortion = textBox->get_TextFrame()->get_Paragraph(0)->get_Portion(0);
textPortion->get_PortionFormat()->get_HyperlinkManager()->SetExternalHyperlinkClick(u"https://www.aspose.com/");
presentation->Save(u"Hyperlink.pptx", SaveFormat::Pptx);
FAQ
В чём разница между текстовым полем и заполнительным текстом на мастер‑слайде или слайде‑разметке?
Заполнитель может наследовать свою позицию и форматирование от мастер‑слайда или слайда‑разметки. Обычное текстовое поле — это независимая фигура на слайде, где оно было создано, и оно не приобретает поведения заполнителя при изменении разметки.
Как заменить текст, не изменяя его в диаграммах, таблицах или SmartArt?
Ограничьте обход фигурами, реализующими IAutoShape, как показано в примере «Обновление текста». Диаграммы, таблицы и SmartArt хранят текст в своих собственных объектных моделях, поэтому они не изменяются этим циклом.