image
   

FrameScript Tutorials

 
 

Navigating Paragraphs

Being able to navigate paragraphs in FrameMaker documents is an essential FrameScript task. This tutorial will explore several methods. For background information, see the Loops and Lists tutorial.

Paragraph Loops

The simplest way to move from paragraph to paragraph in a document is a ForEach loop. This kind of loop moves through ALL of the pargraphs, including those on master and reference pages, but not necessarily in document order.

Loop ForEach(Pgf) In(ActiveDoc) LoopVar(vPgf)
  ...Do something here...
EndLoop

If you want to restrict your actions to paragraphs on body pages, add an If test inside the loop.

Loop ForEach(Pgf) In(ActiveDoc) LoopVar(vPgf)
  If vPgf.Page.ObjectName = 'BodyPage'
    ...Do something here...
  EndIf
EndLoop

The ForEach loop is limited in that it does not allow you to delete any paragraphs within the loop. If you do, the loop will exit right after the first paragraph is deleted. If your script needs to delete paragraphs, you can use the “long-hand” form of the ForEach loop. Here is the basic code.

Set vPgf = ActiveDoc.FirstPgfInDoc;
Loop While(vPgf)
  ...Do something here...
  Set vPgf = vPgf.NextPgfInDoc;
EndLoop

Like the ForEach loop, this one touches all of the paragraphs in the document. Here is the code to delete paragraphs; in this example, all of the paragraphs on reference pages are deleted.

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 many situations, for example creating a chapter table of contents, you will need to process the paragraphs in document order. The way to do this is to move through the paragraphs in the main document flow. Here is how it is done.

Set vFlow = ActiveDoc.MainFlowInDoc;
Set vPgf = vFlow.FirstPgfInFlow;
Loop While(vPgf)
  ...Do something here...
  Set vPgf = vPgf.NextPgfInFlow;
EndLoop

You start with the main flow in the document and get the first paragraph in the flow. From there you can use the NextPgfInFlow property to move from paragraph to paragraph.

One limitation to this approach is that only paragraphs in the main document flow are processed. Paragraphs in tables are skipped. The next section discusses navigating through table paragraphs.

Table Paragraphs

Navigating table paragraphs is a process of moving from cell to cell, and while in each cell, moving from paragraph to paragraph. The following code works with a selected table.

Set vTbl = SelectedTbl;
Set vCell = vTbl.FirstRowInTbl.FirstCellInRow;
Loop While(vCell)
  Set vCellPgf = vCell.FirstPgf;
  Loop While(vCellPgf)
    ...Do something here...
    Set vCellPgf = vCellPgf.NextPgfInFlow;
  EndLoop
  Set vCell = vCell.NextCellInTbl;
EndLoop

The above code processes every single cell in the table, however it skips the table title if it exists. Here is a modification to the above script that will test for a table title and include its paragraph (or paragraphs) if it exists. The new code is shown in red.

Set vTbl = SelectedTbl;
If vTbl.FirstPgf
  Set vCellPgf = vTbl.FirstPgf
  Loop While(vCellPgf)
    ...Do something here...
    Set vCellPgf = vCellPgf.NextPgfInFlow;
  EndLoop
EndIf
Set vCell = vTbl.FirstRowInTbl.FirstCellInRow;
Loop While(vCell)
  Set vCellPgf = vCell.FirstPgf;
  Loop While(vCellPgf)
    ...Do something here...
    Set vCellPgf = vCellPgf.NextPgfInFlow;
  EndLoop
  Set vCell = vCell.NextCellInTbl;
EndLoop

You may want to skip certain rows as you navigate the table, for example heading and footing rows. Here is a script that only processes body rows.

Set vTbl = SelectedTbl;
Set vRow = vTbl.FirstRowInTbl;
Loop While(vRow)
  // Test for row type.
  If vRow.RowType = RowBody
    Set vCell = vRow.FirstCellInRow;
    Loop While(vCell)
      Set vCellPgf = vCell.FirstPgf;
      Loop While(vCellPgf)
        ...Do something here...
        Set vCellPgf = vCellPgf.NextPgfInFlow;
      EndLoop
      Set vCell = vCell.NextCellInRow;
    EndLoop
  EndIf
  Set vRow = vRow.NextRowInTbl;
EndLoop

As you can see, this is a loop within a loop. The outer loop moves from row-to-row, while the inner loop moves from cell-to-cell for each row. This gives you a chance to test for the row type before entering the inner loop.

Combining the Code

Now that you know how to navigate the paragraphs in the text flow and paragraphs in a table, you can combine the methods to navigate all the paragraphs in document order. The key is the Get TextList command, which lets you search for certain text items within a text object. Text items include tables, anchored frames, cross-references, variables, etc., while text objects are paragraphs, text flows, and text lines.

In our script, we want to look for one or more tables in each paragraph. Here is the basic syntax for the Get TextList command.

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

If there are any tables in the text object (vPgf), vTlist will be a list of the tables. You will use a loop to get each member of the text list. If there are no tables in the paragraph, the loop will be skipped.

Loop While (x <= vTlist.Count) LoopVar(x) Init(1) Incr(1)
  Get Member Number(x) From(vTlist) NewVar(vTblAnchor);
  Set vTbl = vTblAnchor.TextData;
  ...Do something with the table here...
EndLoop

A text item has three properties: TextData is the object of the item; TextOffset is the offset of the item from the beginning of the text object; and TextType is the type of text item, in this case, TblAnchor. Since we are looking for the table object, we use

Set vTbl = vTblAnchor.TextData;

Where the script above says “...Do something here...” is where we insert the code to navigate through the table paragraphs. Below is the entire code for navigating all of the paragraphs in the main text flow in order, including tables paragraphs.

Set vFlow = ActiveDoc.MainFlowInDoc;
// Find the first paragraph in the flow.
Set vPgf = vFlow.FirstPgfInFlow;
// Loop through the paragraphs.
Loop While(vPgf)
  ...Do something here...
  // Now test for tables in the paragraph.
  Get TextList InObject(vPgf) NewVar(vTlist) TblAnchor;
  // If there are one or more tables, this loop will be entered.
  Loop While (x <= vTlist.Count) LoopVar(x) Init(1) Incr(1)
    Get Member Number(x) From(vTlist) NewVar(vTblAnchor);
    Set vTbl = vTblAnchor.TextData;
    // Test for a table title.
    If vTbl.FirstPgf
      Set vCellPgf = vTbl.FirstPgf
      // Loop through table title paragraphs.
      Loop While(vCellPgf)
        ...Do something here...
        Set vCellPgf = vCellPgf.NextPgfInFlow;
      EndLoop
    EndIf
    // Go to the first cell in the table.
    Set vCell = vTbl.FirstRowInTbl.FirstCellInRow;
    // Move from cell-to-cell.
    Loop While(vCell)
      Set vCellPgf = vCell.FirstPgf;
      // Loop through each paragraph in the cell.
      Loop While(vCellPgf)
        ...Do something here...
        Set vCellPgf = vCellPgf.NextPgfInFlow;
      EndLoop
      Set vCell = vCell.NextCellInTbl;
    EndLoop
  EndLoop
  Set vPgf = vPgf.NextPgfInFlow;
EndLoop