Skip to main content
Participating Frequently
February 25, 2010
Answered

Square area percent of page report

  • February 25, 2010
  • 2 replies
  • 3816 views

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

This topic has been closed for replies.
Correct answer Peter Kahrel

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!


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

2 replies

Peter Kahrel
Community Expert
Community Expert
February 26, 2010

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

Is there no Illustrator scripting forum?

Peter

Participating Frequently
February 26, 2010

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

Jongware
Community Expert
Community Expert
March 1, 2010

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


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

Participating Frequently
February 25, 2010

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

Peter Kahrel
Community Expert
Community Expert
February 26, 2010

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