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

Square area percent of page report

New Here ,
Feb 25, 2010 Feb 25, 2010

Copy link to clipboard

Copied

Sure this is not the first time someone has looked for a way to do this, but I can't find a solution.

Script to find the square inch area of the each object in the whole document > make a new layer > place a tag on each object stating that object's square area > also generate the percentage of that object's area compared to the page size.

I'm a novice and have hobbled together a few scripts that I've found but can't connect them up. So far I've adjusted a script to return geometric bounds of a selected object. And I modified another script that generates labels on a separate layer (the labels display various attributes of each object, color space, name, link etc).

It seems that inserting my get geometric bounds script should be inserted into the labels script with the parts concerning object attributes but I can't see how (again major Novice).

Haven't figured out how to get the document bounds (though that seems fairly obvious) and how to translate my geometric bounds into inches and find the % of page. I did find an almost perfect script (at the bottom) but it is for Illustrator and doesn't work off the same structure.

My code below. Anything from a point in the right direction to a rewrite would be amazing! Though I really want to understand how so I can contribute, teaching myself but practical applications is not always the best place to learn.

Script #1: Code for geometric bounds (where can I insert this into script #2 to apply square inches and % of page to picture/text labels)

Object.prototype.height = function() {   var bds = this.geometricBounds;

//not using visible bounds, can't see how that would help here but maybe I'm wrong   return [ b[3]-b[1] , b[2]-b[0] ]; }

Script #2: Code for labels (need to convert area from points to inches and find % of page)

var myScriptVer = "2.1"; var myInfoTitle = "Image Info"; var myInfoColor = [0,15,100,0]; var yPos = 100; var xPos = 100;

//getting document length and measurements but not sure that is passing anywhere if(app.documents.length != 0){      var myDocument = app.activeDocument;      var myOrgDocHUnits = myDocument.viewPreferences.horizontalMeasurementUnits;      var myOrgDocVUnits = myDocument.viewPreferences.verticalMeasurementUnits;      var myOrgDocOrigin = myDocument.viewPreferences.rulerOrigin;      myDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.millimeters;      myDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.millimeters;      myDocument.viewPreferences.rulerOrigin = RulerOrigin.spreadOrigin;      var myLinks = myDocument.links;      if(myLinks.length != 0){           var myDialog = app.dialogs.add({name:"Contact Sheet Labels"+ myScriptVer});           with(myDialog){                with(dialogColumns.add()){                     with (dialogRows.add()){                          with(borderPanels.add()){                               with(dialogColumns.add()){                                    with (dialogRows.add()){                                         staticTexts.add({staticLabel:"Loose Proof Label Displays:"});                                    }                                    with(borderPanels.add()){                                         with(dialogColumns.add()){                                              with (dialogRows.add()){                                              staticTexts.add({staticLabel:"Link Info:\t"});                                              }                                         }                                         with(dialogColumns.add()){                                              with (dialogRows.add()){                                                   var myNameOpt = checkboxControls.add({staticLabel:"File Name\t", checkedState:true});                                              }                                              with (dialogRows.add()){                                                   var myPathOpt = checkboxControls.add({staticLabel:"File Path", checkedState:true});                                              }                                         }                                         with(dialogColumns.add()){                                              with (dialogRows.add()){                                                   var myTypeOpt = checkboxControls.add({staticLabel:"File Type\t\t", checkedState:false});                                              }                                              with (dialogRows.add()){                                                   var myStatusOpt = checkboxControls.add({staticLabel:"Link Status", checkedState:false});                                              }                                         }                                    }                                    with(borderPanels.add()){                                         with(dialogColumns.add()){                                              with (dialogRows.add()){                                              staticTexts.add({staticLabel:"Image Info:\t"});                                              }                                         }                                         with(dialogColumns.add()){                                              with (dialogRows.add()){                                                   var myActResOpt = checkboxControls.add({staticLabel:"Actual PPI\t", checkedState:true});                                              }                                              with (dialogRows.add()){                                                   var myEffResOpt = checkboxControls.add({staticLabel:"Effective PPI", checkedState:false});                                              }                                         }                                         with(dialogColumns.add()){                                              with (dialogRows.add()){                                                   var myScaleOpt = checkboxControls.add({staticLabel:"Scale Percentage\t", checkedState:false});                                              }                                              with (dialogRows.add()){                                                   var myColSpaceOpt = checkboxControls.add({staticLabel:"Color Space", checkedState:true});                                              }                                         }                                    }                               }                          }                     }                     with (dialogRows.add()){                          with(borderPanels.add()){                               with(dialogColumns.add()){                                    with (dialogRows.add()){                                         var myLabelOpt = checkboxControls.add({staticLabel:"Printable Labels", checkedState:true});                                    }                               }                          }                     }                     with (dialogRows.add()){                          staticTexts.add({staticLabel:"Contact Sheet Labels"});                     }                }           }           var myResult = myDialog.show({name:"SplitOptions"});           if(myResult == true){                //Clear previous layer, color, and styles                for(i = 0;i < myDocument.layers.length;i++){                     var myLayer = myDocument.layers;                     if(myLayer.name == myInfoTitle){                          myLayer.remove();                     }                }                for(i = 0;i < myDocument.colors.length;i++){                     var myColor = myDocument.colors;                     if(myColor.name == myInfoTitle){                          myColor.remove();                     }                }                               for(i = 0;i < myDocument.paragraphStyles.length;i++){                     var myPStyle = myDocument.paragraphStyles;                     if(myPStyle.name == myInfoTitle){                          myPStyle.remove();                     }                }                for(i = 0;i < myDocument.characterStyles.length;i++){                     var myCStyle = myDocument.characterStyles;                     if(myCStyle.name == myInfoTitle){                          myCStyle.remove();                     }                }                //Create the link info layer                var myLinkInfoLayer = myDocument.layers.add();                myLinkInfoLayer.name = myInfoTitle;                //Create the link info color                var myLinkInfoColor = myDocument.colors.add();                myLinkInfoColor.name = myInfoTitle;                myLinkInfoColor.colorValue = myInfoColor;                //Create the link info Character Style                var myLinkInfoCStyle = myDocument.characterStyles.add();                myLinkInfoCStyle.name = myInfoTitle;                try{                     myLinkInfoCStyle.fontStyle = "Semibold";                }                catch(e){}                //Create the link info Paragraph Style                var myLinkInfoPStyle = myDocument.paragraphStyles.add();                myLinkInfoPStyle.name = myInfoTitle;                try{                     myLinkInfoPStyle.paragraphDirection = ParagraphDirection.leftToRightDirection;                }                catch(e){}                myLinkInfoPStyle.justification = Justification.leftAlign;                try{                     myLinkInfoPStyle.appliedFont = "Myriad Pro";                     myLinkInfoPStyle.fontStyle = "Regular";                }                catch(e){}                myLinkInfoPStyle.pointSize = 6;                myLinkInfoPStyle.leading = 6;                myLinkInfoPStyle.appliedLanguage = "English: USA";                myLinkInfoPStyle.hyphenation = false;                myLinkInfoPStyle.leftIndent = "8mm";                myLinkInfoPStyle.firstLineIndent = "-8mm";                var myLink, myLinkPos, myLinkName, myLinkPath, myLinkType, myLinkStat, myLinkInfoStr, myLinkParent, myLinkSpread, myLinkStatus, myLinkInfoFrame;                                     for(l = 0;l < myLinks.length;l++){                     myLink = myLinks;                     var myD = myLink.linkXmp;                     if(myLink.parent.parent.itemLayer.visible == true){                          myLinkPos = myLink.parent.parent.geometricBounds;                          myLinkName = "";                          myLinkPath = "";                          myLinkType = "";                          myLinkStat = "";                          myLinkInfoStr = "";                                               myLinkParent = myLink.parent;                          do{                               if(myLinkParent.constructor.name != "Character"){                                    myLinkParent = myLinkParent.parent;                               }                               else{                                    if(app.version.split(".")[0] >= 4){                                         myLinkParent = myLinkParent.parentTextFrames[0];                                    }                                    else{                                         myLinkParent = myLinkParent.parentTextFrame;                                    }                                                        }                          }while((myLinkParent.constructor.name != "Spread")&&(myLinkParent.constructor.name != "MasterSpread"))                          if(myLinkParent.constructor.name == "Spread"){                               myLinkSpread = myDocument.spreads[myLinkParent.index];                          }                          else{                               myLinkSpread = myDocument.masterSpreads[myLinkParent.index];                          }                                               if(myNameOpt.checkedState){                               if((myPathOpt.checkedState == false) && (myTypeOpt.checkedState == false) && (myStatusOpt.checkedState == false)){                                    myLinkInfoStr = myLinkInfoStr + myLink.name;                               }                               else{                                    myLinkInfoStr = myLinkInfoStr + "Name:\t" + myLink.name;                               }                          }                          if(myPathOpt.checkedState){                               myLinkInfoStr = myLinkInfoStr + "\rPath:\t" + myLink.filePath;                          }                          if(myTypeOpt.checkedState){                               myLinkInfoStr = myLinkInfoStr + "\rType:\t" + myLink.linkType;                          }                          if(myStatusOpt.checkedState){                               myLinkStatus = "";                               switch(myLink.status){                                    case LinkStatus.normal:                                         myLinkStatus = "OK";                                         break;                                    case LinkStatus.linkOutOfDate:                                         myLinkStatus = "Modified";                                         break;                                    case LinkStatus.linkMissing:                                         myLinkStatus = "Missing";                                         break;                                    case LinkStatus.linkEmbedded:                                         myLinkStatus = "Embedded";                                         break;                                                   }                               myLinkInfoStr = myLinkInfoStr + "\rStatus:\t" + myLinkStatus;                          }                          if(myScaleOpt.checkedState){                               myLinkInfoStr = myLinkInfoStr + "\rScaling:\tX="+myLink.parent.horizontalScale+"%, Y=" + myLink.parent.verticalScale+"%";                          }                          try{                               if(myActResOpt.checkedState){                                    myLinkInfoStr = myLinkInfoStr + "\rAct.Res:\t" + myLink.parent.actualPpi[0]+" x "+myLink.parent.actualPpi[1]+" ppi";                               }                               if(myEffResOpt.checkedState){                                    myLinkInfoStr = myLinkInfoStr + "\rEffc.Res:\t" + myLink.parent.effectivePpi[0]+" x "+myLink.parent.effectivePpi[0]+" ppi";                               }                               if(myColSpaceOpt.checkedState){                                    myLinkInfoStr = myLinkInfoStr + "\rCol.Sp:\t" + myLink.parent.space;                               }                          }                          catch(e){}                                               myLinkInfoFrame = myLinkSpread.textFrames.add();                          myLinkInfoFrame.geometricBounds = [myLinkPos[0],myLinkPos[1],myLinkPos[0]+10,myLinkPos[1]+50];                          myLinkInfoFrame.textFramePreferences.insetSpacing = ["0.5mm","0.5mm","0.5mm","0.5mm"];                          myLinkInfoFrame.textFramePreferences.ignoreWrap = true;                          myLinkInfoFrame.fillColor = myInfoTitle;                          myLinkInfoFrame.fillTint = 15;                          myLinkInfoFrame.strokeColor = myInfoTitle;                          myLinkInfoFrame.strokeWeight = .5;                          if(myLabelOpt.checkedState){                               myLinkInfoFrame.nonprinting = false;                          }                          else{                               myLinkInfoFrame.nonprinting = true;                          }                          myLinkInfoFrame.contents = myLinkInfoStr;                          for(p = 0;p < myLinkInfoFrame.parentStory.paragraphs.length;p++){                               myLinkInfoFrame.parentStory.paragraphs

.appliedParagraphStyle = myInfoTitle;                               myLinkInfoFrame.parentStory.paragraphs

.words[0].appliedCharacterStyle = myInfoTitle;                          }                          myLinkInfoFrame.fit(FitOptions.frameToContent);                     }                }           }      }      myDocument.viewPreferences.horizontalMeasurementUnits = myOrgDocHUnits;      myDocument.viewPreferences.verticalMeasurementUnits = myOrgDocVUnits;      myDocument.viewPreferences.rulerOrigin = myOrgDocOrigin; }

