Copy link to clipboard
Copied
Hi everyone,
I'm working on some documents that cotain text frames aligned to baseline grid where they are not supposed to be. They all have a specific fill color applied ("Akane red"). I managed to create a script which find and select all the text in the frame, but I'm stuck on the "Grid Alignment" part. The selected text should not be aligned to baseline grip. Could you please help me? Here's my code:
var doc = app.activeDocument;
var myDoc = app.activeDocument;
app.findObjectPreferences = null;
app.findObjectPreferences.fillColor = "Akane red";
var found = doc.findObject();
for(var i =0;i<found.length;i++)
{
try{
found[i].select();
}catch(e){}
}
app.findObjectPreferences = null;
try {
app.selection[0].texts[0].select();
} catch (_)
{
}
Thanks in advance,
Rogerio
Copy link to clipboard
Copied
Hi @Rogerio5C09, good to see you around. I had a look at your problem and I think it may be related to a bug I reported a while ago. The bug is that a fillColor (or strokeColor) cannot be supplied to the findObjectPreferences without throwing an error.
Anyway, here is a working script to do what you want I think. The actual property to turn off is "alignToBaseline".
- Mark
/**
* Unsets "Align To Baseline" for all text in text frames filled with the target color.
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/script-to-find-and-select-all-text-in-a-particular-frame-and-set-grid-alignment-to-none/m-p/13932423
*/
function main() {
var doc = app.activeDocument,
swatchName = 'Akane red';
if (!doc.swatches.itemByName(swatchName).isValid) {
alert('No swatch "' + swatchName + '" in document.');
return;
}
app.findChangeObjectOptions.objectType = ObjectTypes.TEXT_FRAMES_TYPE;
app.findObjectPreferences = NothingEnum.NOTHING;
// this next line is just to work around this indesign bug: https://indesign.uservoice.com/forums/601180-adobe-indesign-bugs/suggestions/46404439--extendscript-app-findobjectpreferences-fillcolor
app.changeTextPreferences.fillColor = swatchName;
app.findObjectPreferences.fillColor = swatchName;
var found = doc.findObject();
for (var i = 0; i < found.length; i++)
found[i].texts[0].alignToBaseline = false;
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Unapply Baseline Grid To Target Frames');
Copy link to clipboard
Copied
Hi @m1b , likewise! 🙂 And thanks for the script! It worked just as expected.
I just realized there are some frames in "Akane red" color that Find/Change is not picking up. I found out that the swatch name is changing somehow by adding some random numbers at the end (see screenshot). This is the first time that I'm seeing it. Any thoughts? I guess that's why the script is not working on these particular frames.
Anyway, I found a workaround by finding Inset Spacing instead - the text frames are set to 8,8,10,10 or 5,5,5,5 (Top, Bottom, Left, Right). I'm attaching some files for your reference here. See script below - Sorry, it dosn't look as great as yours and there might be some unnecessary lines hahah. So, I'm try to figure out how to make it work on multiple documents. For now, it works only on a single document and the rest remains the same. Could you please take a look?
for (var d=0; d<app.documents.length; d++)
{
var doc = app.documents[d];
function main() {
app.findChangeObjectOptions.objectType = ObjectTypes.TEXT_FRAMES_TYPE;
app.findObjectPreferences = NothingEnum.NOTHING;
app.changeObjectPreferences.insetSpacing = [ 8,10,8,10 ];
app.findObjectPreferences.insetSpacing = [ 8,10,8,10 ];
var found = doc.findObject();
for (var i = 0; i < found.length; i++)
found[i].texts[0].alignToBaseline = false;
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Unapply Baseline Grid To Target Frames');
}
for (var d=0; d<app.documents.length; d++)
{
var doc = app.documents[d];
function main() {
app.findChangeObjectOptions.objectType = ObjectTypes.TEXT_FRAMES_TYPE;
app.findObjectPreferences = NothingEnum.NOTHING;
app.changeObjectPreferences.insetSpacing = [ 5,5,5,5 ];
app.findObjectPreferences.insetSpacing = [ 5,5,5,5 ];
var found = doc.findObject();
for (var i = 0; i < found.length; i++)
found[i].texts[0].alignToBaseline = false;
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Unapply Baseline Grid To Target Frames');
}
Also, I noticed that some frames contain tables with text aligned to baseline grid and the script doesn't work on them. Would it be possible to turn off "alignToBaseline" on tables as well?
Thanks in advance,
Rogerio
Copy link to clipboard
Copied
Hi @Rogerio5C09, thanks for the test files—that was helpful. Here is a version of the script that searches for any swatch starting with "Akane red". - Mark
/**
* Unsets "Align To Baseline" for all text in text frames filled with the target color.
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/script-to-find-and-select-all-text-in-a-particular-frame-and-set-grid-alignment-to-none/m-p/13932423
*/
function main() {
var doc = app.activeDocument,
swatchNameMatcher = /^Akane Red/i,
foundSwatches = getSwatches(doc, swatchNameMatcher);
if (foundSwatches.length == 0) {
alert('No swatches matching "' + swatchNameMatcher + '" in document.');
return;
}
for (var s = 0; s < foundSwatches.length; s++) {
app.findChangeObjectOptions.objectType = ObjectTypes.TEXT_FRAMES_TYPE;
app.findObjectPreferences = NothingEnum.NOTHING;
// this next line is just to work around this indesign bug: https://indesign.uservoice.com/forums/601180-adobe-indesign-bugs/suggestions/46404439--extendscript-app-findobjectpreferences-fillcolor
app.changeTextPreferences.fillColor = foundSwatches[s].name;
app.findObjectPreferences.fillColor = foundSwatches[s].name;
var found = doc.findObject();
for (var i = 0; i < found.length; i++) {
found[i].texts[0].alignToBaseline = false;
if (found[i].tables.length > 0)
found[i].tables.everyItem().cells.everyItem().texts[0].alignToBaseline = false;
}
}
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Unapply Baseline Grid To Target Frames');
/**
* Returns array of swatches with names
* matching the `matcher` RegExp.
* @author m1b
* @version 2023-07-14
* @param {Document} doc - an Indesign Document.
* @param {RegExp} matcher - the regex to match the swatch name.
*/
function getSwatches(doc, matcher) {
var found = [],
swatches = doc.swatches;
for (var i = 0; i < swatches.length; i++) {
if (matcher.test(swatches[i].name))
found.push(swatches[i]);
}
return found;
};
Copy link to clipboard
Copied
Hi Mark, thanks so much! 🙂
I tested the script and it works perfectly. Would it be possible to make it work across multiple documents as well?
Regards,
Rogerio
Copy link to clipboard
Copied
Hi @Rogerio5C09, glad it worked for you. It should have been really simple to make it work on all open documents, but ... when I simply put the whole thing in a loop over the documents it just did the active document and no others. I've never seen that behaviour before and I honestly don't know why it didn't work, but I would love to learn. Maybe doc.findObject() only works if doc is active? Anyway, I worked-around the problem by looping over the document names and setting them as the activeDocument.
- Mark
Here is the resulting script:
/**
* Unsets "Align To Baseline" for all text in text frames filled with the target color in all open documents.
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/script-to-find-and-select-all-text-in-a-particular-frame-and-set-grid-alignment-to-none/m-p/13932423
*/
function main() {
var docNames = app.documents.everyItem().name,
swatchNameMatcher = /^Akane Red/i;
for (var d = 0; d < docNames.length; d++) {
var doc = app.documents.itemByName(docNames[d]),
foundSwatches = getSwatches(doc, swatchNameMatcher);
if (foundSwatches.length == 0) {
alert('No swatches matching "' + swatchNameMatcher + '" in document "' + doc.name + '".');
continue;
}
app.activeDocument = doc;
for (var s = 0; s < foundSwatches.length; s++) {
app.findChangeObjectOptions.objectType = ObjectTypes.TEXT_FRAMES_TYPE;
app.findObjectPreferences = NothingEnum.NOTHING;
// this next line is just to work around this indesign bug: https://indesign.uservoice.com/forums/601180-adobe-indesign-bugs/suggestions/46404439--extendscript-app-findobjectpreferences-fillcolor
app.changeTextPreferences.fillColor = foundSwatches[s].name;
app.findObjectPreferences.fillColor = foundSwatches[s].name;
var found = doc.findObject();
for (var i = 0; i < found.length; i++) {
found[i].texts[0].alignToBaseline = false;
if (found[i].tables.length > 0)
found[i].tables.everyItem().cells.everyItem().texts[0].alignToBaseline = false;
}
}
}
// clean up
app.activeDocument = app.documents.itemByName(docNames[0]);
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Unapply Baseline Grid To Target Frames');
/**
* Returns array of swatches with names
* matching the `matcher` RegExp.
* @author m1b
* @version 2023-07-14
* @param {Document} doc - an Indesign Document.
* @param {RegExp} matcher - the regex to match the swatch name.
*/
function getSwatches(doc, matcher) {
var found = [],
swatches = doc.swatches;
for (var i = 0; i < swatches.length; i++) {
if (matcher.test(swatches[i].name))
found.push(swatches[i]);
}
return found;
};
Copy link to clipboard
Copied
I'm no expert and i'm learning too - so just looking and lurking here...
Just wondering why docNames variable is assigned the value app.documents.everyItem().name
Just wondering why not like this - I haven't tried it. But just thinking.
function main() {
var documents = app.documents,
swatchNameMatcher = /^Akane Red/i;
for (var d = 0; d < documents.length; d++) {
var doc = documents[d],
foundSwatches = getSwatches(doc, swatchNameMatcher);
if (foundSwatches.length == 0) {
alert('No swatches matching "' + swatchNameMatcher + '" in document "' + doc.name + '".');
continue;
}
app.activeDocument = doc;
}
then at the end
}
// clean up
app.activeDocument = documents[0];
}
Copy link to clipboard
Copied
No, you have a good eye, @Eugene Tyson. I did this a strange way in an attempt to work around an apparent bug I found. It appears to be a problem with Document.findObject(). See this post I wrote, asking if anyone can reproduce the problem. If you have time, check out that post and see if you can reproduce the bug.
Buy yes, if there wasn't a bug (for me, at least) I would do it the way you described, except with no need to set the activeDocument.
- Mark
Copy link to clipboard
Copied
Bit out of my paygrade ! Yikes !
Copy link to clipboard
Copied
Perhaps I can explain what I did. First my aim was to loop over the documents and make each one the activeDocument. The problem with this is that as soon as you change the activeDocument, all the documents' indices change such that the activeDocument is always 0. So the normal loop won't work as the references will be wrong. Instead I collected the document names and looped over those, getting the document with app.documents.itemByName. The clean up bit is just to return the original activeDocument.
- Mark
Copy link to clipboard
Copied
Hi @m1b, yes, it might be a problem with doc.findObject() - I've been testing some other scripts and they only work if doc is active. Very weird. At least findText and findGrep didn't let me down hahaha
Copy link to clipboard
Copied
Yes we have confirmed there is a bug with Document.findObject().
Copy link to clipboard
Copied
A better option would be to create an Object Style - and in the object style don't have it align to the baseline grid.
Then the script could find the frames and apply the object style.
Then you can change the Object Style everytime you need to make a global change.
Copy link to clipboard
Copied
I agree @Eugene Tyson but in this case I got the impression the documents were created elsewhere and weren't so tidy. Also the alignToBaseline would have to be turned off for every paragraph style in the document, and even then it would only work if they were neatly set up with an unoverridden paragraph style.
- Mark
Copy link to clipboard
Copied
ah yes - I don't always remember things are setup as methodically as I would.
Good point.