Zarządzanie listami wypunktowanymi i numerowanymi w prezentacjach w .NET

Przegląd

Aspose.Slides for .NET umożliwia tworzenie i formatowanie list wypunktowanych oraz numerowanych w prezentacjach PowerPoint i OpenDocument. Element listy to akapit, którego ustawienia wypunktowania są kontrolowane poprzez format akapitu.

Użyj właściwości IParagraph.ParagraphFormat aby uzyskać dostęp do ustawień listy na poziomie akapitu. Głównym punktem wejścia jest IParagraphFormat.Bullet, które zwraca obiekt IBulletFormat. Dzięki temu obiektowi możesz ustawić typ wypunktowania, symbol, obraz, kolor, rozmiar, styl numeracji oraz numer początkowy.

Ten artykuł pokazuje, jak:

  • utworzyć listę wypunktowaną z niestandardowym symbolem
  • utworzyć wypunktowanie obrazkiem
  • utworzyć listę wielopoziomową, ustawiając głębokość akapitu
  • utworzyć listę numerowaną
  • sprawdzić i zmienić formatowanie listy w istniejącej prezentacji
  • odczytać rzeczywiste znaczniki list i numery wraz z tekstem akapitu

Utworzenie listy wypunktowanej

Aby utworzyć listę wypunktowaną, dodaj obiekty IParagraph do ITextFrame i ustaw IBulletFormat.Type na BulletType.Symbol. Następnie możesz ustawić IBulletFormat.Char, IBulletFormat.Color i IBulletFormat.Height, aby kontrolować wygląd wypunktowania.

Poniższy kod C# demonstruje, jak utworzyć listę wypunktowaną na slajdzie:

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

static Paragraph CreateParagraph(string text)
{
    var paragraph = new Paragraph();
    paragraph.ParagraphFormat.Bullet.Type = BulletType.Symbol;
    paragraph.ParagraphFormat.Bullet.Char = '*';
    paragraph.ParagraphFormat.Indent = 15;
    paragraph.ParagraphFormat.Bullet.IsBulletHardColor = NullableBool.True;
    paragraph.ParagraphFormat.Bullet.Color.Color = Color.IndianRed;
    paragraph.ParagraphFormat.Bullet.Height = 100;
    paragraph.Text = text;
    return paragraph;
}

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var autoShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 20, 20, 200, 50);

var textFrame = autoShape.TextFrame;
textFrame.Paragraphs.Clear();

var paragraph1 = CreateParagraph("The first paragraph");
textFrame.Paragraphs.Add(paragraph1);

var paragraph2 = CreateParagraph("The second paragraph");
textFrame.Paragraphs.Add(paragraph2);

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

Wynik:

Wypunktowanie symbolem

Utworzenie listy numerowanej

Używaj list numerowanych, gdy kolejność elementów ma znaczenie. Ustaw IBulletFormat.Type na BulletType.Numbered. Możesz także wybrać format numeracji za pomocą IBulletFormat.NumberedBulletStyle lub ustawić IBulletFormat.NumberedBulletStartWith, gdy lista ma zaczynać się od wartości innej niż 1.

Poniższy kod C# pokazuje, jak utworzyć listę numerowaną na slajdzie:

using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var autoShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 20, 20, 90, 80);

var textFrame = autoShape.TextFrame;
textFrame.Paragraphs.Clear();

var paragraph1 = new Paragraph();
paragraph1.ParagraphFormat.Bullet.Type = BulletType.Numbered;
paragraph1.Text = "Apple";
textFrame.Paragraphs.Add(paragraph1);

var paragraph2 = new Paragraph();
paragraph2.ParagraphFormat.Bullet.Type = BulletType.Numbered;
paragraph2.Text = "Orange";
textFrame.Paragraphs.Add(paragraph2);

var paragraph3 = new Paragraph();
paragraph3.ParagraphFormat.Bullet.Type = BulletType.Numbered;
paragraph3.Text = "Banana";
textFrame.Paragraphs.Add(paragraph3);

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