Script #3: Code object area labels, but for Illustrator (basically what I want)

if ( app.documents.length > 0 && app.activeDocument.selection.length > 0 ) {      //Declare the variables.      var myDocument=app.activeDocument;      var pathRef=docRef.selection[0];      var pathRefArea=pathRef.area;      var myReturn="\r";      //Convert pathRefArea to other units of measure. Store them in a text variable named areaMessage.      var areaMessage="Square Points: "+Math.round(pathRefArea*100)/100+myReturn      +"Square Picas: "+(Math.round((pathRefArea/144)*100))/100+myReturn      +"Square Inches: "+(Math.round((pathRefArea/5184)*100))/100+myReturn      +"Square Millimeters: "+(Math.round((pathRefArea/8.037)*100))/100+myReturn      +"Square Centimeters: "+(Math.round((pathRefArea/803.520)*100))/100      //Display areaMessage in an alert.      alert (areaMessage);            //Create a textFrame and set its contents to areaMessage.      var areaLabel = docRef.textFrames.add();      areaLabel.contents = areaMessage;      for(i=0;i<areaLabel.paragraphs.length;i++){           areaLabel.paragraphs.justification=Justification.CENTER;      }            //Position areaLabel at the center of the selected path.      areaLabel.top = pathRef.top-pathRef.height/2+areaLabel.height/2;      areaLabel.left = pathRef.left+pathRef.width/2-areaLabel.width/2;      //Create a temporary textFrame named squarePoints to hold just the value of pathRef's area in square points.      var squarePoints = docRef.textFrames.add();      squarePoints.contents = Math.round(pathRefArea*100)/100;      //Deselect pathRef. Select squarePoints. Redraw. Cut squarePoints to the clipboard.      pathRef.selected=false;      squarePoints.selected=true;      redraw();      app.cut(); }

TOPICS
Scripting

Views

3.1K

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

Community Expert , Feb 26, 2010 Feb 26, 2010

You want to get that function out of the for-loop and place it separately, e.g. at the end of the script:

for (i = 0; i < all_objects.length; i++)
    {
    o_area = object_area (all_objects);
    createTextFrame(all_objects, o_area);
    }

// more script..

// maybe more script

function createTextFrame (forObject, value)
   {
   var frame;
   frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});
   frame.move (forObject.parent);
   frame.move ([forObject.geometricBoun

...

Votes

Translate

Translate
New Here ,
Feb 25, 2010 Feb 25, 2010

Copy link to clipboard

Copied

Follow up: Sorry tried to insert code in the box but obviously got it wrong. Here is the Illustrator code (didn't fit)

if ( app.documents.length > 0 && app.activeDocument.selection.length > 0 ) {      //Declare the variables.      var myDocument=app.activeDocument;      var pathRef=docRef.selection[0];      var pathRefArea=pathRef.area;      var myReturn="\r";      //Convert pathRefArea to other units of measure. Store them in a text variable named areaMessage.      var areaMessage="Square Points: "+Math.round(pathRefArea*100)/100+myReturn      +"Square Picas: "+(Math.round((pathRefArea/144)*100))/100+myReturn      +"Square Inches: "+(Math.round((pathRefArea/5184)*100))/100+myReturn      +"Square Millimeters: "+(Math.round((pathRefArea/8.037)*100))/100+myReturn      +"Square Centimeters: "+(Math.round((pathRefArea/803.520)*100))/100      //Display areaMessage in an alert.      alert (areaMessage);            //Create a textFrame and set its contents to areaMessage.      var areaLabel = docRef.textFrames.add();      areaLabel.contents = areaMessage;      for(i=0;i<areaLabel.paragraphs.length;i++){           areaLabel.paragraphs.justification=Justification.CENTER;      }            //Position areaLabel at the center of the selected path.      areaLabel.top = pathRef.top-pathRef.height/2+areaLabel.height/2;      areaLabel.left = pathRef.left+pathRef.width/2-areaLabel.width/2;      //Create a temporary textFrame named squarePoints to hold just the value of pathRef's area in square points.      var squarePoints = docRef.textFrames.add();      squarePoints.contents = Math.round(pathRefArea*100)/100;      //Deselect pathRef. Select squarePoints. Redraw. Cut squarePoints to the clipboard.      pathRef.selected=false;      squarePoints.selected=true;      redraw();      app.cut(); }

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 ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

You mentioned a layer -- it wasn't clear to me what you want with it.Combining bits of different scripts is always difficult. Better to start from scratch, rather than accommodating one part of a script to another. What I would do in your case is this:

- set your document to inches so that you don't need to do all those calculations (first store the current values, restore them later);

- calculate the page area;

- calculate the selected object's area;

- set the object's area (as a percentage of the page area) as the object's label.

This script does that with all page items in a document. It doesn't check any errors, so make sure all your work is saved.

// reference to the document
doc = app.documents[0];
// store the doc's view preferences
view_prefs = doc.viewPreferences.properties;
// set measurement units to inches
doc.viewPreferences.verticalMeasurementUnits = doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
// calculate page area
p_area = doc.documentPreferences.pageWidth * doc.documentPreferences.pageHeight;

// reference to the document's page items
all_objects = doc.pageItems.everyItem().getElements();
// process them in turn
for (i = 0; i < all_objects.length; i++)
    {
    // calculate an object's page area
    o_area = object_area (all_objects);
    // calculate its percentage of the page area
    pct = (o_area * 100) / p_area;
    // add this as a string to the object's label
    all_objects.label = String (pct);
    }

// restore the doc's view preferences
doc.viewPreferences.properties = view_prefs;

function object_area (obj)
    {
    var gb = obj.geometricBounds;
    var width = gb[3]-gb[1];
    var height = gb[2]-gb[0];
    return width * height
    }

You mentioned something about a layer, but it wasn't clear to me what you want with that.

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
Community Expert ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

> Code object area labels, but for Illustrator (basically what I want)

Is there no Illustrator scripting forum?

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
New Here ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

Maybe I wasn't clear

The question is about InDesign.

The Illustrator script is what I want for InDesign. Please read the whole post.

Thanks

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 ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

Read all, including that 500-line sample script? I think not. Oh, and you are the first one ever to request the relative size of an object, when compared to its page, in inches and on a new layer.

Rather than plough through that immensely long example and trying to fathom what's going on, I just read your question and wrote this. There are a couple of points you might want to find out more about, such as your 'height' prototype (you were about halfway there). Stuff like document page size can be found in the OMV Help, as well as in numerous samples in Adobe's own Scripting Guide.

There is no need to recalculate units between points and inches -- in InDesign, you get what you asked for, or rather, what you already have. So if your current document settings are set to inches, the values ID returns are also in inches.

(It gets complicated if you work in points and want to see results in inches, but ever so slightly: points to inches is divide by 72.)

Before I forget, here's a working script. Select an object on your page and run it to see that it works; read to see how it works

if (app.selection.length != 1) exit(0);

bounds = app.selection[0].geometricBounds;
width = bounds[3] - bounds[1];
height = bounds[2] - bounds[0];

object_area = width * height;

page_area = app.activeDocument.documentPreferences.pageWidth * app.activeDocument.documentPreferences.pageHeight;

try {
app.activeDocument.layers.add({name:"Hey, a new layer"});
} catch (_)
{
}
thatNewLayer = app.activeDocument.layers.item("Hey, a new layer");

frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});
frame.move (app.selection[0].parent);
frame.move ([app.selection[0].geometricBounds[1],app.selection[0].geometricBounds[0]]);
frame.contents = String(Math.round(object_area*10)/10)+" / "+String(Math.round((object_area*1000)/page_area)/10)+"%";

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
New Here ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

First off, thank you both! I realize it was a very long post, but I thought more info than less might be better

I have a few follow up questions so I can understand better what is going on.


As I read Peter's script it makes a lot of sense (thank you for the comments in the script). When I run it I think I see where I didn't explain well. The labels are supposed to be visual labels over each object. Maybe I'm TOTALLY missing the how it works but it seems that this is setting the object's label (as you said above) but not displaying that on a layer.

Jongware's script does display on a layer, but only for the selected item.

With both your advice and scripts (a much better starting point for me) I'm going to try to understand and write the exact solution I need.

I'll post my script, or attempt, along with a pic of the result in layout.

Thank you both so much for your help.

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
New Here ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

So I understand that Peter is putting the object area and the % of the area into a string called pct.

And that Jongware is writing the contents calculation inside the string.

So my first thought was to reference the string name in the frame contents (leaving out the stuff about new layer and frame creation)

all_objects = doc.pageItems.everyItem().getElements();
// process them in turn
for (i = 0; i < all_objects.length; i++)
    {
    // calculate an object's page area
    o_area = object_area (all_objects);
    // calculate its percentage of the page area
    pct = (o_area * 100) / p_area;
    // add this as a string to the object's label
    all_objects.label = String (pct);
    }

frame.contents = String(pct);

I'm obviously missing something here.

So next I tried leaving the string alone and just passing the object area into it. Complete try below. I understand that the function is defining object area and that the for loop should be getting the object area for all objects in the document. I get errors in the function though. Do I need to store the object area in a string within the loop and call to it later in frame contents, or is this missing the forest for the trees.

// reference to the document
doc = app.documents[0];
// store the doc's view preferences
view_prefs = doc.viewPreferences.properties;
// set measurement units to inches
doc.viewPreferences.verticalMeasurementUnits = doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
// calculate page area
p_area = doc.documentPreferences.pageWidth * doc.documentPreferences.pageHeight;


all_objects = doc.pageItems.everyItem().getElements();
for (i = 0; i < all_objects.length; i++);
    {
     object_area = object_area (all_objects);
     }

try {
app.activeDocument.layers.add({name:"Object Percent of Page"});
} catch (_)
{
}
thatNewLayer = app.activeDocument.layers.item("Object Percent of Page");
frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});
frame.move (app.selection[0].parent);
frame.move ([app.selection[0].geometricBounds[1],app.selection[0].geometricBounds[0]]);
frame.fillColor = [10,10,100,10];
frame.fillTint = 50;
frame.contents = String(Math.round(object_area*10)/10)+" / "+String(Math.round((object_area*1000)/p_area)/10)+"%";


