Navigieren durch Absätze

(Übersetzung von »Navigating Paragraphs« von Rick Quatro)

Die Navigation durch die Absätze eines FrameMaker-Dokuments ist eine der wesentlichen Aufgaben von FrameScript. In diesem Tutorial werden mehrere Methoden hierfür vorgestellt. Hintergrundinformationen finden Sie im Tutorial »Schleifen und Listen«.

Absatzschleifen

Der einfachste Weg, sich in einem Dokument von Absatz zu Absatz zu bewegen, ist die ForEach-Schleife. Diese Art von Schleife durchläuft ALLE Absätze, einschließlich derer auf Vorgabe- und Referenzseiten, aber nicht unbedingt in der Reihenfolge, in der sie im Dokument vorkommen.

Loop ForEach(Pgf) In(ActiveDoc) LoopVar(vPgf)
    // ...Hier etwas ausführen...
EndLoop

Wenn Sie die Aktionen lediglich auf die Absätze einschränken möchten, die sich auf Standardseiten befinden, dann fügen Sie eine If-Schleife ein.

Loop ForEach(Pgf) In(ActiveDoc) LoopVar(vPgf)
    If (vPgf.Page.ObjectName = 'BodyPage')
        //...Hier etwas ausführen...
    EndIf
EndLoop

Die ForEach-Schleife ist in ihrer Funktion eingeschränkt, denn Sie können aus der Schleife heraus keine Absätze löschen. Wenn Sie dies tun, wird die Schleife verlassen, sobald der erste Absatz gelöscht wurde. Wenn Sie über das Skript Absätze löschen müssen, können Sie die »ausführliche« Version der ForEach-Schleife verwenden. Hier ist das Grundgerüst des Codes.

Set vPgf = ActiveDoc.FirstPgfInDoc;
Loop While(vPgf)
    // ...Hier etwas ausführen...
    Set vPgf = vPgf.NextPgfInDoc;
EndLoop

Wie bei der ForEach-Schleife werden auch hier alle Absätze des Dokuments durchlaufen. Hier nun der Code zum Löschen von Absätzen. In diesem Beispiel werden alle Absätze auf Referenzseiten gelöscht.

Set vPgf = ActiveDoc.FirstPgfInDoc;
Loop While(vPgf)
    Set vNextPgf = vPgf.NextPgfInDoc;
    If (vPgf.Page.ObjectName = 'RefPage')
        Delete Object(vPgf)
    EndIf
    Set vPgf = vNextPgf;
EndLoop

In vielen Situationen, zum Beispiel bei der Erstellung eines Inhaltsverzeichnisses für ein Kapitel, müssen Sie die Absätze in der Reihenfolge verarbeiten, in der sie im Dokument vorkommen. Dies erreichen Sie, indem Sie beim Durchlaufen der Absätze dem Dokumentfluss folgen. Und so geht es:

Set vFlow = ActiveDoc.MainFlowInDoc;
Set vPgf = vFlow.FirstTextFrameInFlow.FirstPgf;
Loop While(vPgf)
    // ...Hier etwas ausführen...
    Set vPgf = vPgf.NextPgfInFlow;
EndLoop

Da es keine FirstPgfInFlow-Eigenschaft gibt, müssen Sie zunächst den ersten Textrahmen im Dokumentfluss finden und dann zum ersten Absatz im Textrahmen wechseln. Von dort aus können Sie über die NextPgfInFlow-Eigenschaft von Absatz zu Absatz wechseln.

Eine Einschränkung bei diesem Ansatz besteht darin, dass nur Absätze im Hauptdokumentfluss verarbeitet werden. Absätze in Tabellen werden übersprungen. Der nächste Abschnitt befasst sich mit der Navigation durch Tabellenabsätze.

Tabellenabsätze

Die Navigation durch Tabellenabsätze besteht darin, von Zelle zu Zelle zu springen und dabei in jeder Zelle von Absatz zu Absatz zu wechseln. Der folgende Code funktioniert mit einer ausgewählten Tabelle.

Set vTbl = SelectedTbl;
Set vCell = vTbl.FirstRowInTbl.FirstCellInRow;
Loop While(vCell)
    Set vCellPgf = vCell.FirstPgf;
    Loop While(vCellPgf)
        //...Hier etwas ausführen...
        Set vCellPgf = vCellPgf.NextPgfInFlow;
    EndLoop
    Set vCell = vCell.NextCellInTbl;
EndLoop

Der oben stehende Code verarbeitet jede einzelne Zelle der Tabelle. Der Tabellentitel, falls vorhanden, wird jedoch übersprungen. Die folgende Variante des oben stehenden Skripts prüft, ob ein Tabellentitel vorhanden ist, und verarbeitet auch dessen Absatz (oder Absätze), falls ein Titel vorhanden ist. Der neue Code ist markiert.

Set vTbl = SelectedTbl;
If vTbl.FirstPgf // **
    Set vCellPgf = vTbl.FirstPgf // **
    Loop While(vCellPgf) // **
        // ...Hier etwas ausführen...
        Set vCellPgf = vCellPgf.NextPgfInFlow; // **
    EndLoop // **
EndIf // **
Set vCell = vTbl.FirstRowInTbl.FirstCellInRow;
Loop While(vCell)
    Set vCellPgf = vCell.FirstPgf;
    Loop While(vCellPgf)
        //...Hier etwas ausführen...
        Set vCellPgf = vCellPgf.NextPgfInFlow;
    EndLoop
    Set vCell = vCell.NextCellInTbl;
EndLoop