Wynik:

Wypunktowanie numerowane

Utworzenie wypunktowania obrazkiem

Aspose.Slides pozwala zamienić zwykły symbol wypunktowania na obraz. Wypunktowanie obrazkiem działa najlepiej z prostymi grafikami, które pozostają czytelne przy małym rozmiarze, takimi jak ikony lub małe pliki PNG z przezroczystością.

Aby utworzyć wypunktowanie obrazkiem, dodaj obraz do Presentation.Images i przypisz zwrócony obiekt obrazu do IBulletFormat.Picture. Ustaw IBulletFormat.Type na BulletType.Picture przed przypisaniem obrazu.

Załóżmy, że mamy plik „image.png”:

Obraz do wypunktowania

Poniższy kod C# pokazuje, jak utworzyć wypunktowanie obrazkiem na slajdzie:

using Aspose.Slides;
using Aspose.Slides.Export;

static Paragraph CreateParagraph(string text, IPPImage image)
{
    var paragraph = new Paragraph();
    paragraph.ParagraphFormat.Bullet.Type = BulletType.Picture;
    paragraph.ParagraphFormat.Bullet.Picture.Image = image;
    paragraph.ParagraphFormat.Indent = 15;
    paragraph.ParagraphFormat.Bullet.Height = 100;
    paragraph.Text = text;
    return paragraph;
}

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var autoShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 20, 20, 200, 50);

var textFrame = autoShape.TextFrame;
textFrame.Paragraphs.Clear();

var imageBytes = File.ReadAllBytes("image.png");
var bulletImage = presentation.Images.AddImage(imageBytes);

var paragraph1 = CreateParagraph("The first paragraph", bulletImage);
textFrame.Paragraphs.Add(paragraph1);

var paragraph2 = CreateParagraph("The second paragraph", bulletImage);
textFrame.Paragraphs.Add(paragraph2);

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

Wynik:

Wypunktowanie obrazkiem

Utworzenie listy wielopoziomowej

Użyj IParagraphFormat.Depth, aby umieścić elementy listy na różnych poziomach. Poziom 0 to poziom najwyższy, poziom 1 jest zagnieżdżony pod nim itd.

Poniższy kod C# pokazuje, jak utworzyć wielopoziomową listę wypunktowaną:

using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var autoShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 20, 20, 260, 110);

var textFrame = autoShape.TextFrame;
textFrame.Paragraphs.Clear();

var paragraph1 = new Paragraph();
paragraph1.ParagraphFormat.Depth = 0;
paragraph1.Text = "My text - Depth 0";
textFrame.Paragraphs.Add(paragraph1);

var paragraph2 = new Paragraph();
paragraph2.ParagraphFormat.Depth = 1;
paragraph2.Text = "My text - Depth 1";
textFrame.Paragraphs.Add(paragraph2);

var paragraph3 = new Paragraph();
paragraph3.ParagraphFormat.Depth = 2;
paragraph3.Text = "My text - Depth 2";
textFrame.Paragraphs.Add(paragraph3);

var paragraph4 = new Paragraph();
paragraph4.ParagraphFormat.Depth = 3;
paragraph4.Text = "My text - Depth 3";
textFrame.Paragraphs.Add(paragraph4);

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

Wynik:

Lista wielopoziomowa

Zmiana istniejącej listy

Aby zmienić formatowanie listy w istniejącej prezentacji, uzyskaj dostęp do docelowego akapitu i zaktualizuj jego ustawienia IParagraphFormat.Bullet. Te same właściwości użyte do tworzenia list mogą być użyte do przeglądania lub modyfikacji list załadowanych z pliku PPT, PPTX lub ODP.

Poniższy kod C# zmienia pierwszy akapit w ramce tekstowej, aby używał stylu listy numerowanej:

using Aspose.Slides;
using Aspose.Slides.Export;