function object_area (obj)
     {
     var gb = obj.geometricBounds;
     var width = gb[3]-gb[1];
     var height = gb[2]-gb[0];
     return width * height;
     }

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
New Here ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

Sorry, forgot to include the screen shot of the intended result. I guess to simplify Jongware's script

is perfect, I just want it to loop through all objects in the whole document (my attempt in above post).

Picture 1.png

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 ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

A couple of errors ...

object_area = object_area (all_objects)

object_area is a function but you get its value and assign it to .. a variable with the same name. Better to use Peter's example, and give the variable another name -- why not "o_area"?

The for.. loop gathers all data -> right. But then you end the for..loop (with the next } ) so you don't do anything with the value you got. See Peter's sample: in his loop, he calculates the area and then puts it into each object's label. It's at that point exactly where you want my stuff to kick in, and make a small text frame on top of the object with the area as its contents.

Similar to Peter's, let me show you how to write a function to create the new frame.

First off, the stuff to create a new layer is only needed once, so you can move these lines

try {
 app.activeDocument.layers.add({name:"Object Percent of Page"});
} catch (_)
{
}
thatNewLayer = app.activeDocument.layers.item("Object Percent of Page");

all the way to the top in your script. After asserting there is a layer called "Object Percent (etc.)", there is no need to try to re-create it for every next object. Since the variable 'thatNewLayer' gets declared outside all functions, it's therefore global, and can be used inside functions as well as outside.

