• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

ESTK - Adding a blank page at the end of the document

Engaged ,
Oct 28, 2024 Oct 28, 2024

Copy link to clipboard

Copied

For previous documents, there was a requirement for the document to end with Page X/(Y Blank).
 
I have a script that @Russ Ward helped me with to accomplish this. The script:
  • Goes through Pages 2 to the end of the document and removes any custom master pages.
  • Checks the last page of the document and determines if it is odd or even. If it is odd, it applies an X/Y Blank Master page and updates the page numbers in the footer.
 
The script works fine, but I have a new requirement to add a blank page after the X/Y Blank page. (A totally blank page, not an empty page with the header, footer, and page number.)
 
So I need two things added to the script:
 
  • If the doc ends on an odd page, I need to add the blank page. To do that, I thought I needed to add a paragraph at the end of the document, have it start that on an right-hand page, and set the page background to none. I added this code, but it doesn't seem to be working (doc is previously defined as app.ActiveDoc):

 

		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.

 

  • At the start of the script, I need to check for and remove empty paragraphs at the end of the document (From times the script was previously run). I'm not sure how to do this. I have a function that checks for disconnected flow pages, but this is not a disconnected flow page, nor technically an empty page - it has a paragraph on it, just no text in the paragraph.

 

Thanks in advance!

TOPICS
Scripting

Views

409

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

Copy link to clipboard

Copied

Thanks - Nicely done - reviewing and working on it now!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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 ...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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 ...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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 ...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

Copy link to clipboard

Copied

Delete is a method, so you need to do this:

pgf2.Delete ();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

Copy link to clipboard

Copied

Thanks, but I'm still getting the same error with pgf2.Delete();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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;
    }
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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;
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

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).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

Copy link to clipboard

Copied

The script is working with two kludges:

  • Basically, if I add a blank page, the script is adding two blank pages, so I just added a couple of lines to delete the next to the last page. Ugly, but it works.
  • The script is only deleting the last blank paragraph - which normally there would either be one or zero, so it works, but if there were 5 blank paragraphs at the end, I would prefer for it to delete all of them...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

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 ...

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

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 ...

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 28, 2024 Oct 28, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 28, 2024 Oct 28, 2024

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 ...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Dec 09, 2024 Dec 09, 2024

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).

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Dec 09, 2024 Dec 09, 2024

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines