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
|