For a description of the try..catch construction, google for "javascript try catch". (Suffice to say that if the first half fails, code in the next half will be called.)

So, you need a function that takes

1. a reference to an object, so the new frame can be created on top of it, and

2. a value to write in to that.

For functions, it's "best practice" to declare as much variables as possible locally, using the 'var' keyword, so they won't interfere with global variables with the same name. The rest is virtually unchanged -- app.selection[0], which acts on your current selected object, is replaced with the object that you'll have to feed it when calling.

Oh -- I see only one local variable is needed: "frame" is only used inside this function. All other variables are either the function arguments (forObject and value) or global ones declared earlier (thatNewLayer and p_area).

function createTextFrame (forObject, value)

{

     var frame;

     frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});

     frame.move (forObject.parent);

     frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);

     frame.fillColor = [10,10,100,10];

     frame.fillTint = 50;

     frame.contents = String(Math.round(value*10)/10)+" / "+String(Math.round((value*1000)/p_area)/10)+"%";

}

-- and you call the function right after calculating the object area, like this

createTextFrame(all_objects, o_area);

inside the loop.

Hope it helps!

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
New Here ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

Brilliant!

Thank you for taking the time to explain everything so detailed. I read it a few times to make sure that I understood. I knew better with placing the new layer in the loop, that was dumb of me.

