Има два вида кръстосани препратки във FrameMaker: точкови кръстосани препратки и параграфни кръстосани препратки. (Има и трети вид, елементни кръстосани препратки, достъпни само във FrameMaker+SGML. Този урок няма да обсъжда елементните кръстосани препратки.) И параграфните, и точковите кръстосани препратки са подобни по това, че трябва да вмъкнете Xref обект, който сочи към Cross-Ref Marker. Xref обектът има свойство XRefSrcText, което трябва да съответства точно на текста на маркера на Cross-Ref Marker. Нека започнем с точковите кръстосани препратки, тъй като те са малко по-прости за работа.
Точкови кръстосани препратки
Като пример, ето една таблица, която съдържа имената на процедурите за поддръжка, появяващи се в документ. Искаме да използваме FrameScript, за да направим кръстосани препратки от записите в таблицата към действителните процедури в документа. Всяко заглавие на процедура използва формат на параграф Heading2.
Добавяне на маркери за кръстосани препратки
Един принцип, който ни се иска да добавим тук при решаване на проблеми с FrameScript, е да разбиваме проблема на малки задачи. Нашата първа задача е да поставим маркери за кръстосани препратки във всеки заглавен параграф на процедура. Тъй като знаем, че процедурите започват с параграфи Heading2, ще поставим маркери само в тези параграфи. Текстът на маркера ще бъде настроен на текста на параграфа. Важно е всеки маркер за кръстосана препратка в документа да съдържа уникален текст. Ще приемем в нашия пример, че всеки параграф Heading2 съдържа текст, уникален за всички други параграфи Heading2 в документа.
// Test for an active document.
If ActiveDoc = 0
MsgBox 'No active document. ';
LeaveSub;
Else
Set vCurrentDoc = ActiveDoc;
EndIf
Loop ForEach(Pgf) In(vCurrentDoc) LoopVar(vPgf)
If vPgf.Name = 'Heading2'
New Marker NewVar(vMarker) MarkerName('Cross-Ref')
TextLoc(vPgf);
// Set the marker text to the paragraph text.
Set vMarker.MarkerText = vPgf.Text;
EndIf
EndLoop
Всеки параграф Heading2 ще има маркер за кръстосана препратка в началото си с текста на параграфа като текст на маркера. Ето един от параграфите Heading2 с прозореца на маркера, показващ текста на маркера.
Тъй като създаваме маркери с FrameScript, вместо чрез интерфейса на FrameMaker, нека погледнем свойствата на маркера. Можете да изпълните следния код с избран маркер anchor, за да видите свойствата на маркера. Обърнете внимание, че свойството MarkerText е текстът, който се показва в диалоговия прозорец Marker.
Get TextList InRange(TextSelection) MarkerAnchor
NewVar(vTextList);
If vTextList.Count > 0
Get Member Number(1) From(vTextList) NewVar(vMarker);
Set vMarker = vMarker.TextData;
Display vMarker.Properties;
Else
MsgBox 'There is no marker selected. ';
EndIf
Добавяне на кръстосаните препратки
Сега можем да отидем в таблицата и да имаме скрипт, който добавя кръстосани препратки към маркерите („spots“), които вмъкнахме по-рано. Ще приемем, че курсорът е в таблицата, когато се изпълнява следният код.
// Test for an active document.
If ActiveDoc = 0
MsgBox 'There is no active document. ';
LeaveSub;
Else
Set vCurrentDoc = ActiveDoc;
EndIf
// Set a variable for the current table.
Set vTbl = vCurrentDoc.SelectedTbl;
// Make sure a the cursor is in a table.
If vTbl.ObjectName not= 'Tbl'
MsgBox 'There is no selected table. ';
LeaveSub; // Exit the script.
EndIf
// Find the first body row in the table.
Set vRow = vTbl.FirstRowInTbl;
Loop While(vRow.RowType = RowHeading)
Set vRow = vRow.NextRowInTbl;
EndLoop
// Go to the first cell in the first body row.
Set vCell = vRow.FirstCellInRow;
Сега, когато сме в първата клетка, можем да започнем цикъл през клетките. За всяка клетка трябва да „изберем“ текста, така че новата кръстосана препратка да може да го замени. Свойството XRefSrcText на XRef (кръстосана препратка) ще бъде настроено на избрания текст, тъй като това ще съответства на текста на маркера на съответния маркер за кръстосана препратка, който е вмъкнат по-рано. За да изберем текста, ще направим текстов обхват, ще изтрием текста и след това ще вмъкнем XRef обекта на негово място.
// Begin the loop.
Loop While(vCell)
// Select the text by making a TextRange.
New TextRange NewVar(vTextRange) Object(vCell.FirstPgf)
Offset(0) Offset(ObjEndOffset-1);
// Set a variable for the TextRange text.
Set vXRefSrcText = vTextRange.Text;
// Delete the text.
Delete Text TextRange(vTextRange);
// Insert the cross-reference.
New XRef Format('Heading & Page') TextLoc(vCell.FirstPgf)
NewVar(vXRef);
Set vXRef.XRefSrcText = vXRefSrcText;
// Go to the next cell and repeat the loop.
Set vCell = vCell.CellBelowInCol;
EndLoop
// Update the cross-references.
Update DocObject(vCurrentDoc) XRefs Everything;
Таблицата сега показва оригиналния текст, заменен с кръстосаните препратки. Ако кликнете два пъти върху една от кръстосаните препратки, ще се отвори диалоговият прозорец Cross-Reference, както е показано по-долу.
Основното, което трябва да запомните, е, че свойството XRef.XRefSrcText трябва да съответства точно на свойството XRef.MarkerText на съответния маркер, в противен случай ще имате неразрешена кръстосана препратка. За да видите свойствата на кръстосаната препратка, маркирайте една от кръстосаните препратки и изпълнете следния код. Обърнете внимание на свойството XRefSrcText.
Get TextList InRange(TextSelection) XRefBegin
NewVar(vTextList);
If vTextList.Count > 0
Get Member Number(1) From(vTextList) NewVar(XRefBegin);
Set XRefBegin = XRefBegin.TextData;
Display XRefBegin.Properties;
Else
MsgBox 'There is no cross-reference selected. ';
EndIf
Кръстосани препратки към други документи
Едно друго важно свойство, което трябва да се отбележи, е свойството XRefFile. За горната кръстосана препратка то е NULL низ, тъй като е вътрешна кръстосана препратка. Ако препращахме към друг файл, тогава свойството XRefFile ще съдържа абсолютния път до другия файл.
Параграфни кръстосани препратки
Преди да обсъдим вмъкването на параграфни кръстосани препратки с FrameScript, нека прегледаме как те се различават от точковите кръстосани препратки в интерфейса на FrameMaker. Когато вмъквате точкова кръстосана препратка с FrameMaker, трябва да вмъкнете маркер за кръстосана препратка, преди да вмъкнете кръстосаната препратка. Трябва да направите „точка“, която ще се появи в диалоговия прозорец Cross-Reference.
За разлика от това, параграфните кръстосани препратки не изискват вмъкване на маркер за кръстосана препратка предварително. Вместо това посочвате желания параграф в диалоговия прозорец Cross-Reference, кликвате върху Insert и FrameMaker вмъква кръстосаната препратка и маркера за кръстосана препратка на подходящите места.
След като бъдат вмъкнати, точковите и параграфните кръстосани препратки не се различават в основните си свойства. Всички кръстосани препратки се достъпват като XRef обекти от FrameScript. Има разлика обаче в начина, по който те се представят в диалоговия прозорец Cross-Reference на FrameMaker. Когато кликнете два пъти върху точкова кръстосана препратка, диалогът показва Cross-Ref маркери под Source Type и текста на маркера в дясно разположения списък. Двойно кликване върху параграфна кръстосана препратка показва Paragraph Tag на изходния параграф под Source Type и текста на параграфа за всеки от избраните Paragraph Tag параграфи в дясно разположения списък. По-долу е диалоговият прозорец Cross-Reference, показващ параграфна кръстосана препратка.
Разликата между типовете кръстосани препратки идва от разликата в синтаксиса на маркерите за кръстосани препратки. За да видите това, вмъкнете параграфна кръстосана препратка, Control-Alt-Click върху кръстосаната препратка, за да отидете до източника, и отворете прозореца на маркера. Ще видите синтаксиса на маркера, който FrameMaker вмъква с параграфна кръстосана препратка. По-долу е примерен прозорец на маркер, последван от свойствата на XRef.
Подобно на маркерите за точкови кръстосани препратки, които вмъкнахме по-рано, можете да видите текста на изходния параграф в прозореца на маркера и свойството XRefSrcText. Освен това текстът на параграфа се предшества от петцифрен номер (последван от двоеточие и интервал) и името на формата на параграф на изходния параграф (последвано от двоеточие и интервал). Именно тези два допълнителни компонента в свойството XRefSrcText на XRef карат FrameMaker да „вижда“ това като параграфна кръстосана препратка.
Поддържане на cross-ref маркерите уникални
Има и друга причина за различния синтаксис между параграфните и точковите кръстосани препратки. От съществено значение е Cross-Ref маркерите в документ да са уникални. Въпреки че можете да имате повече от една кръстосана препратка, сочеща към един Cross-Ref маркер, не можете да имате единична кръстосана препратка, опитваща се да сочи към повече от един маркер със същия текст на маркера. Когато вмъквате точкови кръстосани препратки, от вас зависи да се уверите, че всеки Cross-Ref маркер е уникален. Когато вмъквате параграфни кръстосани препратки, FrameMaker се грижи маркерите, които вмъква, да са уникални, използвайки специалния синтаксис, по-специално петцифрения сериен номер отпред.
Текстът на cross-ref маркерите никога не трябва да се променя след вмъкването на маркерите. Може да имате няколко кръстосани препратки, сочещи към един и същи маркер; ако промените текста на маркера, кръстосаните препратки ще станат неразрешени. По подобен начин, промяната на текста на изходния параграф няма да промени текста на маркера.
Преди да напишем някакъв код за вмъкване на параграфни кръстосани препратки, ето важните моменти, които трябва да запомните за параграфните и точковите кръстосани препратки.
Добавяне на параграфни кръстосани препратки
Ще използваме същия пример, който използвахме с точковите кръстосани препратки, освен че този път ще вмъкнем кръстосаните препратки и съответстващия им маркер едновременно. В предишния ни пример първо вмъкнахме всички маркери и след това кръстосаните препратки. Предположихме, че за всеки запис в таблицата ще има точно съответстващ параграф Heading2 в документа. Това не винаги може да е безопасно предположение и може да доведе до неразрешени кръстосани препратки.
Ще започнем с нашия цикъл през таблицата. Целият списък с код е по-долу.
// Test for an active document.
If ActiveDoc = 0
MsgBox 'There is no active document. ';
LeaveSub;
Else
Set vCurrentDoc = ActiveDoc;
EndIf
// Set a variable for the current table.
Set vTbl = vCurrentDoc.SelectedTbl;
// Make sure a the cursor is in a table.
If vTbl.ObjectName not= 'Tbl'
MsgBox 'There is no selected table. ';
LeaveSub; // Exit the script.
EndIf
// Make a property list for the color red.
Get Object Type(Color) Name('Red') DocObject(vCurrentDoc)
NewVar(vColor);
New PropertyList NewVar(vProps) Color(vColor);
// Find the first body row in the table.
Set vRow = vTbl.FirstRowInTbl;
Loop While(vRow.RowType = RowHeading)
Set vRow = vRow.NextRowInTbl;
EndLoop
// Go to the first cell in the first body row.
Set vCell = vRow.FirstCellInRow;
// Begin the loop.
Loop While(vCell)
// Select the text by making a TextRange.
New TextRange NewVar(vTextRange) Object(vCell.FirstPgf)
Offset(0) Offset(ObjEndOffset-1);
// Set a variable for the TextRange text.
Set vXRefSrcText = vTextRange.Text;
// Run a subroutine to find the corresponding
heading.
Set vHeadingFound = 0;
Run FindSourceHeading Returns vMarkerText(vXRefSrcText);
If vHeadingFound = 1
// Delete the text.
Delete Text TextRange(vTextRange);
// Insert the cross-reference.
New XRef Format('Heading & Page') TextLoc(vCell.FirstPgf)
NewVar(vXRef);
Set vXRef.XRefSrcText = vXRefSrcText;
Else
// If the corresponding heading can't be found, color the
// text red so it stands out.
Apply TextProperties TextRange(vTextRange)
Properties(vProps);
EndIf
// Go to the next cell and repeat the loop.
Set vCell = vCell.CellBelowInCol;
EndLoop
// Update the cross-references.
Update DocObject(vCurrentDoc) XRefs Everything;
За всеки запис в таблицата ще изпълним подпрограма, наречена FindSourceHeading, която се опитва да намери съответстващото заглавие в документа. Ако не намери съответстващо заглавие със същия текст, тя ще приложи цвета червен към текста в клетката на таблицата, така че лесно да можете да знаете, че има проблем. Ето списъка с код за подпрограмата.
Sub FindSourceHeading
//
Loop ForEach(Pgf) In(vCurrentDoc) LoopVar(vPgf)
If vPgf.Name = 'Heading2'
// See if the paragraph text is the same as the table
// cell text.
If vPgf.Text = vXRefSrcText
// Make marker text with paragraph cross-ref syntax.
// Get the unique Id of the paragraph and convert it to
// a string.
New String NewVar(vMarkerText) Value(vPgf.Unique);
// Drop the first character so we end up with 5 digits.
Get String FromString(vMarkerText) NewVar(vMarkerText)
StartPos(vMarkerText.Size - 4);
// Add the paragraph tag and text.
Set vMarkerText = vMarkerText + ': ' + vPgf.Name + ': ' +
vPgf.Text;
// Add the cross-reference marker.
New Marker NewVar(vMarker) MarkerName('Cross-Ref')
TextLoc(vPgf);
// Set the marker text to the paragraph text.
Set vMarker.MarkerText = vMarkerText;
// Set the vHeadingFound variable to 1.
Set vHeadingFound = 1;
// Leave the subroutine.
LeaveSub;
EndIf
EndIf
EndLoop
//
EndSub
Обърнете внимание, че този код е подобен на по-ранния скрипт, който вмъкваше маркерите за точкови кръстосани препратки. Това е прост цикъл през параграфите на документа, търсещ параграфи Heading2. Той има допълнителен тест, за да види дали текстът на параграфа съответства на текста на клетката на таблицата.