Copy link to clipboard
Copied
Hi all,
This seems to be something I can't find an easy answer to.
I'm trying to take the filename of an active document, and use it to search through all open documents and find a close match.
For example:
Client-BDA_spec-sheet-US_v1.indd <- if this is the active document
Client-TRA_spec-sheet-US_v2.indd
Client-BDC_spec-sheet-A4_v4.indd
Client-BDA_spec-sheet-A4_v1.indd <- the script then finds this open document (perhaps making it active)
Client-TRA_spec-sheet-A4_v1.indd
Client-BDC_spec-sheet-US_v2.indd
Don't laugh but this is as far I got
var doc = app.activeDocument;
var docName = doc.name;
function findMatch(){
for(var i = 0; i < app.documents.length; i++){
// I GIVE UP!!!
}
}
Any help is much appreciated, as always. J
And here's another version that will toggle back and forth between A4 and US versions. You configure it with the two arrays you pass as arguments. findWhat and changeTo can be arrays in this version.
- Mark
var doc = app.activeDocument,
myA4Doc = getDocumentByNameFindChange(doc, [/-US/, /-A4/], ['-A4', '-US'], /_v\d+/);
if (myA4Doc != undefined)
app.activeDocument = myA4Doc;
/**
* Make a document active, based on its
* name, relative to another document.
*
* findWhat and changeTo
...
Copy link to clipboard
Copied
Assuming that you want to match the documents for Client-BDA, you might try this after you define docName:
var clientName = docName.split("_")[0];
which will be the first piece of the name of the active document. In your loop, then, you also split the names of the other open documents to find a match.
Not sure what you want to do if there are multiple matches, but item [1] of docName.split will be a string starting with "spec-sheet" and item [2] will be the version number. So you could use a second and third loop to check for matches in the second and third pieces of the name.
Hope this helps,
Bob
Copy link to clipboard
Copied
Had a brainwave and got it working, albeit not quite in the same way as described in my initial post.
@m1b gave me a solution to a very similar problem, which I've used to get this one working.
#target InDesign
var doc = app.activeDocument;
var docName = doc.name;
var docName = getDocumentByRegex(/-A4/g);
if (docName != undefined)
app.activeDocument = docName;
function getDocumentByRegex(regex) {
for (var i = 0; i < app.documents.length; i++) {
var doc = app.documents[i];
if (regex.test(doc.name))
return doc;
}
}
Copy link to clipboard
Copied
Hi @JustyR, I'm a little worried that the function I supplied for the other question might fail in this case. It will find the *first* document with -A4, which might not always match the client code of your current document. How about this function? Can you see what it does? Let me know if you have questions.
- Mark
var doc = app.activeDocument;
var myA4Doc = getDocumentByNameFindChange(doc, /-US/, '-A4');
if (myA4Doc != undefined)
app.activeDocument = myA4Doc;
/**
* Make a document active, based on its
* name, relative to another document.
* @param {activeDoc} activeDoc - a Document
* @param {RegExp} findWhat - regex to find with
* @param {String} changeTo - text to change to
*/
function getDocumentByNameFindChange(activeDoc, findWhat, changeTo) {
// store a version of the active doc's name
// but with the replacement text
var findThisName = activeDoc.name.replace(findWhat, changeTo);
for (var i = 0; i < app.documents.length; i++) {
var doc = app.documents[i];
// don't want activeDoc
if (doc === activeDoc)
continue;
// check if name matches
if (doc.name == findThisName)
return doc;
}
// if flow gets to here
// no document was found
// so return nothing
}
Copy link to clipboard
Copied
Thanks Mark. I tried it but it didn't do anything (didn't switch to a matched doc). I wonder if it needs a more robust regex or even a split, like Bob suggested.
As shown in my first post, the first 3/4 of the filename changes but will always end with either "-US-v#.indd" or "-A4-v#.indd". So it's trying to find a match for the first part that counts, something like this regex (/(.*)(?=-US|A4)/i)
J
Copy link to clipboard
Copied
Sorry @JustyR, I must have misunderstood your use-case.
I thought you wanted to make the A4 version of the "same" active US document active. That is what your diagram says to me, so:
• if Client-BDA_spec-sheet-US_v1.indd is active then you want Client-BDA_spec-sheet-A4_v1.indd.
• if Client-BDC_spec-sheet-US_v2.indd is active then you want Client-BDC_spec-sheet-A4_v2.indd.
This is what my code does (excepting for bugs, which are likely!) when I run it. You didn't mention the v1, v2 part, which might be a consideration. At the moment it only matches with the same version number—maybe that's why it didn't work for you? I might need a better understanding of what you are trying to achieve. Oh well.
- Mark
Copy link to clipboard
Copied
No need to apologise. I'm indebted to you guys for helping.
I think you've understood it.
There are two versions of each document. One in A4, one in US Letter.
The naming convention is like this:
[client]-[product]-Spec Sheet-[size]_[version].indd
For example:
IR XRL-Spec Sheet-A4_v1.indd <- If this is the ACTIVE document
IR XRL-Spec Sheet-US_v2.indd <- the script finds this document
IR GHU2400-Spec Sheet-A4_v1.indd
IR GHU2400-Spec Sheet-US_v1.indd
IR Adventurer-Spec Sheet-A4_v1.indd
IR Adventurer-Spec Sheet-US_v1.indd
In the example above, if stripped down, the target doc is XRL A4 and the script then finds its sibling XRL US.
Does that make sense?
J
Copy link to clipboard
Copied
Meant to say active doc not target doc. I keep rushing and making typos. Wish this forum had an edit button.
Copy link to clipboard
Copied
Hi @JustyR
The Levenshtein distance could provide a more 'agnostic' approach to your question. You just have to filter out the suffix
/_spec-sheet-[a-z0-9]+_v\d+\.indd$/i
before processing, as this part should be ignored by the algorithm (if I understand properly your last comment.)
Here is a possible implementation of the whole thing:
https://github.com/indiscripts/IdGoodies/blob/master/full/DocShowClosestByName.jsx
Not sure it answers your original question but it was fun to code 😉
Best,
Marc
Copy link to clipboard
Copied
Hi, Marc, thanks for taking the time to write something so complete.
As you mentioned, it doesn't quite fit my needs though. It does switch docs when it finds a match but it's a bit too forgiving.
For example, if I run the script with the following four files open:
IR XRL-Spec Sheet-A4_v1.indd <- ACTIVE document
IR XRL-Spec Sheet-US_v2.indd <- target doc it is supposed to switch to
IR XRT-Spec Sheet-A4_v1.indd <- but it switches to this one instead
IR XRT-Spec Sheet-US_v1.indd
It's as though the const MY_DROP_REGEX is being ignored.
J
Copy link to clipboard
Copied
Ah I see now. It is the v1 or v2 that is a problem here. You are now saying that it's okay to match a v2 with a v1 document, so that's likely why my script didn't find it. Here's an updated version. I just added a new argument: ignoreThis, which is a regex that will be completely ignored (it'll simply be removed before the comparison) so now it'll match documents that have differing version numbers with this regex /_v\d+/ . I hope I've understood now!
- Mark
var doc = app.activeDocument,
myA4Doc = getDocumentByNameFindChange(doc, /-US/, '-A4', /_v\d+/);
if (myA4Doc != undefined)
app.activeDocument = myA4Doc;
/**
* Make a document active, based on its
* name, relative to another document.
*
* @Param {activeDoc} activeDoc - a Document
* @Param {RegExp} findWhat - regex to find with
* @Param {String} changeTo - text to change to
* @Param {RegExp} ignoreThis - regex to ignore
* @Returns {Document} the matched Document
*/
function getDocumentByNameFindChange(activeDoc, findWhat, changeTo, ignoreThis) {
// store a version of the active doc's name
// but with the replacement text
var findThisName = activeDoc.name
.replace(findWhat, changeTo)
// and remove the ignored part
.replace(ignoreThis, '');
for (var i = 0; i < app.documents.length; i++) {
var doc = app.documents[i];
// don't want activeDoc
if (doc === activeDoc)
continue;
// check if name matches (minus the ignored part)
if (doc.name.replace(ignoreThis, '') == findThisName)
return doc;
}
// if flow gets to here
// no document was found
// so return nothing
}
Copy link to clipboard
Copied
And here's another version that will toggle back and forth between A4 and US versions. You configure it with the two arrays you pass as arguments. findWhat and changeTo can be arrays in this version.
- Mark
var doc = app.activeDocument,
myA4Doc = getDocumentByNameFindChange(doc, [/-US/, /-A4/], ['-A4', '-US'], /_v\d+/);
if (myA4Doc != undefined)
app.activeDocument = myA4Doc;
/**
* Make a document active, based on its
* name, relative to another document.
*
* findWhat and changeTo can be Arrays
* such that if findWhat[i] matches active
* document name then switch to document
* named after doing changeTo[i].
* @Param {activeDoc} activeDoc - a Document
* @Param {Array[RegExp]} findWhat - regex to find with
* @Param {Array[String]} changeTo - text to change to
* @Param {RegExp} ignoreThis - regex to ignore
* @Returns {Document} the matched Document
*/
function getDocumentByNameFindChange(activeDoc, findWhat, changeTo, ignoreThis) {
var activeName = activeDoc.name,
index = 0;
// work out which findWhat is in document
if (findWhat.hasOwnProperty('0')) {
for (index = 0; index < findWhat.length; index++)
if (findWhat[index].test(activeName))
break;
}
else {
// just put them in an array so we
// can handle them the same later
findWhat = [findWhat];
changeTo = [changeTo]
}
// store a version of the active doc's name
// but with the replacement text
var findThisName = activeDoc.name
.replace(findWhat[index], changeTo[index])
// and remove the ignored part
.replace(ignoreThis, '');
for (var i = 0; i < app.documents.length; i++) {
var doc = app.documents[i];
// don't want activeDoc
if (doc === activeDoc)
continue;
// check if name matches (minus the ignored part)
if (doc.name.replace(ignoreThis, '') == findThisName)
return doc;
}
// if flow gets to here
// no document was found
// so return nothing
}
Copy link to clipboard
Copied
I tried both but neither switches to another open file. Hmmm, the plot thickens.
Copy link to clipboard
Copied
@m1b I got your second one (the one that switches) to work for me by changing the ignore regex on line 2 to
/-spec-sheet-.*/
Copy link to clipboard
Copied
Well it's really up to you to specify what needs to be ignored. The script can't guess your goal.
In terms of Levenshtein distance,
IR XRT-Spec Sheet-A4_v1.indd
is clearly closer to
IR XRL-Spec Sheet-A4_v1.indd
than
IR XRL-Spec Sheet-US_v2.indd.
Now if you set MY_DROP_REGEX to
/-Spec Sheet-[a-z0-9]+_v\d+\.indd$/
or even to /-.+\.indd$/
that should make a huge difference.
Marc
Copy link to clipboard
Copied
I've updated the regex to /-spec-sheet-.*-[A4]_v\d+\.indd$/ which is now more accurate.
However, if a filename has something like IR CNC1-spec-sheet-A4_v1.indd, it will match with IR CNC2-spec-sheet-A4_v1.indd
How can I get the script to take account of numbers in the first part of the filename?
Copy link to clipboard
Copied
That regex isn't right because [A4] means match any single A or 4. I also noticed that your capitalization isn't consistent so add the 'i' flag to the regex to make it case insensitive. Eg /spec-sheet-A4/i - Mark
Copy link to clipboard
Copied
BTW, It would save some time if you sent us a listing of all your *actual* file names. At the moment what you are saying doesn't match with the results you're getting. Also the regex you posted last doesn't make sense. The one I posted with my last script should work if you add the i flag to each regex. We'll get there!
- Mark