Copy link to clipboard
Copied
var pgf = doc.FirstPgfInDoc;
while (pgf.ObjectValid()) {
pgf = pgf.NextPgfInDoc;
}
// Add New Paragraph
var pgf2 = doc.NewSeriesObject(Constants.FO_Pgf, pgf);
pgf = doc.LastPgfInDoc;
var props = pgf2.GetProps();
pgf2.SetProps(props);
pgf2.Start = Constants.FV_PGF_TOP_OF_RIGHT_PAGE;
var bodyPage = doc.LastBodyPageInDoc;
bodyPage.PageBackground = Constants.FV_BGD_NONE;
There is an anchored frame at the end of the document with "THE END" inside it, so I need the last paragraph in Flow A - which might be why my script doesn't seem to be working.
Thanks in advance!
Copy link to clipboard
Copied
The script isn't working because this code
var pgf = doc.FirstPgfInDoc;
while (pgf.ObjectValid()) {
pgf = pgf.NextPgfInDoc;
}
processes all of the paragraphs in the document, including those on master and reference pages (and in table cells). And the paragraph list is not necessarily in document order. Here is the first video in a series of 4 (they are short):
https://youtu.be/-kkiVfOi2zs?si=wyi-UVOwQjW0UnuY
Copy link to clipboard
Copied
Thanks - Nicely done - reviewing and working on it now!
Copy link to clipboard
Copied
Okay - I probably made a typo somewhere ...
If it's not okay to post YOUR code here, let me know:
main();
// FrameExpert - https://www.youtube.com/watch?v=-kkiVfOi2zs
// will not find paragraphs in tables
function main(){
var doc;
doc=app.ActiveDoc;
if (doc.ObjectValid() === 1) {
processDoc(doc);
}
}
function processDoc(doc){
var pgf
// Turn off document display to speed the script and prevent flicker.
if (app.Displaying ===1) {
app.Displaying ===1;
}
// Loop through the paragraphs in the document's main flow.
pgf = doc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
while (pgf.ObjectValid() === 1){
text = getPgfText(pgf);
Console (text);
pgf=pgf.NextPgfInFlow;
}
// Restore the document display and refresh the screen.
if (app.Displaying === 0) {
app.Displaying = 1;
doc.Redisplay();
}
}
function getPgfText(pgf){
var text, textList, count, i;
textList = pgf.GetText (Constants.FTI_String);
count = textList.length;
for (i = 0; i < count; i += 1) {
text += (textList[i].sdata);
}
alert(text);
return text;
}
When I run the code, in the console, I just get "Result: undefined", but in the alert statement that I added before the end, I get "Undefined.Main1", "Undefined.Main2", etc ...
Copy link to clipboard
Copied
var text, textList, count, i;
text = "";
. . .
text += (textList[i].sdata);
You have to initialize the text variable to an empty string before the loop because it is initially undefined.
Copy link to clipboard
Copied
Okay, it is finding the last paragraph text. One thing to help others: The script outputs to the Console in the main FrameMaker window. That is NOT the same thing and the script does NOT output to the Javascript Console in the ESTK editor ...
Copy link to clipboard
Copied
I would suggest that you don't nest the functions inside each other. It makes it harder to reuse the code. All of the functions should be on the same level in the script. The only time I nest a function is when the inner function is a "helper" to the outer function and wouldn't be useful on its own. For example, when I have a function that creates a dialog box, I will have "initialize" and "validate" functions nested because they are not useful outside of the dialog function.
Copy link to clipboard
Copied
I'm out of practice on Scripting, and I'm slow on the uptake today, but I'm not seeing where I am nesting functions inside each other.
The script above was basically from your video.
I modified it to try to add the blank page at the end of the document, but it isn't working (It runs, but nothing seems to happen). I have the following code. GetLastParagraph is the same as your ProcessDoc and getPgfText is not used (here):
main();
function main(){
var doc;
doc=app.ActiveDoc;
if (doc.ObjectValid() === 1) {
AddLastBlankPage(doc);
}
}
function AddLastBlankPage(doc){
pgf = GetLastParagraph(doc)
// Add New Paragraph
pgf2 = doc.NewSeriesObject(Constants.FO_Pgf, pgf);
var props = pgf2.GetProps();
pgf2.SetProps(props);
pgf2.Start = Constants.FV_PGF_TOP_OF_RIGHT_PAGE;
var bodyPage = doc.LastBodyPageInDoc;
bodyPage.PageBackground = Constants.FV_BGD_NONE;
} // End AddLastBlankPage
function GetLastParagraph(doc){
var pgf
// Turn off document display to speed the script and prevent flicker.
if (app.Displaying ===1) {
app.Displaying ===1;
}
// Loop through the paragraphs in the document's main flow.
pgf = doc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
while (pgf.ObjectValid() === 1){
// text = getPgfText(pgf, doc);
// Console (text);
pgf=pgf.NextPgfInFlow;
}
// Restore the document display and refresh the screen.
if (app.Displaying === 0) {
app.Displaying = 1;
doc.Redisplay();
}
return pgf;
} // End GetLastParagraph
// alert(text);
function getPgfText(pgf){
var text, textList, count, i;
textList = pgf.GetText (Constants.FTI_String);
text = "";
count = textList.length;
for (i = 0; i < count; i += 1) {
text += (textList[i].sdata);
}
return text;
}
for the new paragraph, I also tried:
doc.NewSeriesObject(Constants.FO_Pgf, pgf);
and
var pgf2 = doc.NewSeriesObject(Constants.FO_Pgf, pgf);
and neither worked ...
Copy link to clipboard
Copied
Might as well mention here, the second part of the script - where I want to delete empty paragraphs at the end of the document isn't working either. For that I have:
function DeleteBlankParagraphs(doc){
pgf = GetLastParagraph(doc)
while (getPgfText (pgf)===''){
var pgf2;
pgf2 = pgf;
pgf=pgf.PreviousPgfInFlow
pgf2.delete
}
} // End DeleteBlankParagraphs
It may be deleting the very last paragraph, but it gets stuck on the second pass through the while loop in DeleteBlankParagraphs when it goes to getPgfText and it says Undefined is not an object for the textList = line.
Copy link to clipboard
Copied
Delete is a method, so you need to do this:
pgf2.Delete ();
Copy link to clipboard
Copied
Thanks, but I'm still getting the same error with pgf2.Delete();
Copy link to clipboard
Copied
You probably want something like this:
function DeleteBlankParagraphs(doc){
var pgf, pgf2;
// Get the last paragraph in the main flow.
pgf = GetLastParagraph(doc);
// Loop backwards through the empty paragraphs.
while (pgf.ObjectValid () === 1) {
pgf2 = pgf.PrevPgfInFlow;
// If the paragraph is empty, delete it.
if (getPgfText (pgf) === "") {
pgf.Delete ();
}
else { // Otherwise, exit the loop.
break;
}
pgf = pgf2;
}
}
Copy link to clipboard
Copied
Thank you, but that didn't work either. However, I stepped through the code and it didn't do anything at the while (pgf.ObjectValid===1), which tells me that "GetLastParagraph(doc){} didn't work, although all that is is Process Doc from your example, modifed to return "pgf".
(Which is probably why the AddBlankPage script is also failing).
Copy link to clipboard
Copied
GetLastParagaph doesn't work because you loop through all of the paragraphs, including the last. So you are returning a non-valid object.
Copy link to clipboard
Copied
Makes sense - how would I fix it? I'm thinking something like
Until (pgf.ObjectValid()===0){
but I don't know if ESTK supports that.
I have to leave now, but I'll check back tomorrow.
Copy link to clipboard
Copied
In your loop, test when you are at your last paragraph and return it.
if (pgf.NextPgfInFlow.ObjectValid () === 0) {
return pgf;
}
Copy link to clipboard
Copied
Making Progress!!!
GetLastParagraph is working. Had to add more than you said, but you gave me the critical line:
function GetLastParagraph(doc){
var pgf
// Turn off document display to speed the script and prevent flicker.
if (app.Displaying ===1) {
app.Displaying ===1;
}
// Loop through the paragraphs in the document's main flow.
pgf = doc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
while (pgf.ObjectValid() === 1){
// text = getPgfText(pgf, doc);
// Console (text);
if (pgf.NextPgfInFlow.ObjectValid()===0){
// Restore the document display and refresh the screen.
if (app.Displaying === 0) {
app.Displaying = 1;
doc.Redisplay();
}
return pgf;
}
else{
pgf=pgf.NextPgfInFlow;
}
}
} // End GetLastParagraph
As a result AddLastBlankPage now works.
Spoke too soon. If I use a simple 4 paragraph file like your video was showing, AddLastBlankPage now works. In a real (test) document, if the document is 13 pages, I should end up with Page 13/(14 Blank) with a totally blank page following. I'm ending up with Page 13/(14 Blank), followed by a blank LHP 14 with header and footer, followed by a blank Page 15. I'm trying to step through the code and figure out why, but FM is not responding ... EDIT2: I think I could delete the LHP 14 through script and have what I want, but it's sloppy.
DeleteBlankParagraphs is NOT working. It deletes the very last paragraph and then quits. That tells me that pgf2=pgf.PrevPgfInFlow; is proably giving an invalid result, but I don't know why.
(In reality, we shouldn't have any blank paragraphs at the end of the document - other than maybe the one to add the blank page), but I still want to remove all of them.
(I could loop through running GetLastParagraph each time, but that's a long loop).
Copy link to clipboard
Copied
I'm ending up with Page 13/(14 Blank), followed by a blank LHP 14 with header and footer, followed by a blank Page 15.
Updated - the script you provided and that I posted above is working correctly, when I integrate it with my previous script, I get the error above.
Copy link to clipboard
Copied
The script is working with two kludges:
Copy link to clipboard
Copied
Fixed - I had pgf = pfg.PreviousPgfInFlow, not pgf = pgf.PrevPgfInFlow.
Can't delete replies. I had this incorrect earlier in the script, but it is correct in the function that is failing ...
Copy link to clipboard
Copied
Very inefficient, but this works:
function DeleteBlankParagraphs(doc){
var pgf;
// Get the last paragraph in the main flow.
pgf = GetLastParagraph(doc);
// Loop backwards through the empty paragraphs.
while (pgf.ObjectValid () === 1) {
// If the paragraph is empty, delete it.
if (getPgfText (pgf) === "") {
pgf.Delete ();
}
else { // Otherwise, exit the loop.
break;
}
pgf = GetLastParagraph(doc);
}
}
UPDATE: 9-Dec-2024. A bit late, but the code above isn't THAT inefficent. It could be shortened to just:
function DeleteBlankParagraphs_Works(doc){
var pgf;
// Get the last paragraph in the main flow.
pgf = GetLastParagraph(doc);
// Loop backwards through the empty paragraphs.
while (pgf.ObjectValid () === 1) {
// If the paragraph is empty, delete it.
if (getPgfText (pgf) === "") {
pgf.Delete ();
}
else { // Otherwise, exit the loop.
break;
}
}
}
I could be wrong, but the way it seems to be working to me is that when you delete the last paragraph, you are automatically moved to the previous paragraph, so the script continues running through the loop. I think it might run into problems if you had a table-anchor or an anchored frame in the last paragraph, but then it wouldn't be a blank paragraph, so ...
Copy link to clipboard
Copied
You are right about the nesting. The way the script was indented, it looked like you were nesting the functions. I am sorry about that.
Copy link to clipboard
Copied
No problem. The indentations can be confusing. I usually clean them up when I'm finished, but I was trying to get the scripts working first - which they still are not ...
Copy link to clipboard
Copied
Ran into a new issue. The script I have checks for the current page number variable in a masterpage footer and updates the text. It works fine if the page number is in the first paragraph in the footer.
It finds the first paragraph from:
var doc = app.ActiveDoc;
var lastMasterPage = doc.GetNamedMasterPage('Right');
frame = leftMasterPage.PageFrame.FirstGraphicInFrame;
pgf = frame.FirstPgf;
I have an issue where the page number is in the second paragraph of the footer. @frameexpert posted above how to loop through the main elements of the flow (excluding master and reference pages).
How can I loop through the paragraphs in the text frame?
pgf=pgf.NextPgfinFlow and pgf=pgf.NextPgfinDoc both fail with pgf=undefined, and I don't see a pgf.NextPgfinFrame command?
Thanks in advance!!!
UPDATE: Crude, but I solved this. The page number will always be in the last paragraph in the footer. So I can use pgf=frame.LastPgf; and it works. I'd like to scroll through the pagragraphs in the footer, but I don't need to do so.
I still need solutions for copying conditional formatting and pasting it and for handling more than one variable in the footer (or starting with the last variable in the paragraph).
Copy link to clipboard
Copied
While I'm here, I have another issue also.
The orignial script found the page number in the text frame and changed it to X/(X-1 Blank). IOW, if the last page was 17, it changed the footer to "17/(18 Blank)".
We might have a chapternumber as text - so the page number might be "8-17". I modified the script so that it will change the page number to "8-17/(8-18 Blank)"
However, If I have conditional formatting - i.e. ConditionA = "8-" and ConditionB = "9-" The scritpt removes the conditionalization so I get "...-17(8-9-18 Blank)" without conditionalization.
How would I copy the conditionalized text to a variable so that I can paste it.