Copy link to clipboard
Copied
Indesign mixes my images in a strange way, absolutely no order... I've got no idea what's wrong.
My images have got the same amount of digits and are mixed in the contact sheet like: 00023, 00001, 00024, 00046, 00002 etc.
Indesign CC 13.1 - Mac OS High Sierra 10.13.4
Here is the responsible code of the image catalog script:
function myWinOSFileFilter(myFolder){
var myFiles = new Array;
var myFilteredFiles = new Array;
for(myExtensionCounter = 0; myExtensionCounter < myExtensions.length; myExtensionCounter++){
myExtension = myExtensions[myExtensionCounter];
myFiles = myFolder.getFiles("*"+ myExtension);
if(myFiles.length != 0){
for(var myFileCounter = 0; myFileCounter < myFiles.length; myFileCounter++){
myFilteredFiles.push(myFiles[myFileCounter]);
}
}
}
return myFilteredFiles;
}
function myMacOSFileFilter(myFolder){
var myFilteredFiles = myFolder.getFiles(myFileFilter);
return myFilteredFiles;
}
I am fuzzy about it..
Hi,
the ExtendScript below is an edited version of the original. It is tested on Windows 10 with InDesign CC 2018.1. I could not test it with InDesign on Mac OS X. That's your turn. I added a sort function for file names and implemented it. File name sorting may not be perfect, but sufficiant. The sorting algorithm is by Martin Fischer from www.hilfdirselbst.ch.
Here's the full code:
...// EDITED BY UWE LAUBENDER
// ADDED: SORT FUNCTION.
// ImageCatalog-EDITED.jsx
// An InDesign CS6 JavaScript
/*
@@@BUILD
Copy link to clipboard
Copied
Hi,
Can you share the final document? ( using dropbox or similar service)
Can you share a sample of the actual filenames including extension? Are you on wndows or mac ?
Regards
Malcolm
Copy link to clipboard
Copied
Indesign CC 13.1 - Mac OS High Sierra 10.13.4
That's the first site... it starts with #atf0088.jpg why not #atf0001.jpg
#0001.jpg without letters in front doesn't work neither... .tif neither...
Copy link to clipboard
Copied
Hi,
then you have to sort your image Array with a custom function that is working with the name of the files.
Just tested the script on Windows 10. It's working as expected with a range of JPEG images named like yours.
The case is different on Mac OS X. And it will be even more different with OS X High Sierra. I can remember a bug where the script files in the Scripts Panel are totally jumbled and not sorted alphabetically anymore due to a change Apple did when going from Sierra to High Sierra, I think.
Search the forums and a thread comes up with some sorting suggestions here:
imageCatalog image sorting before import
Regards,
Uwe
Copy link to clipboard
Copied
A note to add: Alphabetical sorting of file names is not easy.
array.sort() without a custom function as argument of method sort() is not the way to go. You can try it, it may better the situation, but it will not be perfect.
EDIT: To make that clear, you have to sort after file names, not after files.
Always a good read by Marc Autret:
Indiscripts :: Alphabetical Sort in JavaScript (and InDesign)
Regards,
Uwe
Copy link to clipboard
Copied
I am a photographer ... no coder
Copy link to clipboard
Copied
Hi,
the ExtendScript below is an edited version of the original. It is tested on Windows 10 with InDesign CC 2018.1. I could not test it with InDesign on Mac OS X. That's your turn. I added a sort function for file names and implemented it. File name sorting may not be perfect, but sufficiant. The sorting algorithm is by Martin Fischer from www.hilfdirselbst.ch.
Here's the full code:
// EDITED BY UWE LAUBENDER
// ADDED: SORT FUNCTION.
// ImageCatalog-EDITED.jsx
// An InDesign CS6 JavaScript
/*
@@@BUILDINFO@@@ ImageCatalog-EDITED.jsx !Version! Thu May 17 2018 17:59:52 GMT+0200
*/
//Creates an image catalog from the graphic files in a selected folder.
//Each file can be labeled with the file name, and the labels are placed on
//a separate layer and formatted using a paragraph style ("label") you can
//modify to change the appearance of the labels.
//
//For more information on InDesign scripting, go to http://www.adobe.com/products/indesign/scripting/index.html
//Or visit the InDesign Scripting User to User forum at http://www.adobeforums.com .
//
//The myExtensions array contains the extensions of the graphic file types you want
//to include in the catalog. You can remove extensions from or add extensions to this list.
//myExtensions is a global. Mac OS users should also look at the file types in the myFileFilter function.
main();
function main(){
var myFilteredFiles;
//Make certain that user interaction (display of dialogs, etc.) is turned on.
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;
myExtensions = [".jpg", ".jpeg", ".eps", ".ps", ".pdf", ".tif", ".tiff", ".gif", ".psd", ".ai"]
//Display the folder browser.
var myFolder = Folder.selectDialog("Select the folder containing the images", "");
//Get the path to the folder containing the files you want to place.
if(myFolder != null){
if(File.fs == "Macintosh")
{
// CHANGES BY UWE LAUBENDER :
myFilteredFiles = myMacOSFileFilter(myFolder).sort( sortFileNames );
}
else
{
// CHANGES BY UWE LAUBENDER :
myFilteredFiles = myWinOSFileFilter(myFolder).sort( sortFileNames );
}
if(myFilteredFiles.length != 0){
myDisplayDialog(myFilteredFiles, myFolder);
alert("Done!");
}
}
}
//Windows version of the file filter.
function myWinOSFileFilter(myFolder){
var myFiles = new Array;
var myFilteredFiles = new Array;
for(myExtensionCounter = 0; myExtensionCounter < myExtensions.length; myExtensionCounter++){
myExtension = myExtensions[myExtensionCounter];
myFiles = myFolder.getFiles("*"+ myExtension);
if(myFiles.length != 0){
for(var myFileCounter = 0; myFileCounter < myFiles.length; myFileCounter++){
myFilteredFiles.push(myFiles[myFileCounter]);
}
}
}
return myFilteredFiles;
}
function myMacOSFileFilter(myFolder){
var myFilteredFiles = myFolder.getFiles(myFileFilter);
return myFilteredFiles;
}
//Mac OS version of file filter
//Have to provide a separate version because not all Mac OS users use file extensions
//and/or file extensions are sometimes hidden by the Finder.
function myFileFilter(myFile){
var myFileType = myFile.type;
switch (myFileType){
case "JPEG":
case "EPSF":
case "PICT":
case "TIFF":
case "8BPS":
case "GIFf":
case "PDF ":
return true;
break;
default:
for(var myCounter = 0; myCounter<myExtensions.length; myCounter++){
var myExtension = myExtensions[myCounter];
if(myFile.name.indexOf(myExtension)>-1){
return true;
break;
}
}
}
return false;
}
function myDisplayDialog(myFiles, myFolder){
var myLabelWidth = 112;
var myStyleNames = myGetParagraphStyleNames(app);
var myLayerNames = ["Layer 1", "Labels"];
var myDialog = app.dialogs.add({name:"Image Catalog"});
with(myDialog.dialogColumns.add()){
with(dialogRows.add()){
staticTexts.add({staticLabel:"Information:"});
}
with(borderPanels.add()){
with(dialogColumns.add()){
with(dialogRows.add()){
staticTexts.add({staticLabel:"Source Folder:", minWidth:myLabelWidth});
staticTexts.add({staticLabel:myFolder.path + "/" + myFolder.name});
}
with(dialogRows.add()){
staticTexts.add({staticLabel:"Number of Images:", minWidth:myLabelWidth});
staticTexts.add({staticLabel:myFiles.length + ""});
}
}
}
with(dialogRows.add()){
staticTexts.add({staticLabel:"Options:"});
}
with(borderPanels.add()){
with(dialogColumns.add()){
with(dialogRows.add()){
staticTexts.add({staticLabel:"Number of Rows:", minWidth:myLabelWidth});
var myNumberOfRowsField = integerEditboxes.add({editValue:3});
}
with(dialogRows.add()){
staticTexts.add({staticLabel:"Number of Columns:", minWidth:myLabelWidth});
var myNumberOfColumnsField = integerEditboxes.add({editValue:3});
}
with(dialogRows.add()){
staticTexts.add({staticLabel:"Horizontal Offset:", minWidth:myLabelWidth});
var myHorizontalOffsetField = measurementEditboxes.add({editValue:12, editUnits:MeasurementUnits.points});
}
with(dialogRows.add()){
staticTexts.add({staticLabel:"Vertical Offset:", minWidth:myLabelWidth});
var myVerticalOffsetField = measurementEditboxes.add({editValue:24, editUnits:MeasurementUnits.points});
}
with (dialogRows.add()){
with(dialogColumns.add()){
staticTexts.add({staticLabel:"Fitting:", minWidth:myLabelWidth});
}
with(dialogColumns.add()){
var myFitProportionalCheckbox = checkboxControls.add({staticLabel:"Proportional", checkedState:true});
var myFitCenterContentCheckbox = checkboxControls.add({staticLabel:"Center Content", checkedState:true});
var myFitFrameToContentCheckbox = checkboxControls.add({staticLabel:"Frame to Content", checkedState:true});
}
}
with(dialogRows.add()){
var myRemoveEmptyFramesCheckbox = checkboxControls.add({staticLabel:"Remove Empty Frames:", checkedState:true});
}
}
}
with(dialogRows.add()){
staticTexts.add({staticLabel:""});
}
var myLabelsGroup = enablingGroups.add({staticLabel:"Labels", checkedState:true});
with (myLabelsGroup){
with(dialogColumns.add()){
//Label type
with(dialogRows.add()){
with(dialogColumns.add()){
staticTexts.add({staticLabel:"Label Type:", minWidth:myLabelWidth});
}
with(dialogColumns.add()){
var myLabelTypeDropdown = dropdowns.add({stringList:["File name", "File path", "XMP description", "XMP author"], selectedIndex:0});
}
}
//Text frame height
with(dialogRows.add()){
with(dialogColumns.add()){
staticTexts.add({staticLabel:"Label Height:", minWidth:myLabelWidth});
}
with(dialogColumns.add()){
var myLabelHeightField = measurementEditboxes.add({editValue:24, editUnits:MeasurementUnits.points});
}
}
//Text frame offset
with(dialogRows.add()){
with(dialogColumns.add()){
staticTexts.add({staticLabel:"Label Offset:", minWidth:myLabelWidth});
}
with(dialogColumns.add()){
var myLabelOffsetField = measurementEditboxes.add({editValue:0, editUnits:MeasurementUnits.points});
}
}
//Style to apply
with(dialogRows.add()){
with(dialogColumns.add()){
staticTexts.add({staticLabel:"Label Style:", minWidth:myLabelWidth});
}
with(dialogColumns.add()){
var myLabelStyleDropdown = dropdowns.add({stringList:myStyleNames, selectedIndex:0});
}
}
//Layer
with(dialogRows.add()){
with(dialogColumns.add()){
staticTexts.add({staticLabel:"Layer:", minWidth:myLabelWidth});
}
with(dialogColumns.add()){
var myLayerDropdown = dropdowns.add({stringList:myLayerNames, selectedIndex:0});
}
}
}
}
var myResult = myDialog.show();
if(myResult == true){
var myNumberOfRows = myNumberOfRowsField.editValue;
var myNumberOfColumns = myNumberOfColumnsField.editValue;
var myRemoveEmptyFrames = myRemoveEmptyFramesCheckbox.checkedState;
var myFitProportional = myFitProportionalCheckbox.checkedState;
var myFitCenterContent = myFitCenterContentCheckbox.checkedState;
var myFitFrameToContent = myFitFrameToContentCheckbox.checkedState;
var myHorizontalOffset = myHorizontalOffsetField.editValue;
var myVerticalOffset = myVerticalOffsetField.editValue;
var myMakeLabels = myLabelsGroup.checkedState;
var myLabelType = myLabelTypeDropdown.selectedIndex;
var myLabelHeight = myLabelHeightField.editValue;
var myLabelOffset = myLabelOffsetField.editValue;
var myLabelStyle = myStyleNames[myLabelStyleDropdown.selectedIndex];
var myLayerName = myLayerNames[myLayerDropdown.selectedIndex];
myDialog.destroy();
myMakeImageCatalog(myFiles, myNumberOfRows, myNumberOfColumns, myRemoveEmptyFrames, myFitProportional, myFitCenterContent, myFitFrameToContent, myHorizontalOffset, myVerticalOffset, myMakeLabels, myLabelType, myLabelHeight, myLabelOffset, myLabelStyle, myLayerName);
}
else{
myDialog.destroy();
}
}
}
function myGetParagraphStyleNames(myDocument){
var myStyleNames = new Array;
var myAddLabelStyle = true;
for(var myCounter = 0; myCounter < myDocument.paragraphStyles.length; myCounter++){
myStyleNames.push(myDocument.paragraphStyles.item(myCounter).name);
if (myDocument.paragraphStyles.item(myCounter).name == "Labels"){
myAddLabelStyle = false;
}
}
if(myAddLabelStyle == true){
myStyleNames.push("Labels");
}
return myStyleNames;
}
function myMakeImageCatalog(myFiles, myNumberOfRows, myNumberOfColumns, myRemoveEmptyFrames, myFitProportional, myFitCenterContent, myFitFrameToContent, myHorizontalOffset, myVerticalOffset, myMakeLabels, myLabelType, myLabelHeight, myLabelOffset, myLabelStyle, myLayerName){
var myPage, myFile, myCounter, myX1, myY1, myX2, myY2, myRectangle, myLabelStyle, myLabelLayer;
var myParagraphStyle, myError;
var myFramesPerPage = myNumberOfRows * myNumberOfColumns;
var myDocument = app.documents.add();
myDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.points;
myDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.points;
var myDocumentPreferences = myDocument.documentPreferences;
var myNumberOfFrames = myFiles.length;
var myNumberOfPages = Math.round(myNumberOfFrames / myFramesPerPage);
if ((myNumberOfPages * myFramesPerPage) < myNumberOfFrames){
myNumberOfPages++;
}
//If myMakeLabels is true, then add the label style and layer if they do not already exist.
if(myMakeLabels == true){
try{
myLabelLayer = myDocument.layers.item(myLayerName);
//if the layer does not exist, trying to get the layer name will cause an error.
myLabelLayer.name;
}
catch (myError){
myLabelLayer = myDocument.layers.add({name:myLayerName});
}
//If the paragraph style does not exist, create it.
try{
myParagraphStyle = myDocument.paragraphStyles.item(myLabelStyle);
myParagraphStyle.name;
}
catch(myError){
myDocument.paragraphStyles.add({name:myLabelStyle});
}
}
myDocumentPreferences.pagesPerDocument = myNumberOfPages;
myDocumentPreferences.facingPages = false;
var myPage = myDocument.pages.item(0);
var myMarginPreferences = myPage.marginPreferences;
var myLeftMargin = myMarginPreferences.left;
var myTopMargin = myMarginPreferences.top;
var myRightMargin = myMarginPreferences.right;
var myBottomMargin = myMarginPreferences.bottom;
var myLiveWidth = (myDocumentPreferences.pageWidth - (myLeftMargin + myRightMargin)) + myHorizontalOffset
var myLiveHeight = myDocumentPreferences.pageHeight - (myTopMargin + myBottomMargin)
var myColumnWidth = myLiveWidth / myNumberOfColumns
var myFrameWidth = myColumnWidth - myHorizontalOffset
var myRowHeight = (myLiveHeight / myNumberOfRows)
var myFrameHeight = myRowHeight - myVerticalOffset
var myPages = myDocument.pages;
// Construct the frames in reverse order. Don't laugh--this will
// save us time later (when we place the graphics).
for (myCounter = myDocument.pages.length-1; myCounter >= 0; myCounter--){
myPage = myPages.item(myCounter);
for (var myRowCounter = myNumberOfRows; myRowCounter >= 1; myRowCounter--){
myY1 = myTopMargin + (myRowHeight * (myRowCounter-1));
myY2 = myY1 + myFrameHeight;
for (var myColumnCounter = myNumberOfColumns; myColumnCounter >= 1; myColumnCounter--){
myX1 = myLeftMargin + (myColumnWidth * (myColumnCounter-1));
myX2 = myX1 + myFrameWidth;
myRectangle = myPage.rectangles.add(myDocument.layers.item(-1), undefined, undefined, {geometricBounds:[myY1, myX1, myY2, myX2], strokeWeight:0, strokeColor:myDocument.swatches.item("None")});
}
}
}
// Because we constructed the frames in reverse order, rectangle 1
// is the first rectangle on page 1, so we can simply iterate through
// the rectangles, placing a file in each one in turn. myFiles = myFolder.Files;
for (myCounter = 0; myCounter < myNumberOfFrames; myCounter++){
myFile = myFiles[myCounter];
myRectangle = myDocument.rectangles.item(myCounter);
myRectangle.place(File(myFile));
myRectangle.label = myFile.fsName.toString();
//Apply fitting options as specified.
if(myFitProportional){
myRectangle.fit(FitOptions.proportionally);
}
if(myFitCenterContent){
myRectangle.fit(FitOptions.centerContent);
}
if(myFitFrameToContent){
myRectangle.fit(FitOptions.frameToContent);
}
//Add the label, if necessary.
if(myMakeLabels == true){
myAddLabel(myRectangle, myLabelType, myLabelHeight, myLabelOffset, myLabelStyle, myLayerName);
}
}
if (myRemoveEmptyFrames == 1){
for (var myCounter = myDocument.rectangles.length-1; myCounter >= 0;myCounter--){
if (myDocument.rectangles.item(myCounter).contentType == ContentType.unassigned){
myDocument.rectangles.item(myCounter).remove();
}
else{
//As soon as you encounter a rectangle with content, exit the loop.
break;
}
}
}
}
//Function that adds the label.
function myAddLabel(myFrame, myLabelType, myLabelHeight, myLabelOffset, myLabelStyleName, myLayerName){
var myDocument = app.documents.item(0);
var myLabel;
var myLabelStyle = myDocument.paragraphStyles.item(myLabelStyleName);
var myLabelLayer = myDocument.layers.item(myLayerName);
var myLink =myFrame.graphics.item(0).itemLink;
//Label type defines the text that goes in the label.
switch(myLabelType){
//File name
case 0:
myLabel = myLink.name;
break;
//File path
case 1:
myLabel = myLink.filePath;
break;
//XMP description
case 2:
try{
myLabel = myLink.linkXmp.description;
if(myLabel.replace(/^\s*$/gi, "")==""){
throw myError;
}
}
catch(myError){
myLabel = "No description available.";
}
break;
//XMP author
case 3:
try{
myLabel = myLink.linkXmp.author
if(myLabel.replace(/^\s*$/gi, "")==""){
throw myError;
}
}
catch(myError){
myLabel = "No author available.";
}
break;
}
var myX1 = myFrame.geometricBounds[1];
var myY1 = myFrame.geometricBounds[2] + myLabelOffset;
var myX2 = myFrame.geometricBounds[3];
var myY2 = myY1 + myLabelHeight;
var myTextFrame = myFrame.parent.textFrames.add(myLabelLayer, undefined, undefined,{geometricBounds:[myY1, myX1, myY2, myX2], contents:myLabel});
myTextFrame.textFramePreferences.firstBaselineOffset = FirstBaseline.leadingOffset;
myTextFrame.parentStory.texts.item(0).appliedParagraphStyle = myLabelStyle;
}
// ADDED BY UWE LAUBENDER :
function sortFileNames( a,b )
{
// incoming a and b are files.
// We need strings to compare, not files!
a = a.name;
b = b.name;
// IDEA BY MARTIN FISCHER FROM www.hilfdirselbst.ch
// http://www.martinfischer.de/
var myRegExp = new RegExp('^\\d+', );
var aObj = {num: a.match(myRegExp) != null ? a.match(myRegExp)[0] : '_', string: a.replace(/^\d+/, '')};
var bObj = {num: b.match(myRegExp) != null ? b.match(myRegExp)[0] : '_', string: b.replace(/^\d+/, '')};
// a and b are fully numeric :
if (aObj.string =='' && bObj.string == ''){ return a - b };
// the numeric parts of a and b are equal :
if (aObj.num == bObj.num ){ return aObj.string.toLowerCase() > bObj.string.toLowerCase() };
// the numeric part of a is greater than the numeric part of b :
if (aObj.num > bObj.num ){ return 1 };
};
Hope, it will work as expected on Mac OS X High Sierra.
Regards,
Uwe
Copy link to clipboard
Copied
Uwe, you are the man! Many thanks! It works! ... Testet with 555 photos
But I cannot believe, that I am the only person working with a Mac and High Sierra who needs this script. It was not easy to find a solution for me. Now its time for a beer - Prost!
Copy link to clipboard
Copied
… Now its time for a beer - Prost!
Very good idea!
Beer gardens are open here in Würzburg.
I'm glad, it's working for you.
Best,
Uwe
Copy link to clipboard
Copied
hi,
same problem here. Could anyone tell me how to import the script into indesign. sorry I am also a photographer, no computer expert.
just copy ??
Copy link to clipboard
Copied
Follow the instructions given in the link below
-Manan
Copy link to clipboard
Copied
Thank you for this! - I found helpful too!
My other Pet peeve is that I ALWAYS have to go back and add CAPS versions to the filetype line:
[".jpg", ".jpeg", ".eps", ".ps", ".pdf", ".tif", ".tiff", ".gif", ".psd", ".ai"]
If those CASE lines are meant to cover the .JPGs or .JPEGs they don't seem to ever work for me.
Copy link to clipboard
Copied
Thank you Uwe! The UXP script sorted, and it worked for me for a while, but recently, it stopped. Your tweak of the jsx is what I've been looking for.
Copy link to clipboard
Copied
Thank you very much
I have tested it and it works perfectly.
Thank you Uwe
Copy link to clipboard
Copied
This correctly sorts the images on InDesign 2023 (v13.0) on MacOS 12.6.5.
Copy link to clipboard
Copied
Laubender schrieb
Search the forums and a thread comes up with some sorting suggestions here:
imageCatalog image sorting before import
Regards,
Uwe
this unfortunately doesn't solve the problem... still consists the alternative ways neither
Copy link to clipboard
Copied
Oh my goodness, it worked. Thank you very much, Uwe!
Copy link to clipboard
Copied
Hi Uwe,
Do you have any ideas how I might solve the syntax error that InDesign is giving when using this code? Not sure if something has just changed between the 2018 and 2020 versions of indd causing it to error, but I'm not sure how to fix it. Your code seems like it's exactly what I'm looking for! Thanks for any help you might be able to give.
Copy link to clipboard
Copied
Hi Holly,
must have missed your post last year.
Hope you found the answer.
If not:
{\rtf at the beginning of the source of the error message in your screenshot is telling me:
You copied the code to an app, perhaps TextEdit, where formatting was turned on and saved the file formatted.
jsx files require text only without any formatting. Switch the mode in TextEdit to Text Only, then do a new file, paste the code from above and only then save with the *.jsx suffix.
Regards,
Uwe Laubender
( ACP )
Copy link to clipboard
Copied
UWE! thank you for your work. If you have a venmo or something I would like to send you a contribution. The SCRIPT WORKED FOR ME — Catalina Mac OS, INDD 2020. I had almost given up hope. Bless you.