Управление абзацами текста PowerPoint на Android

Обзор

Aspose.Slides for Android via Java представляет текст в виде иерархии текстовых фреймов, абзацев и фрагментов:

  • ITextFrame представляет контейнер текста в фигуре и предоставляет доступ к его коллекции абзацев.
  • IParagraph представляет один абзац в текстовом фрейме и предоставляет доступ к его фрагментам и форматированию уровня абзаца.
  • IPortion представляет строку текста внутри абзаца. Каждый фрагмент может иметь собственный текст и форматирование на уровне символов.

Таким образом, абзац может содержать текст с разными шрифтами, цветами, размерами и другим форматированием, используя несколько фрагментов.

Создание и форматирование абзацев

Создание абзацев с несколькими фрагментами

Следующие шаги создают текстовый фрейм с тремя абзацами, каждый из которых содержит три фрагмента:

  1. Создайте экземпляр класса Presentation.
  2. Получите доступ к соответствующему слайду по его индексу.
  3. Добавьте прямоугольную IAutoShape на слайд.
  4. Получите доступ к ITextFrame формы.
  5. Используйте абзац по умолчанию и добавьте два дополнительных объекта IParagraph в текстовый фрейм.
  6. Добавьте достаточное количество объектов IPortion для каждого абзаца, чтобы он содержал три фрагмента. Абзац по умолчанию уже содержит один пустой фрагмент.
  7. Установите текст каждого фрагмента.
  8. Примените форматирование на уровне символов через IPortion.getPortionFormat.
  9. Сохраните изменённую презентацию.

Этот пример для Android via Java реализует перечисленные шаги:

import com.aspose.slides.*;
import android.graphics.Color;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 50, 150, 300, 150);
    ITextFrame textFrame = shape.getTextFrame();

    IParagraph firstParagraph = textFrame.getParagraphs().get_Item(0);
    firstParagraph.getPortions().add(new Portion());
    firstParagraph.getPortions().add(new Portion());

    IParagraph secondParagraph = new Paragraph();
    secondParagraph.getPortions().add(new Portion());
    secondParagraph.getPortions().add(new Portion());
    secondParagraph.getPortions().add(new Portion());
    textFrame.getParagraphs().add(secondParagraph);

    IParagraph thirdParagraph = new Paragraph();
    thirdParagraph.getPortions().add(new Portion());
    thirdParagraph.getPortions().add(new Portion());
    thirdParagraph.getPortions().add(new Portion());
    textFrame.getParagraphs().add(thirdParagraph);

    int paragraphCount = textFrame.getParagraphs().getCount();
    for (int paragraphIndex = 0; paragraphIndex < paragraphCount; paragraphIndex++) {
        IParagraph paragraph = textFrame.getParagraphs().get_Item(paragraphIndex);
        int portionCount = paragraph.getPortions().getCount();
        for (int portionIndex = 0; portionIndex < portionCount; portionIndex++) {
            IPortion portion = paragraph.getPortions().get_Item(portionIndex);
            portion.setText("Portion " + (paragraphIndex + 1) + "." + (portionIndex + 1));

            if (portionIndex == 0) {
                portion.getPortionFormat().getFillFormat().setFillType(FillType.Solid);
                portion.getPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.RED);
                portion.getPortionFormat().setFontBold(NullableBool.True);
                portion.getPortionFormat().setFontHeight(15);
            } else if (portionIndex == 1) {
                portion.getPortionFormat().getFillFormat().setFillType(FillType.Solid);
                portion.getPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLUE);
                portion.getPortionFormat().setFontItalic(NullableBool.True);
                portion.getPortionFormat().setFontHeight(18);
            }
        }
    }

    presentation.save("paragraphs_with_portions.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Создание маркированных и нумерованных списков

Создание маркированного или нумерованного списка

Маркированные пункты и нумерация упрощают просмотр связанных элементов. В Aspose.Slides настройки списка определяются через IBulletFormat.

  1. Создайте экземпляр класса Presentation.
  2. Получите доступ к соответствующему слайду по его индексу.
  3. Добавьте IAutoShape на выбранный слайд.
  4. Получите доступ к ITextFrame.
  5. Удалите абзац по умолчанию из текстового фрейма.
  6. Создайте Paragraph для символа маркера.
  7. Установите IBulletFormat.setType в значение BulletType.Symbol и задайте символ маркера.
  8. Установите текст абзаца, отступ, цвет маркера и высоту маркера.
  9. Добавьте абзац в текстовый фрейм.
  10. Создайте второй абзац и установите IBulletFormat.setType в значение BulletType.Numbered.
  11. Настройте стиль нумерованного маркера и добавьте абзац в текстовый фрейм.
  12. Сохраните презентацию.

Этот пример для Android via Java создаёт символный маркер и нумерованный маркер:

import com.aspose.slides.*;
import android.graphics.Color;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 200, 200, 400, 200);
    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getParagraphs().clear();

    Paragraph symbolParagraph = new Paragraph();
    symbolParagraph.setText("Welcome to Aspose.Slides");
    symbolParagraph.getParagraphFormat().getBullet().setType(BulletType.Symbol);
    symbolParagraph.getParagraphFormat().getBullet().setChar((char) 0x2022);
    symbolParagraph.getParagraphFormat().setIndent(25);
    symbolParagraph.getParagraphFormat().getBullet().getColor().setColorType(ColorType.RGB);
    symbolParagraph.getParagraphFormat().getBullet().getColor().setColor(Color.BLACK);
    symbolParagraph.getParagraphFormat().getBullet().setBulletHardColor(NullableBool.True);
    symbolParagraph.getParagraphFormat().getBullet().setHeight(100);
    textFrame.getParagraphs().add(symbolParagraph);

    Paragraph numberedParagraph = new Paragraph();
    numberedParagraph.setText("This is a numbered item");
    numberedParagraph.getParagraphFormat().getBullet().setType(BulletType.Numbered);
    numberedParagraph.getParagraphFormat().getBullet().setNumberedBulletStyle(NumberedBulletStyle.BulletCircleNumWDBlackPlain);
    numberedParagraph.getParagraphFormat().setIndent(25);
    numberedParagraph.getParagraphFormat().getBullet().getColor().setColorType(ColorType.RGB);
    numberedParagraph.getParagraphFormat().getBullet().getColor().setColor(Color.BLACK);
    numberedParagraph.getParagraphFormat().getBullet().setBulletHardColor(NullableBool.True);
    numberedParagraph.getParagraphFormat().getBullet().setHeight(100);
    textFrame.getParagraphs().add(numberedParagraph);

    presentation.save("bulleted_and_numbered_list.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Использование изображений в качестве маркеров

Маркеры с изображениями позволяют использовать пользовательскую картинку вместо символа или числа.

  1. Создайте экземпляр класса Presentation.
  2. Получите доступ к соответствующему слайду по его индексу.
  3. Добавьте IAutoShape и получите доступ к его ITextFrame.
  4. Удалите абзац по умолчанию из текстового фрейма.
  5. Загрузите изображение маркера и добавьте его в коллекцию изображений презентации как IPPImage.
  6. Создайте Paragraph и задайте его текст.
  7. Установите IBulletFormat.setType в значение BulletType.Picture.
  8. Назначьте изображение через IBulletFormat.getPicture и установите высоту маркера.
  9. Добавьте абзац в текстовый фрейм.
  10. Сохраните изменённую презентацию.

Этот пример для Android via Java создаёт маркер с изображением:

import com.aspose.slides.*;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IImage bulletImage = Images.fromFile("bullets.png");
    IPPImage presentationImage;
    try {
        presentationImage = presentation.getImages().addImage(bulletImage);
    } finally {
        bulletImage.dispose();
    }

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 200, 200, 400, 200);
    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getParagraphs().clear();

    Paragraph paragraph = new Paragraph();
    paragraph.setText("Welcome to Aspose.Slides");
    paragraph.getParagraphFormat().getBullet().setType(BulletType.Picture);
    paragraph.getParagraphFormat().getBullet().getPicture().setImage(presentationImage);
    paragraph.getParagraphFormat().getBullet().setHeight(100);
    textFrame.getParagraphs().add(paragraph);

    presentation.save("picture_bullet.pptx", SaveFormat.Pptx);
    presentation.save("picture_bullet.ppt", SaveFormat.Ppt);
} finally {
    presentation.dispose();
}

