Copy link to clipboard
Copied
Hi all
I need a script to delete all empty graphics frames inside all tables of a multi page document.
The following script deletes text frames in the document but does not delete them if they are inside a table.
var myGraphicFrames = app.activeDocument.rectangles;
for (i=myGraphicFrames.length-1; i>=0; i--) {
if (myGraphicFrames.graphics.length < 1)
myGraphicFrames.remove();
}
Anyone know how to rewrite this script so that it deletes graphic frames from within all tables as well?
I'm a total beginner at scripting so any help would be much appreciated.
Cheers
Mike
Copy link to clipboard
Copied
Something like below should work, you need to iterate all the tables in the document and then each cell of all these tables
var myGraphicFrames = app.activeDocument.stories.everyItem().tables.everyItem().cells.everyItem().pageItems
for (i = 0; i < myGraphicFrames.length; i++)
{
if (myGraphicFrames.graphics.length == 0)
myGraphicFrames.remove();
}
-Manan
Copy link to clipboard
Copied
I just noticed that the code i gave would not work on inner tables i.e. tables within a table cell and so forth. But that can be added to it, you just need to check each cell to check for tables within it and then the process repeats itself to iterate each cell. A recursive algorithm fits the bill in this case.
-Manan
Copy link to clipboard
Copied
In fact it's probably simpler to get a handle on all graphics, and delete those that are in a table:
g = app.documents[0].allGraphics;
for (i = g.length-1; i >= 0; i--) {
if (g.parent.parent.parent instanceof Cell) {
g.parent.remove();
}
}
Peter
Copy link to clipboard
Copied
Hi Peter,
I think, only empty graphic frames in tables should be removed.
All with graphics inside should stay.
Regards,
Uwe
Copy link to clipboard
Copied
Ah, thanks Uwe, hadn't spotted that. Anyway, a bit more work but not much:
r = app.documents[0].allPageItems;
for (i = r.length-1; i >= 0; i--) {
if (r instanceof Rectangle && r.parent.parent instanceof Cell && r.graphics.length == 0) {
r.remove();
}
}
P.
Copy link to clipboard
Copied
Hi Peter,
tested your code.
Did a try/catch around the if clause so it could run through my sample document without error message.
Even then:
It will fail on group items that are empty.
It will remove graphic frames where graphic frames with images are pasted in.
And of course there could be Polygons or Ovals as well.
Before:
After:
Just trying to write my own code that would
1. Also remove the empty frames in the anchored group of cell 1 in the nested table.
2. Not remove the frame with the pasted in graphic of cell 2 of the nested table.
EDIT:
3. Also removes the empty graphic frame in the graphic cell of the nested table.
Just spotted that.
Currently I have success with item 1. and item 3.
Still looking for a straight way to get around item 2.
Regards,
Uwe
Copy link to clipboard
Copied
https://forums.adobe.com/people/Manan+Joshi wrote
I just noticed that the code i gave would not work on inner tables i.e. tables within a table cell and so forth. But that can be added to it, you just need to check each cell to check for tables within it and then the process repeats itself to iterate each cell. A recursive algorithm fits the bill in this case.
-Manan
Hi Manan,
check the allPageItems array of a cell. That would include also nested tables with their cells and inserted page items.
Something like the code below would work.
Warning! It's not perfect!
It would also remove graphic frames where graphic frames with images are pasted inside!
( function()
{
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
app.doScript
(
removeEmptyFramesInTablesOfDoc,
ScriptLanguage.JAVASCRIPT,
[],
UndoModes.ENTIRE_SCRIPT,
"Remove Empty Frames in Tables of Document | SCRIPT"
);
function removeEmptyFramesInTablesOfDoc()
{
var doc = app.documents[0];
var cellsArray = doc.stories.everyItem().tables.everyItem().cells.everyItem().getElements();
var cellsArrayLength = cellsArray.length;
var resultsArray = [];
var e;
for( var n=0;n<cellsArrayLength;n++ )
{
// allPageItems would include also nested contents, like page items in tables nested in tables:
var allItems = cellsArray
.allPageItems; var allItemsLength = allItems.length;
for( var a=0; a<allItemsLength; a++ )
{
// Perhaps also exlude other objects as well like Button, MultiStateObject …
if( allItems.constructor.name == "Group" ){ continue };
if( !allItems.hasOwnProperty("graphics") ){ continue };
if( allItems.graphics.length == 0)
{
resultsArray[resultsArray.length++] = allItems;
};
}
};
for( var n=0; n<resultsArray.length; n++ )
{
// resultsArray
.fillColor = "Magenta"; try{ resultsArray
.remove() }catch(e){ /* $.writeln( n +"\t"+ e.message ) */}; };
};
}() )
Before:
After:
The pasted in graphic is still a problem!!
The parent frame should not be removed.
Regards,
Uwe
Copy link to clipboard
Copied
Ah. Found a solution and changed the for loop where I remove the object to that:
for( var n=0; n<resultsArray.length; n++ )
{
// Test for allGraphics array of individual object:
if( resultsArray
.allGraphics.length > 0 ){ continue }; try{ resultsArray
.remove() }catch(e){ /* $.writeln( n +"\t"+ e.message ) */}; };
Regards,
Uwe
Copy link to clipboard
Copied
Interesting, different approaches.
To find empty graphic frames of any embedded depth, keep testing its parent's constructor until it's Cell or Document. If it's Document the page item is not in a cell. Pasted graphics aren't deleted, by the way.
function inCell (frame) {
var p = frame.parent;
while (!(p instanceof Document || p instanceof Cell)) {
p = p.parent;
}
return p instanceof Cell;
}
r = app.documents[0].allPageItems;
for (i = r.length-1; i >= 0; i--) {
if (r.hasOwnProperty('graphics') && inCell (r) && r.graphics.length == 0) {
r.remove();
}
}
Because of JavaScript's short-circuit evaluation, you can speed up the script (any script) by rearranging the three coordinated tests. (Short-circuit evaluation means that if the first test fails, following tests aren't done.) If very few page items are in cells, then it makes sense first to test whether any page item is in a cell: if a frame is not in a cell, the two other tests are done. And if very few frames are empty, then first test whether any frame has a graphic.
P.
Copy link to clipboard
Copied
Hi Peter,
I would add a fourth condition just at the start of the if condition:
if ( r.isValid && r.hasOwnProperty('graphics') && inCell (r) && r.graphics.length == 0 )
{
r.remove();
}
With nested structures it could be that a item does not exist anymore because the parent item was already removed.
Tested that with my sample and it was necessary to avoid an error message.
Regards,
Uwe
Copy link to clipboard
Copied
Sure. Always a wise precaution.
P.