This works perfectly.

// reference to the document
doc = app.documents[0];
// store the doc's view preferences
view_prefs = doc.viewPreferences.properties;
// set measurement units to inches
doc.viewPreferences.verticalMeasurementUnits = doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
// calculate page area
p_area = doc.documentPreferences.pageWidth * doc.documentPreferences.pageHeight;

//create new layer
try {
app.activeDocument.layers.add({name:"Object Percent of Page"});
}
catch (_)
{
}
thatNewLayer = app.activeDocument.layers.item("Object Percent of Page");

// reference to the document's page items
all_objects = doc.pageItems.everyItem().getElements();


// process them in turn
for (i = 0; i < all_objects.length; i++)
    {
    // calculate an object's page area
    o_area = object_area (all_objects);
     createTextFrame(all_objects, o_area);

     function createTextFrame (forObject, value)
               {
               var frame;
               frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});
               frame.move (forObject.parent);
               frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);
               //frame.fillColor = [10,10,100,10];
               //frame.fillTint = 50;
               frame.contents = String(Math.round(value*10)/10)+" / "+String(Math.round((value*1000)/p_area)/10)+"%";
               }
    }
// restore the doc's view preferences
doc.viewPreferences.properties = view_prefs;

function object_area (obj)
    {
    var gb = obj.geometricBounds;
    var width = gb[3]-gb[1];
    var height = gb[2]-gb[0];
    return width * height
    }