Создание многоуровневого списка

Установите IParagraphFormat.setDepth чтобы разместить абзацы на разных уровнях списка. Верхний уровень имеет глубину 0.

  1. Создайте Presentation и получите доступ к слайду.
  2. Добавьте IAutoShape и очистите абзац по умолчанию из её текстового фрейма.
  3. Создайте четыре абзаца и настройте их символы маркеров.
  4. Установите их значения IParagraphFormat.setDepth в 0, 1, 2 и 3.
  5. Добавьте абзацы в текстовый фрейм и сохраните презентацию.

Этот пример для Android via Java создаёт четырёхуровневый маркированный список:

import com.aspose.slides.*;
import android.graphics.Color;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 200, 200, 400, 200);
    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getParagraphs().clear();

    IParagraph firstParagraph = new Paragraph();
    firstParagraph.setText("Content");
    firstParagraph.getParagraphFormat().getBullet().setType(BulletType.Symbol);
    firstParagraph.getParagraphFormat().getBullet().setChar((char) 0x2022);
    firstParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    firstParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    firstParagraph.getParagraphFormat().setDepth((short) 0);

    IParagraph secondParagraph = new Paragraph();
    secondParagraph.setText("Second level");
    secondParagraph.getParagraphFormat().getBullet().setType(BulletType.Symbol);
    secondParagraph.getParagraphFormat().getBullet().setChar('-');
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    secondParagraph.getParagraphFormat().setDepth((short) 1);

    IParagraph thirdParagraph = new Paragraph();
    thirdParagraph.setText("Third level");
    thirdParagraph.getParagraphFormat().getBullet().setType(BulletType.Symbol);
    thirdParagraph.getParagraphFormat().getBullet().setChar((char) 0x2022);
    thirdParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    thirdParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    thirdParagraph.getParagraphFormat().setDepth((short) 2);

    IParagraph fourthParagraph = new Paragraph();
    fourthParagraph.setText("Fourth level");
    fourthParagraph.getParagraphFormat().getBullet().setType(BulletType.Symbol);
    fourthParagraph.getParagraphFormat().getBullet().setChar('-');
    fourthParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    fourthParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    fourthParagraph.getParagraphFormat().setDepth((short) 3);

    textFrame.getParagraphs().add(firstParagraph);
    textFrame.getParagraphs().add(secondParagraph);
    textFrame.getParagraphs().add(thirdParagraph);
    textFrame.getParagraphs().add(fourthParagraph);

    presentation.save("multilevel_list.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Начало нумерованных пунктов списка с пользовательских значений

Используйте IBulletFormat.setNumberedBulletStartWith чтобы задать начальный номер, отображаемый для нумерованного абзаца.

  1. Создайте Presentation и добавьте IAutoShape на слайд.
  2. Очистите абзац по умолчанию из текстового фрейма формы.
  3. Создайте три нумерованных абзаца.
  4. Установите IBulletFormat.setNumberedBulletStartWith в 2, 3 и 7 для соответствующих абзацев.
  5. Добавьте абзацы в текстовый фрейм и сохраните презентацию.

Этот пример для Android via Java задаёт пользовательский начальный номер для каждого абзаца:

import com.aspose.slides.*;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 200, 200, 400, 200);
    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getParagraphs().clear();

    Paragraph firstParagraph = new Paragraph();
    firstParagraph.setText("Start at 2");
    firstParagraph.getParagraphFormat().getBullet().setType(BulletType.Numbered);
    firstParagraph.getParagraphFormat().getBullet().setNumberedBulletStartWith((short) 2);
    textFrame.getParagraphs().add(firstParagraph);

    Paragraph secondParagraph = new Paragraph();
    secondParagraph.setText("Start at 3");
    secondParagraph.getParagraphFormat().getBullet().setType(BulletType.Numbered);
    secondParagraph.getParagraphFormat().getBullet().setNumberedBulletStartWith((short) 3);
    textFrame.getParagraphs().add(secondParagraph);

    Paragraph thirdParagraph = new Paragraph();
    thirdParagraph.setText("Start at 7");
    thirdParagraph.getParagraphFormat().getBullet().setType(BulletType.Numbered);
    thirdParagraph.getParagraphFormat().getBullet().setNumberedBulletStartWith((short) 7);
    textFrame.getParagraphs().add(thirdParagraph);

    presentation.save("custom_numbered_list.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Управление макетом абзаца и конечными свойствами

Установка отступа первой строки

Используйте IParagraphFormat.setIndent чтобы управлять отступом первой строки абзаца. Этот метод перемещает только первую строку относительно левого поля абзаца. Положительное значение сдвигает первую строку вправо, а остальные строки остаются выровненными по телу абзаца.

Используйте IParagraphFormat.setMarginLeft когда необходимо переместить весь абзац. Используйте IParagraphFormat.setIndent когда нужно переместить только первую строку.

Пример ниже создаёт несколько абзацев и применяет различные значения IParagraphFormat.setIndent чтобы продемонстрировать, как отступ первой строки влияет на макет абзаца.

  1. Создайте экземпляр класса Presentation.
  2. Получите доступ к целевому слайду.
  3. Добавьте прямоугольную IAutoShape на слайд.
  4. Получите доступ к ITextFrame формы и удалите абзац по умолчанию.
  5. Создайте несколько абзацев и установите разные значения IParagraphFormat.setIndent для них.
  6. Добавьте абзацы в текстовый фрейм.
  7. Сохраните изменённую презентацию.

Этот код показывает, как установить отступ абзаца:

import com.aspose.slides.*;
import android.graphics.Color;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 50, 50, 420, 220);
    shape.getFillFormat().setFillType(FillType.NoFill);
    shape.getLineFormat().getFillFormat().setFillType(FillType.Solid);
    shape.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.GRAY);

    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getTextFrameFormat().setAutofitType(TextAutofitType.Shape);
    textFrame.getParagraphs().clear();

    Paragraph firstParagraph = new Paragraph();
    firstParagraph.setText("No first-line indent. Wrapped lines start at the same position as the first line.");
    firstParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    firstParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    firstParagraph.getParagraphFormat().setMarginLeft(20f);
    firstParagraph.getParagraphFormat().setIndent(0f);

    Paragraph secondParagraph = new Paragraph();
    secondParagraph.setText("First-line indent of 20 points. The first line moves to the right, while wrapped lines remain aligned to the paragraph body.");
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    secondParagraph.getParagraphFormat().setMarginLeft(20f);
    secondParagraph.getParagraphFormat().setIndent(20f);

    Paragraph thirdParagraph = new Paragraph();
    thirdParagraph.setText("First-line indent of 40 points. This paragraph shows a larger first-line offset to make the effect easier to see.");
    thirdParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    thirdParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    thirdParagraph.getParagraphFormat().setMarginLeft(20f);
    thirdParagraph.getParagraphFormat().setIndent(40f);

    textFrame.getParagraphs().add(firstParagraph);
    textFrame.getParagraphs().add(secondParagraph);
    textFrame.getParagraphs().add(thirdParagraph);

    presentation.save("paragraph_indent.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Результат:

Отступ первой строки абзацев

Установка висячего отступа

Висячий отступ — это макет абзаца, при котором первая строка начинается левее остальных строк. В Aspose.Slides вы создаёте этот эффект с помощью IParagraphFormat.setIndent. Передайте отрицательное значение, чтобы переместить первую строку влево относительно тела абзаца.

На практике IParagraphFormat.setMarginLeft определяет левую позицию тела абзаца, а IParagraphFormat.setIndent определяет позицию первой строки относительно этого поля. Чтобы создать висячий отступ, передайте положительное значение в setMarginLeft и отрицательное значение в setIndent.

Это форматирование полезно для библиографий, ссылок, глоссариев и других абзацев, где перенесённые строки должны выравниваться под телом абзаца, а не под первым символом первой строки.

  1. Создайте экземпляр класса Presentation.
  2. Получите доступ к целевому слайду.
  3. Добавьте прямоугольную IAutoShape на слайд.
  4. Получите доступ к ITextFrame формы и удалите абзац по умолчанию.
  5. Создайте абзацы и передайте положительное значение IParagraphFormat.setMarginLeft для каждого абзаца.
  6. Передайте отрицательное значение IParagraphFormat.setIndent чтобы создать эффект висячего отступа.
  7. Добавьте абзацы в текстовый фрейм.
  8. Сохраните изменённую презентацию.

Этот код показывает, как установить висячий отступ для абзаца:

import com.aspose.slides.*;
import android.graphics.Color;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 50, 50, 420, 220);
    shape.getFillFormat().setFillType(FillType.NoFill);
    shape.getLineFormat().getFillFormat().setFillType(FillType.Solid);
    shape.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.GRAY);

    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getTextFrameFormat().setAutofitType(TextAutofitType.Shape);
    textFrame.getParagraphs().clear();

    Paragraph firstParagraph = new Paragraph();
    firstParagraph.setText("A hanging indent is created by combining a positive left margin with a negative indent. The first line starts to the left, while wrapped lines align with the paragraph body.");
    firstParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    firstParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    firstParagraph.getParagraphFormat().setMarginLeft(40f);
    firstParagraph.getParagraphFormat().setIndent(-20f);

    Paragraph secondParagraph = new Paragraph();
    secondParagraph.setText("This second example uses a deeper hanging indent so the difference between the first line and the wrapped lines is easier to compare.");
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
    secondParagraph.getParagraphFormat().setMarginLeft(60f);
    secondParagraph.getParagraphFormat().setIndent(-30f);

    textFrame.getParagraphs().add(firstParagraph);
    textFrame.getParagraphs().add(secondParagraph);

    presentation.save("hanging_indent.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Результат:

Висячий отступ абзацев

Установка свойств конечного фрагмента абзаца

IParagraph.setEndParagraphPortionFormat управляет форматированием конечного знака абзаца. Следующий пример назначает размер шрифта и латинский шрифт конечному знаку второго абзаца:

  1. Загрузите Presentation и получите доступ к слайду.
  2. Добавьте IAutoShape и очистите его абзац по умолчанию.
  3. Создайте два абзаца и добавьте к ним текстовые фрагменты.
  4. Создайте PortionFormat для конечного знака второго абзаца.
  5. Установите IBasePortionFormat.setFontHeight и IBasePortionFormat.setLatinFont.
  6. Присвойте формат с помощью IParagraph.setEndParagraphPortionFormat и сохраните презентацию.
import com.aspose.slides.*;

Presentation presentation = new Presentation("Test.pptx");
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 10, 10, 200, 250);
    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getParagraphs().clear();

    Paragraph firstParagraph = new Paragraph();
    firstParagraph.getPortions().add(new Portion("Sample text"));

    Paragraph secondParagraph = new Paragraph();
    secondParagraph.getPortions().add(new Portion("Sample text 2"));

    PortionFormat endParagraphFormat = new PortionFormat();
    endParagraphFormat.setFontHeight(48);
    endParagraphFormat.setLatinFont(new FontData("Times New Roman"));
    secondParagraph.setEndParagraphPortionFormat(endParagraphFormat);

    textFrame.getParagraphs().add(firstParagraph);
    textFrame.getParagraphs().add(secondParagraph);

    presentation.save("end_paragraph_format.pptx", SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Подсчёт отрисованных строк

Для правил абзаца, влияющих на автоматический перенос и пунктуацию в конце строк, см. Управление разрывом строк и Управление висячей пунктуацией.

Используйте IParagraph.getLinesCount чтобы подсчитать количество строк, занимаемых абзацем после размещения текста, включая автоматический перенос. Это полезно при проверке длины текста и макета в шаблонах презентаций.

Абзац является одним элементом в ITextFrame.getParagraphs и может занимать несколько отрисованных строк. Явный разрыв строки внутри абзаца заставляет перейти на новую строку без создания другого абзаца. Автоматический перенос создает строки на основе доступной ширины без вставки явных разрывов строк в текст. Поэтому подсчёт абзацев или символов разрыва строк не дает количества отрисованных строк.

Следующий пример создаёт текстовую форму, считает её строки, сужает форму, а затем заменяет текст более короткой строкой. Перенос включён, а автоподгонка отключена, чтобы ширина формы контролировала перенос без автоматического уменьшения текста или изменения размеров формы. Размеры формы указаны в пунктах. В конце пример добавляет ещё один абзац и суммирует количество строк по всему текстовому фрейму.

import com.aspose.slides.*;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 50, 50, 400, 200);
    ITextFrame textFrame = shape.getTextFrame();
    textFrame.getTextFrameFormat().setWrapText(NullableBool.True);
    textFrame.getTextFrameFormat().setAutofitType(TextAutofitType.None);

    IParagraph paragraph = textFrame.getParagraphs().get_Item(0);
    paragraph.getParagraphFormat().getDefaultPortionFormat().setFontHeight(20);
    paragraph.setText("This text demonstrates how automatic wrapping changes the number of rendered lines.");
    System.out.println("Original width: " + paragraph.getLinesCount());

    shape.setWidth(150);
    System.out.println("Narrower shape: " + paragraph.getLinesCount());

    paragraph.setText("Short text.");
    System.out.println("Shorter text: " + paragraph.getLinesCount());

    Paragraph secondParagraph = new Paragraph();
    secondParagraph.setText("Another paragraph.");
    secondParagraph.getParagraphFormat().getDefaultPortionFormat().setFontHeight(20);
    textFrame.getParagraphs().add(secondParagraph);

    int totalLineCount = 0;
    for (IParagraph currentParagraph : textFrame.getParagraphs()) {
        totalLineCount += currentParagraph.getLinesCount();
    }
    System.out.println("Total lines in the text frame: " + totalLineCount);
} finally {
    presentation.dispose();
}