Vielleicht möchten Sie beim Navigieren durch die Tabelle bestimmte Reihen überspringen, zum Beispiel Kopf- und Fußteil. Das folgende Skript verarbeitet nur die Standardreihen der Tabelle.

Set vTbl = SelectedTbl;
Set vRow = vTbl.FirstRowInTbl;
Loop While(vRow)
    // Reihentyp prüfen.
    If vRow.RowType = RowBody
        Set vCell = vRow.FirstCellInRow;
        Loop While(vCell)
            Set vCellPgf = vCell.FirstPgf;
            Loop While(vCellPgf)
                //...Hier etwas ausführen...
                Set vCellPgf = vCellPgf.NextPgfInFlow;
            EndLoop
            Set vCell = vCell.NextCellInRow;
        EndLoop
    EndIf
    Set vRow = vRow.NextRowInTbl;
EndLoop

Sie sehen, dass es sich hierbei um eine Schleife innerhalb einer anderen Schleife handelt. Die äußere Schleife wechselt von Reihe zu Reihe, während die innere Schleife in jeder Reihe von Zelle zu Zelle wechselt. Dadurch erhalten Sie die Möglichkeit, den Reihentyp zu prüfen, bevor Sie die innere Schleife aufrufen.

Kombinieren des Codes

Nun wissen Sie, wie Sie durch die Absätze im Textfluss und durch die Absätze in einer Tabelle navigieren, also können Sie die beiden Methoden kombinieren, um durch alle Absätze in derselben Reihenfolge zu navigieren, wie sie im Dokument vorkommen. Der Schlüssel hierfür ist der Get TextList-Befehl, mit dem Sie nach bestimmten Textelementen in einem Textobjekt suchen können. Textelemente sind Tabellen, verankerte Rahmen, Querverweise, Variable usw., Textobjekte sind Absätze, Textflüsse und Textzeilen.

In Ihrem Skript möchten Sie in jedem Absatz prüfen, ob eine oder mehrere Tabellen enthalten sind. Hier die allgemeine Syntax des Get TextList-Befehls:

Get TextList InObject(vPgf) NewVar(vTlist) TblAnchor;

Falls das Textobjekt (vPgf) Tabellen enthält, ist vTlist eine Liste der Tabellen. Mit einer Schleife lesen Sie jedes Element der Textliste ein. Wenn keine Tabellen im Absatz vorhanden sind, wird die Schleife übersprungen.

Loop While (x <= vTlist.Count) LoopVar(x) InitVal(1) Incr(1)
    Get Member Number(x) From(vTlist) NewVar(vTblAnchor);
    Set vTbl = vTblAnchor.TextData;
    //...Hier etwas mit der Tabelle ausführen...
EndLoop

Ein Textelement besitzt drei Eigenschaften: TextData ist das zugehörige Objekt des Elements, TextOffset ist der Abstand des Elements vom Anfang des Textobjekts und TextType ist der Typ des Textelements, in diesem Fall TblAnchor. Da Sie nach dem Tabellenobjekt suchen, verwenden Sie

Set vTbl = vTblAnchor.TextData;

An der Stelle, an der es in oben stehendem Skript heißt »...Hier etwas mit der Tabelle ausführen...«, fügen Sie den Code ein, mit dem Sie durch die Tabellenabsätze navigieren. Unten finden Sie den vollständigen Code für die Navigation durch sämtliche Absätze im Haupttextfluss, einschließlich Tabellenabsätze.

// Aktualisiert: Neue Konvention für Variablenbezeichner!
Local lvFlow lvPgf lvTList lvX lvTblAnchor lvTbl lvCellPgf lvCell;

Set lvFlow = ActiveDoc.MainFlowInDoc;
// Ersten Absatz im Fluss finden.
Set lvPgf = lvFlow.FirstTextFrameInFlow.FirstPgf;
// Schleife durch die Absätze starten.
Loop While(lvPgf)
    //...Hier etwas ausführen...
    // Nun auf Tabellen im Absatz prüfen.
    Get TextList InObject(lvPgf) NewVar(lvTlist) TblAnchor;
    // Wenn Tabelle vorhanden, wird diese Schleife aufgerufen.
    Loop While (lvX <= lvTlist.Count) LoopVar(lvX) InitVal(1) Incr(1)
        Get Member Number(lvX) From(lvTlist) NewVar(lvTblAnchor);
        Set lvTbl = lvTblAnchor.TextData;
        // Auf Tabellentitel prüfen.
        If (lvTbl.FirstPgf)
            Set lvCellPgf = lvTbl.FirstPgf
            // Schleife durch die Absätze des Tabellentitels starten.
            Loop While(lvCellPgf)
                //...Hier etwas ausführen...
                Set lvCellPgf = lvCellPgf.NextPgfInFlow;
            EndLoop
        EndIf
        // Zur ersten Zelle der Tabelle wechseln.
        Set lvCell = lvTbl.FirstRowInTbl.FirstCellInRow;
        // Von Zelle zu Zelle wechseln.
        Loop While(lvCell)
            Set lvCellPgf = lvCell.FirstPgf;
            // Jeden Absatz der Zelle durchlaufen.
            Loop While(lvCellPgf)
                //...Hier etwas ausführen...
                Set lvCellPgf = lvCellPgf.NextPgfInFlow;
            EndLoop
            Set lvCell = lvCell.NextCellInTbl;
        EndLoop
    EndLoop
    Set lvPgf = lvPgf.NextPgfInFlow;
EndLoop

Kommentare? Bitte gleich hier eintragen…

Mai 2008, Michael Müller-Hillebrand