Two follow up questions so that I understand even more.

  1. The function object_area (obj) at the end of the deocument defines what object_area does earlier in the script. Why does this not get placed earlier, wouldn't the loop need this definition?
  2. My frame.fillColor is causing the error "expected swatch". While this isn't a critical need for the functionality of the script, it makes it easier to read the labels. I'm confused by this because this way worked before...so I'm going to try defining a swatch by name and go from there. Left it commented out in the script above.

Thanks again, you both have helped make a lot of smiles here today!

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
New Here ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

So I tried adding

//label fill color
var frameColor = [0,15,100,0];

To the top so it would be a global variable for each frame label. The tried calling it just above frame contents. But getting the error "expected swatch".

frame.fillColor = frameColor;
     frame.contents = String(Math.round(value*10)/10)+"squ IN: "+ String(Math.round((value*1000)/p_area)/10)+"% of Total Page";
     }

Should frameColor not be a Global variable?

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 ,
Feb 26, 2010 Feb 26, 2010

Copy link to clipboard

Copied

You want to get that function out of the for-loop and place it separately, e.g. at the end of the script:

for (i = 0; i < all_objects.length; i++)
    {
    o_area = object_area (all_objects);
    createTextFrame(all_objects, o_area);
    }

// more script..

// maybe more script

function createTextFrame (forObject, value)
   {
   var frame;
   frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});
   frame.move (forObject.parent);
   frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);

   // colour: see below

   frame.fillColor = colour;
   frame.fillTint = 50;
   frame.contents = String(Math.round(value*10)/10)+" / "+String(Math.round((value*1000)/p_area)/10)+"%";
   }


As to colour, you define that at the beginning of the script. Where Jongware checks/created the layer would be a good place, and the check looks the same:

try
    {
    app.activeDocument.colors.add ({name: "pct_colour", space: ColorSpace.cmyk, colorValue: [10,10,100,10]})
    }
catch (_) {} // not interested in errors

You would then later assign that colour to a text frame:

frame.fillColor = app.activeDocument.swatches.item ("pct_colour");

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
New Here ,
Mar 01, 2010 Mar 01, 2010

Copy link to clipboard

Copied

Thank you, you're both awesome!

One more question (I debated starting a new post but thought it was so relvant to this one it probably belonged here):

I'd like to add the link name to the frame label. I thought if I followed the same logic of referencing all links in the document and then setting a loop to capture them all that I could reference it later in the frame.contents before the math string.

I'm sure that I have a few things wrong and I can't figure out  how to write the function to add the link names to the text frame. Putting it inside the createTextFrame function seems illogical, but with writing it into that function I'm at a loss.

I searched the Forums and turned up some interesting bits about extracting file names as a starting point (Peter, I think my all_links reference is from one of your posts). I also tried (but abondoned) referencing XMP.

// reference to the document's page items
all_objects = doc.pageItems.everyItem().getElements();

//try 02 to reference all links
all_links = app.activeDocument.allGraphics;
     for (i = 0; i < all_links.length; i++)
          {
     frame.contents = String(all_links.itemLink.filePath).name;
     }
     

// process each object in turn
for (i = 0; i < all_objects.length; i++)
    {
    // calculate an object's page area
    o_area = object_area (all_objects);
     createTextFrame(all_objects, o_area);

     function createTextFrame (forObject, value, myObject)
               {
               var frame;

/* frame code */
               frame.contents = all_links, String(Math.round(value*10)/10)+"squ IN: "+ String(Math.round((value*1000)/p_area)/10)+"% of Total Page";
               }
    }