При таком тексте и этих размерах сужение формы увеличивает количество строк, а замена текста короткой строкой уменьшает его. Точные подсчёты могут различаться в зависимости от доступности шрифтов и их замены, размера шрифта, полей, отступов, переноса и настроек автоподгонки. При проверке шаблона используйте шрифты и настройки макета, предназначенные для целевой среды.

Только количество строк не определяет, выходит ли текст за пределы контейнера. Важны также доступная высота, высота строк, межабзацевый и межстрочный интервал, а также поведение автоподгонки; даже одна строка может превышать доступную ширину, если перенос отключён.

Импорт и экспорт содержимого абзаца

Импорт HTML‑текста в абзацы

Используйте ParagraphCollection.addFromHtml чтобы преобразовать разметку HTML в абзацы и фрагменты в текстовом фрейме.

  1. Создайте экземпляр класса Presentation.
  2. Получите доступ к слайду и добавьте IAutoShape.
  3. Получите доступ к ITextFrame формы и очистите её абзац по умолчанию.
  4. Прочитайте исходный файл HTML.
  5. Передайте строку HTML в ParagraphCollection.addFromHtml.
  6. Сохраните изменённую презентацию.

Этот пример для Android via Java импортирует HTML в текстовый фрейм:

import com.aspose.slides.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    float shapeWidth = (float) presentation.getSlideSize().getSize().getWidth() - 20;
    float shapeHeight = (float) presentation.getSlideSize().getSize().getHeight() - 20;
    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 10, 10, shapeWidth, shapeHeight);
    shape.getFillFormat().setFillType(FillType.NoFill);
    shape.getTextFrame().getParagraphs().clear();

    try {
        byte[] htmlBytes = Files.readAllBytes(Paths.get("file.html"));
        String html = new String(htmlBytes, StandardCharsets.UTF_8);
        shape.getTextFrame().getParagraphs().addFromHtml(html);
        presentation.save("html_text.pptx", SaveFormat.Pptx);
    } catch (IOException exception) {
        System.out.println("The HTML file could not be read: " + exception.getMessage());
    }
} finally {
    presentation.dispose();
}