using var presentation = new Presentation("input.pptx");
var slide = presentation.Slides[0];
var autoShape = (IAutoShape)slide.Shapes[0];

var paragraph = autoShape.TextFrame.Paragraphs[0];
paragraph.ParagraphFormat.Bullet.Type = BulletType.Numbered;
paragraph.ParagraphFormat.Bullet.NumberedBulletStyle = NumberedBulletStyle.BulletRomanUCPeriod;
paragraph.ParagraphFormat.Bullet.NumberedBulletStartWith = 1;
paragraph.ParagraphFormat.MarginLeft = 30;
paragraph.ParagraphFormat.Indent = -20;

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

Odczyt rzeczywistych wartości wypunktowania

Podczas wyodrębniania treści prezentacji należy zachować znaczniki listy wraz z tekstem akapitu. Wywołaj IParagraphFormat.GetEffective i uzyskaj dostęp do IParagraphFormatEffectiveData.Bullet, aby otrzymać efektywny format wypunktowania. Sprawdź jego Type przed odczytaniem ActualBulletValue.

Dla list numerowanych rozróżnia się trzy wartości:

  • NumberedBulletStyle określa format, np. liczby arabskie z kropką lub małe litery z kropką.
  • NumberedBulletStartWith określa numer początkowy dla grupy numerowanych akapitów.
  • ActualBulletValue zwraca sformatowany znacznik dla konkretnego akapitu. Na przykład drugi element listy zaczynającej się od 5 zwróci 6..

Zachowuj Depth przy każdym akapicie, aby utrzymać jego poziom zagnieżdżenia. Rzeczywisty znacznik nie koduje pełnej hierarchii: element zagnieżdżony może zwrócić c. zamiast połączonej etykiety takiej jak 6.c..

Poniższy, samodzielny przykład tworzy listy, zapisuje je do prezentacji i ponownie wczytuje prezentację, aby zgłosić tekst każdego akapitu, jego głębokość, typ wypunktowania oraz rzeczywistą wartość. Mały niebieski znacznik obrazkowy jest tworzony z wbudowanego SVG.

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

using (var presentation = new Presentation())
{
    presentation.SlideSize.SetSize(720, 440, SlideSizeScaleType.DoNotScale);
    var slide = presentation.Slides[0];

    var shape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 30, 20, 660, 400);
    shape.FillFormat.FillType = FillType.NoFill;
    shape.LineFormat.FillFormat.FillType = FillType.NoFill;

    var textFrame = shape.TextFrame;
    textFrame.Paragraphs.Clear();

    // Utwórz znacznik obrazka bez zewnętrznego pliku obrazu.
    var svg = new SvgImage("<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16'><rect width='16' height='16' rx='4' fill='#0078D4'/></svg>");
    var bulletImage = presentation.Images.AddImage(svg);

    void AddParagraph(string text, short depth, BulletType type, short start = 1, NumberedBulletStyle style = NumberedBulletStyle.BulletArabicPeriod)
    {
        var paragraph = new Paragraph { Text = text };

        var format = paragraph.ParagraphFormat;
        format.Depth = depth;
        format.MarginLeft = 30 + depth * 40;
        format.Indent = -28;
        format.SpaceAfter = 8;
        format.DefaultPortionFormat.FontHeight = 22;
        format.DefaultPortionFormat.FillFormat.FillType = FillType.Solid;
        format.DefaultPortionFormat.FillFormat.SolidFillColor.Color = Color.Black;
        format.Bullet.Type = type;
        format.Bullet.IsBulletHardColor = NullableBool.True;
        format.Bullet.Color.Color = Color.Black;
        if (type == BulletType.Numbered)
        {
            format.Bullet.NumberedBulletStyle = style;
            format.Bullet.NumberedBulletStartWith = start;
        }
        else if (type == BulletType.Symbol)
        {
            format.Bullet.Char = '\u2022';
        }
        else if (type == BulletType.Picture)
        {
            format.Bullet.Picture.Image = bulletImage;
        }

        textFrame.Paragraphs.Add(paragraph);
    }

    AddParagraph("First item", 0, BulletType.Numbered, 5);
    AddParagraph("Second item", 0, BulletType.Numbered, 5);
    AddParagraph("Nested item", 1, BulletType.Numbered, 3, NumberedBulletStyle.BulletAlphaLCPeriod);
    AddParagraph("Next nested item", 1, BulletType.Numbered, 3, NumberedBulletStyle.BulletAlphaLCPeriod);
    AddParagraph("Deep item", 2, BulletType.Numbered, 4, NumberedBulletStyle.BulletRomanLCPeriod);
    AddParagraph("Back to top level", 0, BulletType.Numbered, 5);
    AddParagraph("Symbol marker", 0, BulletType.Symbol);
    AddParagraph("No bullet", 0, BulletType.None);
    AddParagraph("Picture marker", 0, BulletType.Picture);
    presentation.Save("actual_bullet_values.pptx", SaveFormat.Pptx);
}

using var loadedPresentation = new Presentation("actual_bullet_values.pptx");
var loadedShape = (IAutoShape)loadedPresentation.Slides[0].Shapes[0];
Console.WriteLine("Text | Depth | Type | Actual value");
foreach (var paragraph in loadedShape.TextFrame.Paragraphs)
{
    var bullet = paragraph.ParagraphFormat.GetEffective().Bullet;
    string marker;
    switch (bullet.Type)
    {
        case BulletType.Numbered:
        case BulletType.Symbol:
            marker = bullet.ActualBulletValue;
            break;
        case BulletType.None:
            marker = $"{bullet.ActualBulletValue ?? "null"} (no bullet)";
            break;
        case BulletType.Picture:
            marker = $"{bullet.ActualBulletValue ?? "null"} (image required)";
            break;
        default:
            marker = "unsupported bullet type";
            break;
    }
    Console.WriteLine($"{paragraph.Text} | {paragraph.ParagraphFormat.Depth} | {bullet.Type} | {marker}");
}

Źródłowe listy są przedstawione poniżej.

Listy zaczynające się od 5, zagnieżdżone elementy literowe i rzymskie, symboliczny znacznik, akapit bez wypunktowania oraz niebieski znacznik obrazkowy

Raport odpowiada znacznikom wyświetlanym w PowerPoint:

Text | Depth | Type | Actual value
First item | 0 | Numbered | 5.
Second item | 0 | Numbered | 6.
Nested item | 1 | Numbered | c.
Next nested item | 1 | Numbered | d.
Deep item | 2 | Numbered | iv.
Back to top level | 0 | Numbered | 7.
Symbol marker | 0 | Symbol | •
No bullet | 0 | None | null (no bullet)
Picture marker | 0 | Picture | null (image required)

Dla BulletType.None i BulletType.Picture, ActualBulletValue zwraca null, a nie pusty ciąg znaków. Obsługuj te typy oddzielnie: pierwszy nie ma znacznika, drugi wymaga osobnego wyodrębnienia obrazu wypunktowania. Wypunktowanie obrazkiem nie może być odtworzone wyłącznie poprzez wyodrębnienie znacznika tekstowego.

FAQ

Czy listy wypunktowane i numerowane mogą być eksportowane do PDF lub obrazów?

Tak. Aspose.Slides zachowuje formatowanie list, gdy docelowy format obsługuje odpowiadający układ tekstu i funkcje wypunktowania.

Czy mogę edytować listy w istniejących prezentacjach?

Tak. Wczytaj prezentację, uzyskaj dostęp do docelowego akapitu, sprawdź lub zaktualizuj jego ustawienia IParagraphFormat.Bullet i zapisz prezentację.

Czy listy mogą zawierać tekst niełaciński?

Tak. Tekst elementów listy może zawierać znaki Unicode, więc możesz tworzyć listy w wielojęzycznych prezentacjach. Upewnij się, że użyte w prezentacji czcionki obsługują potrzebne znaki.