The rest of the script works perfectly and I understand the part about the fill color now, create a new color and name it while setting the value, then reference it inside the frame variable. Maybe I should do the same with the link name?

Thanks again

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
New Here ,
Mar 01, 2010 Mar 01, 2010

Copy link to clipboard

Copied

Tried switching from all ojects to just the links, but I think I've got it wrong at the frame.contents point. Help?

//new reference to all links
all_objects = app.activeDocument.allGraphics;


//all_links = doc.pageItems[0].graphics[0].itemLink.filePath.name;
     

// process them in turn
for (i = 0; i < all_objects.length; i++)
    {
    // calculate an object's page area
    o_area = object_area (all_objects);
     createTextFrame(all_objects, o_area);
     
     /*try 02
     all_links = app.activeDocument.allGraphics;
     for (i = 0; i < all_links.length; i++) */

     function createTextFrame (forObject, value, myObject)
               {
               var frame;

               frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","45mm"]});
               frame.move (forObject.parent);
               frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);
               //label fill color & tint
               frame.fillColor = app.activeDocument.swatches.item ("pct_color");
               frame.fillTint = 50;
               frame.textFramePreferences.ignoreWrap = false;
               frame.contents = String(all_links.itemLink.filePath).name, String(Math.round(value*10)/10)+"squ IN: "+ String(Math.round((value*1000)/p_area)/10)+"% of Total Page";
               }
    }

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 ,
Mar 01, 2010 Mar 01, 2010

Copy link to clipboard

Copied

That function should not be declared inside the for loop. Always put all your functions outside everything else to make them globally available.

(.. I think that's all, without running the script ..)

[Add] Well, apart from this: the function is already called with your active object, so it's kinda "neat" if you also use

frame.contents = forObject.itemLink.filePath, [etc.]

I see you cast the filePath to a String -- according to my JS Help, it's already a string, and it doesn't have a .name property.

Again, that ought to be 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
New Here ,
Mar 01, 2010 Mar 01, 2010

Copy link to clipboard

Copied

Mmm, seems I'm still not understanding function placement with loops. I visited W3C to read up on it, but I think I also need more practice to make hte connection.

I placed the reference outside then tried calling to the string inside the for loop. I think I'm going wrong at the second declaration under the for loop. If so, where does that belong, or is it redundent?

// reference to the document's page items
all_objects = doc.pageItems.everyItem().getElements();

// reference all graphics
all_links = app.activeDocument.allGraphics;

// process them in turn
for (i = 0; i < all_objects.length; i++)

/*this is where I think I'm going wrong*/

(i = 0; i < all_links.length; i++);
    {
// calculate an object's page area
    o_area = object_area (all_objects);


     createTextFrame(all_objects, o_area);
     function createTextFrame (forObject, value, myObject)
               {
               var frame;
               //var myLink = myObject.graphics.item(0).itemLink;

               frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","45mm"]});
               frame.move (forObject.parent);
               frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);
          //label fill color
          frame.fillColor = app.activeDocument.swatches.item ("pct_color");
          frame.fillTint = 50;
          frame.textFramePreferences.ignoreWrap = false;
               //frame.contents = myLink.name;
/*I added the name String but not sure it's right*/

          frame.contents = String(all_links.itemLink.filePath).name)+String(Math.round(value*10)/10)+"squ IN: "+ String(Math.round((value*1000)/p_area)/10)+"% of Total Page";
          }
    }

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
New Here ,
Mar 01, 2010 Mar 01, 2010

Copy link to clipboard

Copied

Okay, tried changing everything to only get the links but I error out at

all_links = doc.allGraphics.getElements();

so, not getting far.

Total script below. I'll keep reading and working tomorrow, eyes hurt for now.

// reference to the document's page items
/*all_objects = doc.pageItems.everyItem().getElements();*/

// reference all graphics
all_links = doc.allGraphics.getElements();



// process them in turn
/*for (i = 0; i < all_objects.length; i++)*/
for (i = 0; i < all_links.length; i++);
    {
// calculate an object's page area
    o_area = object_area (all_links);


     createTextFrame(all_links, o_area);

     function createTextFrame (forObject, value, myObject)
               {
               var frame;
               //var myLink = myObject.graphics.item(0).itemLink;

               frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","45mm"]});
               frame.move (forObject.parent);
               frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);
               //label fill color
               frame.fillColor = app.activeDocument.swatches.item ("pct_color");
               frame.fillTint = 50;
               frame.textFramePreferences.ignoreWrap = false;
               //frame.contents = myLink.name;
/*tried adding string for link names here*/
               frame.contents = String((all_links.itemLink.filePath).name)+String(Math.round(value*10)/10)+"squ IN: "+ String(Math.round((value*1000)/p_area)/10)+"% of Total Page";
               }
    }
// restore the doc's view preferences
doc.viewPreferences.properties = view_prefs;