Экспорт текста абзаца в HTML

Используйте ParagraphCollection.exportToHtml чтобы экспортировать выбранный диапазон абзацев в виде HTML.

  1. Создайте экземпляр класса Presentation и загрузите нужную презентацию.
  2. Получите доступ к слайду и найдите IAutoShape, содержащий текст.
  3. Получите доступ к ITextFrame.
  4. Вызовите ParagraphCollection.exportToHtml с индексом начального абзаца и количеством абзацев для экспорта.
  5. Запишите возвращённую строку HTML в файл.

Этот пример для Android via Java экспортирует все абзацы из первой текстовой формы:

import com.aspose.slides.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

Presentation presentation = new Presentation("ExportingHTMLText.pptx");
try {
    IShape shape = presentation.getSlides().get_Item(0).getShapes().get_Item(0);

    if (shape instanceof IAutoShape) {
        IAutoShape textShape = (IAutoShape) shape;
        ITextFrame textFrame = textShape.getTextFrame();
        if (textFrame != null) {
            IParagraphCollection paragraphs = textFrame.getParagraphs();
            String html = paragraphs.exportToHtml(0, paragraphs.getCount(), null);
            try {
                Files.write(Paths.get("paragraphs.html"), html.getBytes(StandardCharsets.UTF_8));
            } catch (IOException exception) {
                System.out.println("The HTML file could not be written: " + exception.getMessage());
            }
        } else {
            System.out.println("The first shape does not contain a text frame.");
        }
    } else {
        System.out.println("The first shape is not a text shape.");
    }
} finally {
    presentation.dispose();
}

