Fortschrittsanzeige (ppptools.Progress)

Erstellt: 2026-07-11 · Aktualisiert: 2026-07-11

Länger laufende Snippets/Actions blockieren den UI-Thread — ohne Rückmeldung sieht man nur den Wartecursor. PPPTools zeigt deshalb eine Fortschrittsanzeige, die animiert bleibt, während dein Code läuft (sie läuft auf einem eigenen Thread).

Es gibt zwei Ebenen:

  1. Automatisch — bei jedem Lauf, der länger als ~0,4 s dauert, erscheint ein „Wird ausgeführt…"-Fenster (Marquee) mit Abbrechen. Dafür musst du nichts tun.
  2. Mit echtem Fortschritt — wenn dein Code die Gesamtzahl kennt (z. B. Anzahl Folien), schaltest du mit ppptools.Progress(...) auf einen Prozentbalken um.

ppptools.Progress(text, total)

var p = ppptools.Progress("Formatiere Folien…", ppptools.SlideCount);
for (int s = 1; s <= ppptools.SlideCount; s++)
{
    p.Report(s, $"Folie {s} von {ppptools.SlideCount}");   // Balken + Text
    FormatShapes(ppptools.GetAllShapes(ppptools.GetSlide(s)));
}
  • Progress(text, total) — startet den determinierten Balken (0…total) und gibt ein Handle zurück.
  • Report(value, text) — aktualisiert Balken und Text. Report(text) (nur Text) geht auch für unbestimmte Schritte.
  • Die Anzeige schliesst sich automatisch am Ende des Laufs (bzw. sobald du ppptools.ShowResult/ResultDialog zeigst).

Abbrechen

Das „Abbrechen" im Fenster wirkt so:

  • Mit ppptools.Progress: der nächste Report(...)-Aufruf wirft eine OperationCanceledException → deine Schleife stoppt sofort und sauber. Willst du ohne Exception reagieren, prüfe p.IsCanceled.
  • Ohne Progress (nur Auto-Anzeige): Abbrechen greift am nächsten Prüfpunkt — bei einer engen Rechenschleife ohne Report also evtl. erst am Ende. Für zuverlässiges Abbrechen langer Läufe daher Progress verwenden.

Nur bei Bedarf

Kurze Snippets brauchen nichts — die Auto-Anzeige erscheint erst ab ~0,4 s. Progress lohnt sich, sobald du über viele Folien/Shapes iterierst.


Vollständiges Beispiel

Text über alle Folien suchen und formatieren — mit Fortschrittsbalken, sauberem Abbruch-Handling und Ergebnis-Dialog am Schluss:

// @param string SearchString "Suchbegriff" tooltip="Zu formatierender Text"
// @param font   FormatFont   "Format"      default="Calibri,18,Bold"
// @button Ausführen

string searchString = Params.GetString("SearchString", "");
var    fmt          = Params.GetFont("FormatFont");
int    replaced     = 0;

void FormatShapes(System.Collections.Generic.List<dynamic> shapes)
{
    foreach (dynamic sh in shapes)
    {
        if ((int)sh.HasTextFrame != (int)MsoTriState.msoTrue) continue;
        dynamic tr = sh.TextFrame.TextRange;

        dynamic found = tr.Find(searchString, 0, MsoTriState.msoFalse, MsoTriState.msoFalse);
        while (found != null)
        {
            found.Font.Name = fmt.Name;
            found.Font.Size = fmt.SizeInPoints;
            found.Font.Bold = fmt.Bold ? MsoTriState.msoTrue : MsoTriState.msoFalse;
            replaced++;
            int after = found.Start + found.Length - 1;
            found = tr.Find(searchString, after, MsoTriState.msoFalse, MsoTriState.msoFalse);
        }
    }
}

if (!string.IsNullOrWhiteSpace(searchString))
{
    // Fortschritt über alle Folien
    var p = ppptools.Progress("Formatiere Folien…", ppptools.SlideCount);
    try
    {
        for (int s = 1; s <= ppptools.SlideCount; s++)
        {
            p.Report(s, $"Folie {s} von {ppptools.SlideCount}");   // Abbrechen → wirft hier
            FormatShapes(ppptools.GetAllShapes(ppptools.GetSlide(s)));
        }

        // Ergebnis (schliesst die Fortschrittsanzeige automatisch)
        ppptools.ShowResult("Fertig",
            $"<b>{replaced}</b> Treffer über {ppptools.SlideCount} Folien formatiert.",
            "OK", "success");
    }
    catch (System.OperationCanceledException)
    {
        // „Abbrechen" wurde geklickt — sauber melden
        ppptools.ShowResult("Abgebrochen",
            $"Vorzeitig gestoppt — <b>{replaced}</b> Treffer bis dahin formatiert.",
            "OK", "warn");
    }
}

Ablauf: Ab ~0,4 s erscheint das Fenster mit Prozentbalken und „Folie x von y". Klickt der Benutzer Abbrechen, wirft der nächste p.Report(...) eine OperationCanceledException → der catch meldet, wie viele Treffer bis dahin bearbeitet wurden. Am regulären Ende schliesst ShowResult die Anzeige und zeigt das Resultat.


Verwandte Seiten