Copy link to clipboard
Copied
Hi Experts, I dont know what the problem of this script , when it run in document without section(s) it run correctly but when i add section it cannot identify page (1,2,3) so page (1,2,3) became (7,8,9), see the screen shot here as example :
here is the script :
var myDoc = app.documents[0];
var myDocPages = myDoc.pages.everyItem().getElements();
var TargetPagesArray = [1,2,3];
//Loop in Pages
for(var n = myDocPages.length-1; n >= 0; n--){
if (checkPage(TargetPagesArray, n+1)) {
$.writeln(n);
//Now Assign to Desired Frames
var allTargeTextFrames = myDoc.pages[n].textFrames.everyItem().getElements();
// Check for text frames if locked and apply Object Style:
for( var i = 0; i<allTargeTextFrames.length; i++ ){
if(allTargeTextFrames[i].locked == true){//Prevent Apply to Locked TextFrames
var locked = "locked"; //Dont Apply to Locked TextFrames!
}else{
allTargeTextFrames[i].applyObjectStyle(myDoc.objectStyles.item("Test"));
}
}
}
}
//First Check if Page is Existed in the Array Function - from Rob Day
function checkPage(PagesArray, obj) {
for (var i = 0; i < PagesArray.length; i++) {
if (PagesArray[i] === obj) {
return true;
}
}
return false;
}
to check if the page is already exist before continue, i used the function of @rob day discussed here :
https://community.adobe.com/t5/indesign-discussions/remove-pages-in-an-array/m-p/11758331#M410798
so please help! and thanks in advance
Hi @M.Hasanin, your script is looking good, but I have made a few changes:
1. I've wrapped it in a main function and doScript call. This just helps by providing a single undo for each time you run the script—otherwise to undo, you must use one undo for each setting of object style.
2. I've changed the function name of checkPages to be more general—you can use it for any case where you want to know if an object is in an array.
3. I've changed the if predicate to check the *name* of the page conve
...Good point @Laubender and this might be critical any many cases, especially if you are not in control of the document.
But on the other hand, if you are controlling the document, my preference is use page names. Yes I must ensure page numbers are unique but I think that is a good practice in any case. The reason for my preference is that I can use the itemByRange method more intuitively I can say itemByRange('1','3') and I know I'm getting the pages I named '1' to '3' which might happen to hav
...While I think of it, here's another interesting thing about the object you get back from Page.itemByRange:
It gives you an everyItem-style object—sorry don't know the technical term for this thing. But it is an interesting object—very different from a normal collection or array.
You can do this:
var doc = app.activeDocument;
var myPages = doc.pages.itemByRange('1', '3');
var myPageNames = myPages.name;
If you run this, the myPageNames variable is a normal ExtendScript array containing strings—
...Copy link to clipboard
Copied
Hi @M.Hasanin, your script is looking good, but I have made a few changes:
1. I've wrapped it in a main function and doScript call. This just helps by providing a single undo for each time you run the script—otherwise to undo, you must use one undo for each setting of object style.
2. I've changed the function name of checkPages to be more general—you can use it for any case where you want to know if an object is in an array.
3. I've changed the if predicate to check the *name* of the page converted to number, rather than the index.
- Mark
function main() {
var myDoc = app.documents[0];
var myDocPages = myDoc.pages.everyItem().getElements();
var TargetPagesArray = [1, 2, 3];
//Loop in Pages
for (var n = myDocPages.length - 1; n >= 0; n--) {
if (arrayContainsObject(TargetPagesArray, Number(myDocPages[n].name))) {
$.writeln(n);
//Now Assign to Desired Frames
var allTargeTextFrames = myDoc.pages[n].textFrames.everyItem().getElements();
// Check for text frames and apply label value:
for (var i = 0; i < allTargeTextFrames.length; i++) {
if (allTargeTextFrames[i].locked == true) {//Prevent Apply to Locked TextFrames
var locked = "locked"; //Dont Apply to Locked TextFrames!
} else {
allTargeTextFrames[i].applyObjectStyle(myDoc.objectStyles.item("Test"));
}
}
}
}
//First Check if Page is Existed in the Array Function - from Rob Day
function arrayContainsObject(arr, obj) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === obj) {
return true;
}
}
return false;
}
}
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Do Script');
Copy link to clipboard
Copied
Copy link to clipboard
Copied
@m1b , thanks for your help, i tried to apply the same concept on page ranges! but it didnt work,, thats weired!
here is the simple script :
//Apply Object Style to TextFrames in Pages Range
//---------------------------------------------------------------------------------//
var myDoc = app.documents[0];
var myDocPages = myDoc.pages.everyItem().getElements();
//Logical Pages
var UserPageStart = 7; //Actually its Page 1
var UserPageEnd = 9; //Actually its Page 3
//Convert Logical Pages to Script Understand!
var PrepareStart = Number(UserPageStart)-1;
var PrepareEnd = Number(UserPageEnd)-1;
var StartNumber = app.activeDocument.pages[PrepareStart].name;
var EndNumber = app.activeDocument.pages[PrepareEnd].name;
function doPageRangeFrames(){
var myFrames = myDoc.pages.itemByRange(StartNumber,EndNumber).textFrames.everyItem().getElements();
for (var i=0; i< myFrames.length ; i++) {
if(myFrames[i].locked == true){//Prevent Apply to Locked TextFrames
var Locked = "Locked"; //Dont Apply to Locked TextFrames!
}else{
myFrames[i].applyObjectStyle(myDoc.objectStyles.item("Test"));
}
}
}
//doPageRangeFrames();
app.doScript(doPageRangeFrames, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Apply Object Style to Text Frames in Page Range");
Copy link to clipboard
Copied
If you use primary text frames, you need only to apply text frames with that primary text frame with that object style.
Copy link to clipboard
Copied
Thank you, but in this case i need it scripted because i will use some individual pages in the array
Copy link to clipboard
Copied
To spare you some trouble, do not work with page names, but with page positions, property documentOffset of a page, in the document. As you already found out, there could be two or more pages with exactly the same name in one document.
Regards,
Uwe Laubender
( Adobe Community Professional )
Copy link to clipboard
Copied
Thanks @Laubender , its first time to identify (documnetOffset property), please can you show me example? and what if there is a lot of Numbers as the same name? shouid i loop for them using this property? and thanks in advance
Copy link to clipboard
Copied
Good point @Laubender and this might be critical any many cases, especially if you are not in control of the document.
But on the other hand, if you are controlling the document, my preference is use page names. Yes I must ensure page numbers are unique but I think that is a good practice in any case. The reason for my preference is that I can use the itemByRange method more intuitively I can say itemByRange('1','3') and I know I'm getting the pages I named '1' to '3' which might happen to have a documentOffset that might change by the side-effect of adding another page to a preceding section. Feel free to correct me, as I am quite inexperienced with complex documents.
@M.Hasanin here's a little help: the Pages.itemByRange method takes two arguments for start and end of range, but those arguments can be Numbers or Strings. If they are numbers they will be interpreted as documentOffsets. If they are strings they will be interpreted as names. This is really good to understand.
For example both the following examples do the same thing:
1. using Page.documentOffset
var startDocumentOffset = 7;
var endDocumentOffset = 9;
var myFrames = myDoc.pages.itemByRange(startDocumentOffset, endDocumentOffset).textFrames.everyItem().getElements();
2. using Page.name
var startPageName = '1';
var endPageName = '3';
var myFrames = myDoc.pages.itemByRange(startPageName, endPageName).textFrames.everyItem().getElements();
Your weakest point is understanding what objects are held by your variables. I recommend you make a large effort to name your variables with what they are. It sounds strange, but this tends to force you to know what they are.
So startDocumentOffset which is much better than UserStartPage (which is wrong because that variable doesn't hold a Page object) it holds a Number object. And then your variable StartNumber is misleading because it contains a String object (the page's name) so I called it StartPageName. Can you see how things can be easier to understand when you really try to get your variable name's right?
I hope that helps. It will take time and practice and many attempts to understand, and you are doing very well.
- Mark
Copy link to clipboard
Copied
While I think of it, here's another interesting thing about the object you get back from Page.itemByRange:
It gives you an everyItem-style object—sorry don't know the technical term for this thing. But it is an interesting object—very different from a normal collection or array.
You can do this:
var doc = app.activeDocument;
var myPages = doc.pages.itemByRange('1', '3');
var myPageNames = myPages.name;
If you run this, the myPageNames variable is a normal ExtendScript array containing strings—one for each page collected in the myPages variable and the strings are the page names. The equivalent of typing this:
var myPageNames = [
doc.pages.itemByName('1').name,
doc.pages.itemByName('2').name,
doc.pages.itemByName('3').name
];
However, it isn't always that straightforward. If you do this:
var myTextFrames = myPages.textFrames;
then you get a single TextFrames collection object, not an array of TextFrames objects (one per page). This is convenient in some cases I suppose. So we just have to learn what to expect.
- Mark
Copy link to clipboard
Copied
Thanks alot, you are great teacher and genius! , i will do my best and let you know, have agreat wonderful day
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more