Отображение абзаца в виде изображения

IParagraph.getImage отображает отдельный абзац напрямую и возвращает IImage. Сохраните результат в файл или поток с помощью IImage.save. Нет необходимости рендерить содержащую форму или вручную обрезать растровое изображение.

IParagraph.getImage может вернуть null, если абзац не найден в родительской коллекции, не имеет допустимых границ рендеринга или не может быть отрендерен. Проверьте результат перед сохранением и освободите полученное изображение после использования.

Отображение абзаца в масштабе по умолчанию

Допустим, у нас есть файл презентации sample.pptx с одним слайдом, где первая форма — текстовый блок, содержащий три абзаца.

Текстовый блок с тремя абзацами

Следующий пример рендерит второй абзац в обычной текстовой форме в масштабе по умолчанию и сохраняет полученное изображение в формате PNG. Блок finally гарантирует корректное освобождение изображения.

import com.aspose.slides.*;

Presentation presentation = new Presentation("sample.pptx");
try {
    IShape shape = presentation.getSlides().get_Item(0).getShapes().get_Item(0);

    if (shape instanceof IAutoShape) {
        IAutoShape textShape = (IAutoShape) shape;
        ITextFrame textFrame = textShape.getTextFrame();
        if (textFrame != null && textFrame.getParagraphs().getCount() > 1) {
            IParagraph paragraph = textFrame.getParagraphs().get_Item(1);
            IImage paragraphImage = paragraph.getImage();

            if (paragraphImage != null) {
                try {
                    paragraphImage.save("paragraph.png", ImageFormat.Png);
                } finally {
                    paragraphImage.dispose();
                }
            } else {
                System.out.println("The paragraph could not be rendered.");
            }
        } else {
            System.out.println("The expected paragraph was not found.");
        }
    } else {
        System.out.println("The first shape is not a text shape.");
    }
} finally {
    presentation.dispose();
}

