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
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.
...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
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.
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
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?
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.
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.
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 Kai Rübsamen'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
/*
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
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
Kai Rübsamen wrote:
4. Delete the object
app.activeDocument.textFrames
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?
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
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
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
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
Copy link to clipboard
Copied
Ahh it's me being too generous
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 .
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
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.
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
}
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?
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.
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();
}
}
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!
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();
}
}
Copy link to clipboard
Copied
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
textFrames
x++;
c--;
}
}
}else{
for(c=0;c<textFrames.length;c++){
if(Math.round(textFrames
textFrames
x++;
c--;
}
}
}alert(x + " Items have been removed.");
}