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

Script that can delete objects by coordinates

Explorer ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

I have a long document and I need to remove some text frames that appear on every page. Those frames share the same y coordinate and some others that share the same x coordinate. Is there a script that can locate those text frames and delete them throughout the document?

I'm on Windows so no applescript

TOPICS
Scripting

Views

2.9K

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

correct answers 1 Correct answer

Enthusiast , Sep 09, 2016 Sep 09, 2016

Now to the second part:

If you have your current text frame, you can read the geometric Bounds. Since you want to find only frames with specific x or y coordinates, you need only y1 and x1. And since the values could have a lot of decimals, it is a good idea to round the values, as Peter mentioned.

Bildschirmfoto 2016-09-09 um 10.56.39.png

var curDoc = app.activeDocument;

var allTextFrames = curDoc.textFrames;

var yValue = 11.5;

var xValue = 20;

var nTextFrames = allTextFrames.length-1;

for (var i = nTextFrames; i >= 0; i--) {

  var curTextFram

...

Votes

Translate

Translate
Advisor ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

Most likely you won't find a out-of-the-box solution, but it is a very simple script that you can try and build by yourself.

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
Enthusiast ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

Hi Dimitra,

here is the idea. If you have any problems with the script, you will surely get help

1. Collect all textframes in you document

2. Loop backwards through all your textframes

3. Compare the x OR y coordinates of the current object with your specified value

3 a. If you have no result, the values should maybe rounded before comparison

4. Delete the object

best

Kai

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 ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

Kai Rübsamen wrote:

2. Loop backwards through all your textframes

I have wrote a script for this but my script doesn't loop backwards.. what is the reason for looping backwards rather than just looping in order of the textFrames?

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
Enthusiast ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

In this case there is no particular reason! Both will work. If I remove or duplicate things, I do it always backwards.

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
Explorer ,
Sep 07, 2016 Sep 07, 2016

Copy link to clipboard

Copied

Would you be so kind as to share the script you wrote? I am a beginner and have difficulty on how to go about 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
Engaged ,
Sep 07, 2016 Sep 07, 2016

Copy link to clipboard

Copied

I will not provide my script just yet. Since you imply that you are trying to learn to script I will explain how to go about this process following 's steps above steps above:

Kai Rübsamen wrote:

1. Collect all textframes in you document

app.activeDocument.textFrames; // This will tell InDesign to find all text frames within the active document.

Kai Rübsamen wrote:

2. Loop backwards through all your textframes

for(c=app.activeDocument.textFrames.length - 1; c < 0; c--){

     /*

     script to be looped will go withing the for loop braces: "{}".

     the for loop says that c is equal to the number of text frames within the active document minus 1.

     the second part of the for loop says to loop as long as c is greater than 0.

     and the final part of the script says to take one away from c after each loop.

     */

}

Kai Rübsamen wrote:

3. Compare the x OR y coordinates of the current object with your specified value

if(app.activeDocument.textFrames.geometricBounds[0] == VALUE){

     /*

     the IF() line tests if the y axis is a certain value; where "VALUE" is replaced with the desired y value to remove text frames.

     To test the x axis use app.activeDocument.textFrames.geometricBounds[1].

     any script within the IF() braces "{}" will only be executed if the condition is true.

     The IF() function should be placed within the FOR() loop braces "{}"

     */

}

Kai Rübsamen wrote:

3 a. If you have no result, the values should maybe rounded before comparison

//to round a number you will need to use the round function:

eg -- Math.round(app.activeDocument.textFrames.geometricBounds[0] / .125) * .125 //Will round the y axis to the nearest 1/8 unit

Kai Rübsamen wrote:

4. Delete the object

app.activeDocument.textFrames.remove(); // Will remove the text frame.. should be placed within the IF() function braces"{}".

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
Explorer ,
Sep 08, 2016 Sep 08, 2016

Copy link to clipboard

Copied

app.activeDocument.textFrames;

for(c=app.activeDocument.textFrames.length - 1; c < 0; c--){

if(app.activeDocument.textFrames.geometricBounds[0] == -11,5){

Math.round(app.activeDocument.textFrames.geometricBounds[0] / .125)

app.activeDocument.textFrames.remove();

}

}

Does this look right? It doesn't seem to do anything... Does it matter that the document is a book with facing pages?

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
People's Champ ,
Sep 08, 2016 Sep 08, 2016

Copy link to clipboard

Copied

Yeah you did it ! Now we can start really helping you

app.activeDocument.textFrames; is a reference that you will recall later so you may want to store into a variable:

var doc = app.activeDocument;

var myTextFrames = doc.textFrames;

When you do loop, it's always a good habit not to check the "array" length every round. So you may want to store it inside another variable:

var n = myTextFrames.length - 1 ; //-1 if decremental loop

When you build a loop, the direction (incrementtal or decremental impact how you build the loop.

In your case you try to loop backward but the exit condition states that the loop as to go through as long as the length is lesser than 0 which is not from the beginning. So your loop never runs actually.

When you go backwards, your exit condition is that your index is greater or equals 0;

for ( i = n; i>=0 ; i-- ) {

myTextFrames //reference to the text frame of rank i

}

Now geometricBounds is an array of four reals as you saw. If you are expecting a very same position, you could store the array and compare to the geometric bounds of the object:

for ( i = n; i>=0 ; i-- ) {

     if ( myTextFrames.geometricBounds == [0,0,10, 100] )  myTextFrames.remove();

}

but chances are high that an user might have moved things a little so the comparison might not work. So and that will be your very last step, it's generally better to define a virtual surrounding box (i.e. an array of 4 reals) that is bigger than teh box dimension. Then you can check if the geometricbounds stand inside that virtual box giving you a bit of margin. Then you can safely remove the object.

Keep up the good work. You have done the toughest part…start coding

Loic

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
Guide ,
Sep 08, 2016 Sep 08, 2016

Copy link to clipboard

Copied

Hi Loic,

Just a note. You can't compare arrays using code like [1,2,3,4]==[1,2,3,4] (result is false) unless you have prototyped the '==' operator.

This can be done this way:

Array.prototype['=='] = function(a){ return this.toSource() == a.toSource() };

@+

Marc

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
People's Champ ,
Sep 08, 2016 Sep 08, 2016

Copy link to clipboard

Copied

Hi @Marc,

Oh ok, I guess I never got into that pitfall because I never had to do such comparisons but it's interesting to know

Plus, your code will be a perfect snippet to put aside for further use.

Given the lack of experienceof our friend, let's offer her another form of comparison

var a = [1,2,3,4];

var b = [1,2,3,4];

if ( a[0]==b[0]

&& a[1]==b[1]

&& a[2]==b[2]

&& a[3]==b[3] ) { alert("a & b equal); }

Loic

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
Enthusiast ,
Sep 08, 2016 Sep 08, 2016

Copy link to clipboard

Copied

Loic, the question is, how to find x- and y-positions, not to compare the whole bounds 😉

Besides the wrong loop, the op use a comma in his value, instead of a point, so 11,5 should bei 11.5

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
People's Champ ,
Sep 08, 2016 Sep 08, 2016

Copy link to clipboard

Copied

Ahh it's me being too generous

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
Explorer ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

app.activeDocument.textFrames;

var doc = app.activeDocument;

var myTextFrames = doc.textFrames;

var n = myTextFrames.length - 1 ; //-1 if decremental loop

for ( i = n; i>=0 ; i-- ) {

myTextFrames

}

for ( i = n; i>=0 ; i-- ) {

     if ( myTextFrames.geometricBounds == [170,-11.5,117,4.1] )  myTextFrames.remove();

}

Still doesn't work .

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 ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

Dimitra,

You check if the geometricBounds of your text frame are [170,-11.5,117,4.1]. But it's likely that the bounds are something different. Print the frame's g.bounds (select the frame and do $.writeln(app.selection[0].geometricBounds) and check the result. InDesign's measurements have 12 decimals, so what is displayed in the InDesign's panels as e.g. 170, might infact be 170.000000000001, and that's not the same as 170. So to check whether two frames are in the same position, you need to build in some allowance, e.g. by rounding the numbers or chopping off some decimals.

On a different note, lines 5-7 appear not to do anything, you might as well leave them out.

Peter

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
Enthusiast ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

O.k., so let’s go one step backwards!

The goal is to find textframes on a specific x or y position. So you need first: all text frames in your document. Since you cannot simply call textframes, you must call the containers as well. Als Loic said, it is always a good idea to store such things in a variable.

Bildschirmfoto 2016-09-09 um 10.41.59.png

var curDoc = app.activeDocument;

var allTextFrames = curDoc.textFrames;

While you can count your textframes, you can loop through every individual textframe with it’s index. And because you want to delete frames, it may a good idea to loop from the end. Since this so called index starts with '0' instead of '1', we need one loop less than the length of your textframes.

var nTextFrames = allTextFrames.length-1;

for (var i = nTextFrames; i >= 0; i--) {

    var curTextFrame = allTextFrames;

    // do something

}

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
Explorer ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

var curDoc = app.activeDocument; 

var allTextFrames = curDoc.textFrames; 

var n = myTextFrames.length - 1 ; //-1 if decremental loop

    var nTextFrames = allTextFrames.length-1; 

    for (var i = nTextFrames; i >= 0; i--) { 

        var curTextFrame = allTextFrames

       myTextFrames.remove(); // do something 

    } 

And where do I input the coordinates x, y in that code?

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
Enthusiast ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

Now to the second part:

If you have your current text frame, you can read the geometric Bounds. Since you want to find only frames with specific x or y coordinates, you need only y1 and x1. And since the values could have a lot of decimals, it is a good idea to round the values, as Peter mentioned.

Bildschirmfoto 2016-09-09 um 10.56.39.png

var curDoc = app.activeDocument;

var allTextFrames = curDoc.textFrames;

var yValue = 11.5;

var xValue = 20;

var nTextFrames = allTextFrames.length-1;

for (var i = nTextFrames; i >= 0; i--) {

  var curTextFrame = allTextFrames;

  var gB = curTextFrame.geometricBounds;

  var y1 = gB[0].toFixed(2);

  var x1 = gB[1].toFixed(2);

 

  if (y1 == yValue) {

    curTextFrame.remove();

  }

  if (x1 == xValue) {

    curTextFrame.remove();

  }

}

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
Explorer ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

!!! It finally works!!! I won't have to delete 1,4000 text frames by hand!!


I only managed to get it to work when I only use the x or only the y coordinate otherwise it removes all text boxes on the same y and all on the same x without them sharing both x&y but still, this works just fine.

var curDoc = app.activeDocument;

var allTextFrames = curDoc.textFrames;

var yValue = -11.5;

// var xValue = 170;

var nTextFrames = allTextFrames.length-1;

for (var i = nTextFrames; i >= 0; i--) {

var curTextFrame = allTextFrames;

var gB = curTextFrame.geometricBounds;

var y1 = gB[0].toFixed(2);

//  var x1 = gB[1].toFixed(2);

if (y1 == yValue) {

  curTextFrame.remove();

}

//  if (x1 == xValue) {

//  curTextFrame.remove();

//  }

}

Thank you all!

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
Enthusiast ,
Sep 09, 2016 Sep 09, 2016

Copy link to clipboard

Copied

Hopefully you understand, that a lot of people try to give you an entry to scripting .

I would assume, that this version, works with both cases?

var curDoc = app.activeDocument;

var allTextFrames = curDoc.textFrames;

var yValue = 11.5;

var xValue = 20;

var nTextFrames = allTextFrames.length-1;

var i, curTextFrame, gB, y1, x1;

for (i = nTextFrames; i >= 0; i--) {

  curTextFrame = allTextFrames;

  gB = curTextFrame.geometricBounds;

  y1 = gB[0].toFixed(2);

  x1 = gB[1].toFixed(2);

 

  if (y1 == yValue && x1 != xValue) {

    curTextFrame.remove();

  }

    else if (x1 == xValue && y1 != yValue) {

      curTextFrame.remove();

  }

}

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 ,
Sep 12, 2016 Sep 12, 2016

Copy link to clipboard

Copied

LATEST

Since you have a working script I will now provide my script. The main difference with the scripts here and mine is that my script uses a text frame selection for the x and y coordinates and also provides a simple dialog to choose whether to use the x or y axis. Obi-wan Kenobi​ has gotten me really into adding UIs.

/*

scripted by Skemicle

4:05 PM 9/6/2016

*/

if(parseFloat(app.version) < 6){

    dialog();

}else{

    app.doScript(dialog, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Delete Cooresponding Text Frames");

}

function dialog(){

    if(app.selection.length != 1){

        alert("Please, select a single text frame and retry");

        exit();

    }else{

        with(new Window('dialog {orientation:"column", alignChildren:"right"}', "Delete Corresponding Text Frames")){

            add('staticText', undefined, "Delete textFrames that share the same:")

            with(add('group {orientation:"row"}')){

                var ycoord = add('radiobutton {value:true, text:"Y Coordinate"}');

                add('radiobutton {value:false, text:"X Coordinate"}');

            }with(add('group')){

                add('button', undefined, "OK");

                add('button', undefined, "Cancel");

            }if(show() != 1){

                exit();

            }else{

                main(ycoord);

            }

        }

    }

}

function main(ycoord){

    var x=0;

    var doc = app.activeDocument;

    var sel = app.selection[0];

    var selgb0 = Math.round(sel.geometricBounds[0] / .0125) * .0125;

    var selgb1 = Math.round(sel.geometricBounds[1] / .0125) * .0125;

    var textFrames = doc.textFrames;

    if(ycoord.value == true){

        for(c=0;c<textFrames.length;c++){

            if(Math.round(textFrames.geometricBounds[0] / .0125) * .0125 == selgb0){

                textFrames.remove();

                x++;

                c--;

            }

        }

    }else{

        for(c=0;c<textFrames.length;c++){

            if(Math.round(textFrames.geometricBounds[1] / .0125) * .0125 == selgb1){

                textFrames.remove();

                x++;

                c--;

            }

        }

    }alert(x + " Items have been removed.");

}

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