Результат:

Изображение абзаца

Отображение абзаца в ячейке таблицы с масштабированием

Используйте перегрузку IParagraph.getImage принимающую параметры float scaleX и float scaleY, чтобы задать горизонтальные и вертикальные коэффициенты масштабирования. Следующий пример создаёт таблицу, рендерит абзац в её первой ячейке в два раза шире и выше, чем по умолчанию, и сохраняет результат в виде PNG‑изображения.

import com.aspose.slides.*;

float scaleX = 2f;
float scaleY = 2f;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);
    ITable table = slide.getShapes().addTable(50, 50, new double[] { 300 }, new double[] { 80 });
    IParagraph paragraph = table.get_Item(0, 0).getTextFrame().getParagraphs().get_Item(0);
    paragraph.setText("Text in a table cell");

    IImage paragraphImage = paragraph.getImage(scaleX, scaleY);
    if (paragraphImage != null) {
        try {
            paragraphImage.save("table_paragraph.png", ImageFormat.Png);
        } finally {
            paragraphImage.dispose();
        }
    } else {
        System.out.println("The paragraph could not be rendered.");
    }
} finally {
    presentation.dispose();
}

Коэффициент масштабирования 1 сохраняет ось с её размером по умолчанию в пикселях. Например, 2 для обеих осей создаёт изображение, ширина и высота которого примерно вдвое больше стандартных размеров, в результате получаем в четыре раза больше пикселей. Большие коэффициенты обычно дают более чёткий текст при масштабировании или выводе в высоком разрешении, но также увеличивают использование памяти и размер файла. Коэффициенты ниже 1 дают более мелкие изображения с меньшей детализацией. Используйте одинаковые коэффициенты, чтобы сохранять соотношение сторон абзаца; разные горизонтальные и вертикальные коэффициенты растягивают вывод независимо.

Отображение всей формы с помощью IShape.getImage остаётся полезным, когда вывод должен включать заливку формы, границу или другой визуальный контекст. Для изображения только абзаца используйте IParagraph.getImage.

Вопросы и ответы

Можно ли полностью отключить перенос строк внутри текстового фрейма?

Да. Установите ITextFrameFormat.setWrapText чтобы отключить перенос, и строки не будут разбиваться у краёв текстового фрейма.

Как получить точные границы конкретного абзаца на слайде?

Используйте IParagraph.getRect чтобы получить ограничивающий прямоугольник абзаца. IPortion.getRect предоставляет границы отдельного фрагмента.

Где управляется выравнивание абзаца (по левому, правому краю, по центру или по ширине)?

IParagraphFormat.setAlignment — это настройка уровня абзаца и применяется ко всему абзацу независимо от форматирования отдельных фрагментов. Чтобы вертикально выравнивать шрифты разных размеров внутри каждой строки, смотрите Вертикальное выравнивание шрифтов в строке.

Можно ли задать язык проверки правописания для части абзаца?

Да. Установите IBasePortionFormat.setLanguageId для отдельных фрагментов, чтобы один абзац мог содержать текст на разных языках.