function object_area (obj)
    {
    var gb = obj.geometricBounds;
    var width = gb[3]-gb[1];
    var height = gb[2]-gb[0];
    return width * height
    }

Really interested in where I'm going wrong. Thanks!

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
New Here ,
Mar 01, 2010 Mar 01, 2010

Copy link to clipboard

Copied

Jongware, thanks for the added info.

I didn't see it before I added those posts. I'll back track and see if I can get it right from your advice. Thanks!

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
New Here ,
Nov 02, 2010 Nov 02, 2010

Copy link to clipboard

Copied

Hello,

This "square area percent page report" is so very close to what I need for my project. The only difference is that instead of a percentage of each object in relation to the page, I need the actual size in square millimeters of each object on each page. My task is two draw boxes around every object. Copy and paste the height and width in a spreadsheet that multiplies the two measurements to give me the area. Of course I have to do this literally thousands of times! Do you know of a script that can assist me with this task? I appreciate any direction you can give.  Thank you.

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 ,
Nov 02, 2010 Nov 02, 2010

Copy link to clipboard

Copied

Mmm.

Peter's "object_area" function returns the actual object area, but it's in inches, rather than mm. You can work around that using the definition of one inch ("One Inch Equals 25.4 mm" -- it's official!), using

area_in_mm = object_area (all_objects) * 25.4 * 25.4;

or -- easier -- just set the measurements to millimeters, near the top of his script! (All measurements "inside" a script are automatically converted to 'the active' units.)

But I don't get this

My task is two draw boxes around every object

or this

Copy and paste the height and width in a spreadsheet that multiplies the two measurements to give me the area

The scripts above don't draw the boxes; they use what's already there on the page. (And why "two"?)

And InDesign is horrible in copying information out of it into a spreadsheet. A typical solution would be to write the measurements into a simple text file, and import that into any other program to process.

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
New Here ,
Nov 03, 2010 Nov 03, 2010

Copy link to clipboard

Copied

d

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
New Here ,
Nov 03, 2010 Nov 03, 2010

Copy link to clipboard

Copied

The boxes are really frames. Every image on a page has a frame around it. The dimensions of this frame (width and height) gives me a very simple approximation of how much space the image takes up on the page. Because selecting the frame doesnt give me square area (only width and height) I multiply the two to give me the square area. It would save me a step and cut my time in half if I already had the square area of the object to copy and paste into my list. If InDesign just gave me the square area I wouldn't have this problem. Hope that makes more sense.

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
Participant ,
Nov 13, 2020 Nov 13, 2020

Copy link to clipboard

Copied

Hello all, 

 

I found this from way back when, this is 90% of what I am looking for—with some modifications. 
I try running it, but it's throwing an underfined error in the function at the end, outside of the loop. I read the code multiple time, i don't quite understand the use of (obj).

function object_area (obj)



// reference to the document
doc = app.documents[0];
// store the doc's view preferences
view_prefs = doc.viewPreferences.properties;
// set measurement units to inches
doc.viewPreferences.verticalMeasurementUnits = doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
// calculate page area
p_area = doc.documentPreferences.pageWidth * doc.documentPreferences.pageHeight;

//create new layer
try {
 app.activeDocument.layers.add({name:"Object Percent of Page"});
} 
catch (_)
{
}
thatNewLayer = app.activeDocument.layers.item("Object Percent of Page");

// reference to the document's page items
all_objects = doc.pageItems.everyItem().getElements();


// process them in turn
for (i = 0; i < all_objects.length; i++)
    {
    // calculate an object's page area
    o_area = object_area (all_objects);
     createTextFrame(all_objects, o_area);

     function createTextFrame (forObject, value)
               {
               var frame;
               frame = app.activeDocument.textFrames.add(thatNewLayer, {geometricBounds:[0,0,"5mm","20mm"]});
               frame.move (forObject.parent);
               frame.move ([forObject.geometricBounds[1],forObject.geometricBounds[0]]);
               //frame.fillColor = [10,10,100,10];
               //frame.fillTint = 50;
               frame.contents = String(Math.round(value*10)/10)+" / "+String(Math.round((value*1000)/p_area)/10)+"%";
               }
    }
// restore the doc's view preferences
doc.viewPreferences.properties = view_prefs;

function object_area (obj)
    {
    var gb = obj.geometricBounds;
    var width = gb[3]-gb[1];
    var height = gb[2]-gb[0];
    return width * height
    }


So my first question is how to get rid off the underfined error in the function? The second question. I need to sum up all the text boxes on the page ( or all object is fine-i can delete the picture boxes, etc prior to running the script) and provide the total area in percentage occupied in the document.  For example, all object (text boxes) occupies 19.25%.  
This can either be an alert or draw another text box with the percentage result
I don't know how to loop each box and capture it in an array, and then process the info.
Any pointers would be appreciated, i can take bits and pieces and assemble it.

Regards, Brian

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
Participant ,
Nov 14, 2020 Nov 14, 2020

Copy link to clipboard

Copied

LATEST

pls. ignore this, i will start new thread. thanks.

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