Forum Replies Created
-
AuthorPosts
-
Mike Dean
MemberI’m not sure at a glance why the previousItem method isn’t working, but if you assign the duplicate layer to a variable:
var newLayer = docList[d].layers.item (layerList[check]).duplicate();
You can then refer to it later:
newLayer.name = "Unpriced";
Mike Dean
MemberAh, even simpler. Thanks Peter!
It would be a good idea to add some error checking in there, especially on the save file step. It currently overwrites without asking, and you probably don’t want that longer term. You could add a step to check for an existing file, and if it exists either ask the user if they want to overwrite. Or it could automatically create a backup copy of the existing file.
Mike Dean
MemberHi Morgan,
It’s pretty simple but you have to create a new file object for both the template you’re opening and file you’re saving before you can open/save. Example code is below. Hope this helps, and good luck!
//create a new file object for the template
var templateFile = new File("~/Desktop/test.indt"); //where ~/Desktop is a username-independent path to the desktop
//open template
var template = app.open(templateFile);//create a new file object for the test01 file
var docFile = new File("~/Desktop/test01.indd");
//save as. NOTE: This will overwrite without asking, so be careful
var doc = template.save(docFile)//do stuff in file here
//close and save doc file
doc.close(SaveOptions.YES)Mike Dean
MemberOk, ok, I’ll quit being lazy. :)
This has been updated to attempt to find all number series using GREP and update.
(function(){
app.findGrepPreferences = NothingEnum.nothing;
app.findGrepPreferences.findWhat = "(d+, )((d)[, ]*)+";
var found = app.activeDocument.findGrep();for (var i=found.length-1; i>=0; i--){
var newText = removeCommonPrefix(found[i].contents.split(", ")).join(", ");
$.writeln("Replacing " + found[i].contents + "with " + newText)
found[i].contents = newText;
}function removeCommonPrefix(numbers) {
var updatedNumbers =[];
var i = numbers.length -1;
while (i >= 1) {
var currentNumber = numbers[i];
var currentNumberPrefix = numbers[i].toString().slice(0, 3);
var preceedingNumberPrefix = numbers[i -1].toString().slice(0, 3);
var numberSuffix = numbers[i].toString().slice(3);
if (currentNumberPrefix == preceedingNumberPrefix) {
var number = numberSuffix;
} else {
var number = currentNumber;
}
updatedNumbers.unshift(number);
i--;
}
//the first number will always need the initial 3, so at the end of the loop add it to the start
updatedNumbers.unshift(numbers[0]);
return updatedNumbers;
}
})();
Mike Dean
MemberAh, my mistake. It’s just a few more lines to run this based on a selection, so I’ve updated the script below. Just select a series of numbers and run the script and it should clean up the series. It should also work on numbers greater than 6 digits as long as it’s always the first 3 numbers that are common.
(function(){
var selection = app.selection[0];if(selection!="[object Text]" && selection!="[object Paragraph]" ){
alert("Please select text and try again.");
return;
}selection.contents = removeCommonPrefix(selection.contents.split(", ")).join(", ");
function removeCommonPrefix(numbers) {
var updatedNumbers =[];
var i = numbers.length -1;
while (i >= 1) {
var currentNumber = numbers[i];
var currentNumberPrefix = numbers[i].toString().slice(0, 3);
var preceedingNumberPrefix = numbers[i -1].toString().slice(0, 3);
var numberSuffix = numbers[i].toString().slice(3);
if (currentNumberPrefix == preceedingNumberPrefix) {
var number = numberSuffix;
} else {
var number = currentNumber;
}
updatedNumbers.unshift(number);
i--;
}
//the first number will always need the initial 3, so at the end of the loop add it to the start
updatedNumbers.unshift(numbers[0]);
return updatedNumbers;
}
})();
Mike Dean
MemberIf you can find an entire series of numbers with GREP in a script, you should be able to split them into an array, loop through them to compare each number with the preceding number, then add them to a new array. So if the first 3 of the current number match the first 3 of the preceding number, only add the last 3 numbers to the new array. Otherwise, add the number as is (hopefully that makes sense).
I’m extra bored today, so I threw together a function to handle the number checking (I’m sure there’s a cooler way to do this, but this seems to work). If the function works as you expect, you could expand the script to loop through multiple number series in the document, feed them to this function, and use the returned array to update the document.
var sourceNumbers = [405354, 405358, 405359, 405369, 305046, 305047, 405360, 405381, 405382, 405378];var numbers = removeCommonPrefix(sourceNumbers);
$.writeln(numbers);function removeCommonPrefix(numbers){
var updatedNumbers = [];var i = numbers.length-1;
while(i>=1){
var currentNumber = numbers[i];
var currentNumberPrefix = numbers[i].toString().slice(0,3);
var preceedingNumberPrefix = numbers[i-1].toString().slice(0,3);
var numberSuffix = numbers[i].toString().slice(3,6);if(currentNumberPrefix==preceedingNumberPrefix){
var number = numberSuffix;
}
else{
var number = currentNumber;
}updatedNumbers.unshift(number);
i--;
}//the first number will always need the initial 3, so at the end of the loop add it to the start
updatedNumbers.unshift(numbers[0]);return updatedNumbers;
}
Mike Dean
MemberI think the easiest thing would be to leave the first line as is so it styles everything with the main body text style, then replace the second line with a GREP search that will find all number-only cells within that style and table.
So the second line would be replaced with something like this:
//create variables for paragraph styles
var tableBodyStyle = paragraphStyle(‘Table’, ‘Table – Body Text’);
var tableNumberStyle = paragraphStyle(‘Table’, ‘Table – Body Number’);//GREP to find text that only contains numbers, comma separator, or decimal, currency symbol
app.findGrepPreferences.findWhat = “^[d,.$]+$”; //this can be reduced if you only need digits
app.findGrepPreferences.appliedParagraphStyle = tableBodyStyle;
app.changeGrepPreferences.appliedParagraphStyle = tableNumberStyle;//search within current table
table.changeGrep();Mike Dean
MemberHmm, the only other thing I can think of is to read the contents of EPS file (the metadata should be plain text). If you open a MathType file in Notepad, do you see a line like this near the top?
%%Creator: MathTypeIf that’s present in a MathType 6.7a file, then you should be able to read the EPS file with a script as discussed in this Adobe forum thread:
https://forums.adobe.com/thread/472724Hope that helps!
Mike Dean
MemberOur MathType EPS files have the creator application name stored in the XMP metadata (we’re on MathType 6.9b), and it looks like you can check the XMP data from within InDesign.
So, from within your loop, you should be able to check the creator application for each link using:
myLink[i].linkXmp.creator;If it’s a MathType EPS, the creator property should be “MathType” (at least, that’s what it’s returning for me).
Mike Dean
MemberI think Loic’s approach will be simpler and more efficient, but as a learning exercise I thought I’d point out a couple of reasons why your original code isn’t working. First, the curly brace {} nesting isn’t quite right. Everything inside the for loop needs to be in a single set of curly braces. Then, everything that depends on an if statement needs to be in its own set of braces. So you’d want something like this:
for (i=0;i<myTable.cells.length;i++){
if (myTable.cells[i].texts[0].contents[0] == “Air Conditioning & Heating”){
myTable.rows.add(LocationOptions.AT_END, myTable);
myTable.rows[-1].contents = “###Heating & Air Conditioning”;
}
[[[Additional if statements here]]]
}In your existing code, the for loop ends at the first closing curly brace, then errors because the next line begins with an opening brace that it doesn’t know what to do with. Also, it’s always placing “Heating & Air Conditioning” because an if statement that doesn’t have a set of curly braces after it only applies to the next line. So myTable.rows.add depends on the if statement, but myTable.rows[-1].contents will always run.
Second, I think the if statement test might not come out quite right. I’m pretty sure .contents[0] will give you the first letter of the contents, so your first test winds up being something like “H” == “Air Conditioning & Heating”.
Mike Dean
MemberI’ve done this before using a combination of right indent and whites space characters, but usually only in TOCs that don’t include tab leader dots.
First, set up the right indents based on how much white space you want between your text and your page number. If you want 1 inch of white space, set the Right Indent to 1in and the Last Line Right Indent to -1in. This will push all your text over except the last line which will extend to the edge of the frame. (This is not quite done because this allows more than just the page number and tab separator to extend to the edge of the frame.)
Second, in the TOC settings, add a few em spaces before your tab character in the TOC page number separator (the number of spaces depends on how much white space you need). So your separator would be something like ^m^m^t. The em spaces should prevent any text from extending into the white space. But, tab leader dots can’t be applied to the em spaces, so if those are necessary this method may not work for you. It’s possible you could use the right indents for a partial solution and then add soft returns where it doesn’t quite work out. It’ll still be some soft returns, but it should be a lot less.
Mike Dean
MemberI can’t think of a reason why either of those settings would cause problems in an EPUB. Can they give you a reason why they don’t want these settings? (Note, I don’t really work with external clients, but I’m guessing it’s not that much fun to get them to change or explain their ways….)
For 1), InDesign does export keep option settings into the CSS, but I’ve never found an EPUB reading system that pays any attention to CSS keep options. If the settings are within paragraph styles, I’d think it would be very easy to remove those from the CSS (if they’re concerned about these settings I’m assuming they’re using the InDesign generated CSS and not writing their own).
If any keep options are set as a local setting and not in a style then they’ll show up in the CSS as an override. For example, if you’ve set keep options locally on a paragraph you’ll have an additional style declaration in the CSS (meaning there could be more settings to remove than just the one in the paragraph style).
Anyway, trying to typeset a book while not using the keep options sounds like a huge pain. That seems like it would add hours to typesetting, while removing those settings from the CSS could be done with a find and replace in a few minutes.
For 2), again, I’m not sure why this would cause an issue. There’s a CSS rule for transforming text to uppercase: text-transform:uppercase. InDesign will export this CSS rule if you’ve applied all caps in a paragraph style. The only difference I can think of is that most EPUB TOCs don’t allow styles to be applied, so if you have all caps applied by CSS they’ll still appear as title case in the navigation (to me this is preferable; all cap headings in the body can look ok, but all caps in an EPUB TOC don’t).
As far as scripts go, I’m sure there are options out there. It sounds like a common issue and a simple thing for a script. Here’s a GREP based option:
https://www.kahrel.plus.com/indesign/grep_change_case.htmlJanuary 13, 2016 at 12:14 pm in reply to: Recurrent Open And Save Indd Files In a Whole File Tree using JS #80757Mike Dean
MemberI have a similar script that I used to use years ago. It will loop through all the files in a single folder, run code on each file, then save and close (your code would go after the ////Script goes here line).
It only runs on a single folder though, it doesn’t go through subfolders. Recursion hurts my brain so I probably can’t help you there, but maybe this is at least a start. Also, it saves over all the files, so you’ll probably want to create backups before running this in case anything goes wrong.
Here’s the code for the script:
//This script will execute a script on all INDD files in selected folder
var myFolder = Folder.selectDialog(“Choose an Folder”)
var myFiles = myFolder.getFiles( “*.indd” );//disables warnings (missing fonts, etc.)
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.neverInteract;//If you’re placing a for loop within this loop, make sure the variables are different
for( var i = 0; i < myFiles.length; i++ ){
if (myFiles[i].name.slice(-5) == “.indd”){
myCurrentFile = app.open(myFiles[i])
}
/////////////////////////////Script goes here
myCurrentFile.close (SaveOptions.YES)
////////////////////////
}//re-enable warnings
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAllMike Dean
MemberI see. Thanks for the explanation!
I think this might be fairly simple (at least, simpler than I was originally making it). I was trying to think of was of being able to mark fonts as “used” and have the script skip them. But I think an even easier answer is to use script you originally posted with just two minor tweaks.
First, somewhere around the font array declaration (var font = [];), add a variable with the font that you only want to use once:
var uniqueFont = “Comic Sans MSBold”;Second, at the very end of the script (after all the curly braces), add:
app.selection[0].characters[Math.floor(Math.random() * app.selection[0].characters.length)].appliedFont = uniqueFont;The idea here is to let the original script work as intended. It will randomly apply a font to every character. Then, when that’s finished, it will apply your uniqueFont to a single, random character. That should keep things nice and simple!
Mike Dean
MemberDo you mean you want the very first character in the frame to use font[0] and swatch[0]? If that’s the case, you can adjust the for loop at the end of the script to start at the second character. Just change ch=0 to ch=1:
for (ch = 1; ch < app.selection[sel].characters.length; ch++) {Then right above that loop, add a couple of lines to style the first character:
app.selection[sel].characters[0].appliedFont = font[0];
app.selection[sel].characters[0].fillColor = swatch[0];And finally, to prevent the first font/swatch from being reused, you can add a couple of statements to remove them from the array:
font = font.slice(1);
swatch = swatch.slice(1);Out of curiosity, what’s the utility of a script like this? I’m just having trouble thinking of how I would use this (other than to play an evil joke on someone… “what happened to all the text in your InDesign file??”).
-
AuthorPosts
