Copy link to clipboard
Copied
Hello everyone!
Is there someone able to help me with a script?
My file has 16 pages, each page has 20-30 frames with a number written inside (i.e. 123456), that is part of the name of the image that has to be placed inside.
I need to replace the texts with actual images and I found multiple scripts that do this. The problem is that images are saved in a photo archive, with multiple sub-folders, and the images are named not only with the numeric code but even with text (i.e. RedBlueCar_year1990_123456.jpg)
Thank you in advance for your help and for your time!
Copy link to clipboard
Copied
Have you looked into using Data Merge to do this? Otherwise, you'd probably need to pay a developer to write something custom for this.
Copy link to clipboard
Copied
Hi brianp311
I have already tried with Data Merge but it does not work because the images are not in the same folder (I have sub folders too) and it actually recognize the full name, not just a part of it.
I found an interesting script that does most of the job I need, but it replaces images only if their names match exactly with the written text in the text frame.
Copy link to clipboard
Copied
Data Merge can look into multiple folders as long as you provide the full path to each image.
Do you want to post the promising script? It could just be a matter of setting up a recursive function to check within each subfolder of a given folder.
Copy link to clipboard
Copied
Yes sure!
here where I found the script. the name of the script is Place Images
the author is Kasyan Servetsky
http://kasyan.ho.ua/indesign/image/place_images.html
and here is the script
Copy link to clipboard
Copied
Hi Im trying to use this script but I received
No idea what is happening
Thank you
Copy link to clipboard
Copied
Some questions
-Manan
Copy link to clipboard
Copied
Try the following script, change the path to the base folder within which the file needs to be searched. It will search for the first file within this folder or its subfolders and use the first file whose name contains the numerical value of the textframes in the document. The images are placed as inline image and all the numeric content of every frame is considered a potential filename
function findAndReplace(foldername)
{
app.findGrepPreferences.findWhat = "\\d+"
var nameList = app.activeDocument.findGrep(true)
for(var i = nameList.length - 1; i >= 0; i--)
{
var fileName = nameList[i].contents
var f = findFile(foldername, fileName)
if(f != undefined)
nameList[i].place(File(f))
}
app.findGrepPreferences = NothingEnum.nothing;
}
function findFile(foldername, name)
{
var folder = new Folder(foldername)
var f = folder.getFiles()
for(var i = 0; i < f.length; i++)
{
if(f[i].constructor.name == "Folder")
{
var r = findFile(f[i], name)
if(r != undefined)
return r
}
var fName = decodeURI(f[i].name)
if(fName.indexOf(name) != -1)
return f[i].fsName
}
}
findAndReplace("/Users/manan/Desktop/test") //Change this to your base folder
-Manan
Copy link to clipboard
Copied
Hi Manan,
thanks for your concern to my issue!
To answer your previous questions:
I've tried your script and it's almost there. Could it be possible to limit the research to any 4 or more numbers within the first _ and the file extension .jpg? And don't place the image as an inline image but replace the entire textframe?
I could give you some visual example if you need.
many thanks
Copy link to clipboard
Copied
So if we take an example of your string i.e. RedOldCar1990_123456_789789.jpg
Then the code should find files named like
a_123456_789789.jpg
345_123456_789789fgfhgfhfh.jpg
Also could you please elaborate the following with an example
Could it be possible to limit the research to any 4 or more numbers within the first _ and the file extension .jpg
-Manan
Copy link to clipboard
Copied
The code should search only from the first _ to the extension, nothing before the first "_"
so taking your example, not a_123456_789789.jpg but _123456_789789.jpg and not 345_123456_789789fgfhgfhfh.jpg but only _123456_789789fgfhgfhfh.jpg
I try to explain the second thing. The code should find only files named with 4 or more numbers between the _ and the .jpg. So for i.e. the code should not consider a file named abcd_123.jpg because there are just three caracters within _ and .jpg; On the contrary, It should find a files named abcd_1234.jpg or abcd_12345.jpg and so on.
I could give you some real examples, so maybe it is more clear, just let me know.
thanks
Copy link to clipboard
Copied
What happens for these conditions
abc_4_d_5_7_3_abc.jpg //The total numbers of characters between first _ and jpg are 4 but they are not continuous.
-Manan
Copy link to clipboard
Copied
you're right. the 4 characters have to be continuous, however, a case like that it won't happen, 'cause all the images in the archive should have been saved with the same "pattern" such as namenamename_123456.jpg
I'm going to try your code and I'll tell you
Copy link to clipboard
Copied
Based on what i understood i have modified the code, give it a spin and see how it behaves
function checkNumberCount(str)
{
var reg = new RegExp("\\d")
var count = 0
var retval = reg.exec(str)
while(retval)
{
count++
if(count == 4)
return true
str = str.substr(retval.index + 1)
retval = reg.exec(str)
}
return false
}
function findAndReplace(foldername)
{
app.findGrepPreferences.findWhat = "(_.*\\.jpg)$"
var nameList = app.activeDocument.findGrep(true)
for(var i = nameList.length - 1; i >= 0; i--)
{
var fileName = nameList[i].contents
if(!checkNumberCount(fileName))
continue;
var f = findFile(foldername, fileName)
if(f != undefined)
nameList[i].parentTextFrames[0].place(File(f))
}
app.findGrepPreferences = NothingEnum.nothing;
}
function findFile(foldername, name)
{
var folder = new Folder(foldername)
var f = folder.getFiles()
for(var i = 0; i < f.length; i++)
{
if(f[i].constructor.name == "Folder")
{
var r = findFile(f[i], name)
if(r != undefined)
return r
}
var fName = decodeURI(f[i].name)
if(fName.indexOf(name) != -1)
return f[i].fsName
}
}
findAndReplace("/Users/manan/Desktop/test") //Change this to your base folder
-Manan
Copy link to clipboard
Copied
it doesn't run
Copy link to clipboard
Copied
Sorry I had used png instead of jpg as the extension, try again I have edited the code above
-Manan
Copy link to clipboard
Copied
It works!! I have just to adjust a couple more things but the code runs!
Thanks Manan, thank you very very much
Copy link to clipboard
Copied
hi Manan,
your code checks the folder every time by this command:
findFile(foldername, fileName)
...
folder.getFiles()
this is bad because a folder can contain 10000 or more files,
I would first get a list of files and then place them in frames,
something like this:
function set_frames(){
for(var i = 0; i < tf.length; i++){
if(tf[i].contents in files){
tf[i].place(files[tf[i].contents])
}
}
}
function get_files(path){
var folder = Folder(path).getFiles()
for(var i = 0; i < folder.length; i++){
if(File(folder[i]).constructor.name == 'Folder'){get_files(folder[i])}
else{
var f = File(folder[i]).fsName
if(f.split('.').slice(-1)[0] == extension){
var cur = f.split('\\').slice(-1)[0].split(delimiter).slice(1).join(delimiter).match(pattern)
if(cur != null){
for(var ii = 0; ii < cur.length; ii++){
files[cur[ii]] = f
}
}
}
}
}
}
var tf = app.activeDocument.textFrames.everyItem().getElements()
var files = {}
var pattern = /\d{4,}/gi
var delimiter = '_'
var extension = 'jpg'
get_files('c:/job/test/')
app.doScript('set_frames()', ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'set_frames')
Copy link to clipboard
Copied
Yes, you have a point, but it depends upon the incoming data, for example, your code would always parse the whole folder and its subfolders once. So for 1000 files, you ran the loop 1000 times for making a collection of files and then a loop to replace, so the order is 1000 + n. The code complexity is constant.
In my case, I run the loop to find the first file that matches and return(note I return as soon as I find the result and abort the function). So if the files are found early in the iteration, my approach would lead to much faster execution. It could be made more efficient if I made a collection of found filepaths for the cases where some file is used multiple times in different text frames. So it all depends upon the nature of data arrangement, your code would be balanced in general, mine would be more extreme either way(slowness/speed).
-Manan
Copy link to clipboard
Copied
No. Folder(path).getFiles() has already received a list of files, it can take minutes or even tens of minutes.
Imagine you are working with a folder containing over 200k images (I worked, I know how long it will take), it makes no sense to execute this command every time
Copy link to clipboard
Copied
Yes, now you point the exact problem that would be a bottleneck. In that case, I will still prefer to use my approach, but as you rightly pointed to just call getFiles once. So the following changes need to be done for my solution
I hope now we can agree to each other's approach 🙂
-Manan