Copy link to clipboard
Copied
Hello again! I made a similar post a few days ago that helped me solve one problem, but unfortunately it created another, so I'm back.
Quick background: I have modified a script created by Kasyan (found here) that finds tags and replaces them with images. The main changes I made now have the script create an anchored text frame where the tag is found, find and insert the image file inline in the new text frame, and then grab the "Description" from the xmp link and insert it as text after the image.
The problem: The script runs beautifully so long as it is able to find the metadata it is looking for. I have tried to use try...catch() to look for the linkXmp.description, but I think I fundementally don't understand what to put in the "catch" area. I want it to just tell the script that the description is null so I can later use "else" to put a placeholder in the caption text frame.
(This might not be the best way to handle this - the image files that are returning empty definitely have the metadata there when I look at them in Bridge. Would you recommend a different way of grabbing the metadata, or error handling if it can't be found?)
What I'm trying: here is the small snippet that is causing problems for me:
try {
//get XMP Description
imgDescription = imgPath.linkXmp.description;
}
catch (err){
if (debug) $.writeln(err.message + ", line: " + err.line);
}
//add caption contents from XMP Description
finally{
if (imgDescription != null){
captionInsPts.contents = "\r" + imgDescription;
}
else {
captionInsPts.contents = "\r Description metadata not available";
}
}
The code: below is the meat of the script where I made most of the changes. Most of the script outside of this section is the same as the original script by Kasyan, linked above so you can compare. I have attached the full script in case the problem cannot be found in the excerpt below:
if(imgFile != null) {
//remove figure tag from text
foundItem.remove();
story.recompose();
//create caption frame
imgCaption = story.insertionPoints[insPtIndex].textFrames.add();
//set position and size of the caption frame
imgCaption.geometricBounds = [imgCaption.geometricBounds[0],
imgCaption.geometricBounds[1],
imgCaption.geometricBounds[2],
imgCaption.geometricBounds[1] + maxWidth ];
//insert container for image file
container = imgCaption.insertionPoints[0].rectangles.add();
currentStyle = container.appliedObjectStyle;
captionInsPts = imgCaption.insertionPoints[-1]
//set position and size of image file container
gb = container.geometricBounds;
width = gb[3] - gb[1];
height = gb[2] - gb[0];
container.geometricBounds = [container.geometricBounds[0],
container.geometricBounds[1],
gb[0] + maxHeight,
gb[3] ];
container.geometricBounds = [container.geometricBounds[0],
container.geometricBounds[1],
container.geometricBounds[2],
container.geometricBounds[1] + maxWidth ];
//place figure image
img = container.place(imgFile)[0];
//set frame fitting options for image
if (set.fitOption > 1) {
container.fit(fitOptions[set.fitOption - 2]);
if (set.fitFrameToContents && (set.fitOption == 6 || set.fitOption == 7)) {
container.fit(FitOptions.FRAME_TO_CONTENT);
}
}
var imgPath = img.itemLink;
//find and place metadata as caption
try {
//get XMP Description
imgDescription = imgPath.linkXmp.description;
}
catch (err){
if (debug) $.writeln(err.message + ", line: " + err.line);
}
//add caption contents from XMP Description
finally{
if (imgDescription != null){
captionInsPts.contents = "\r" + imgDescription;
}
else {
captionInsPts.contents = "\r Description metadata not available";
}
}
//finalize styles
imgCaption.applyObjectStyle(currentStyle);
imgCaption.clearObjectStyleOverrides ();
container.applyObjectStyle(app.activeDocument.objectStyleGroups.itemByName("Figures"));
container.clearObjectStyleOverrides ();
count++;
}
else {
logErrArr.push(figureTagID + " - the file doesn't exist." + " - page " + ((pageNumber != null) ? pageNumber : "N/A"));
}
Hi @Bridgette.Is.Enthusiastic, normally you would do something like this:
var imgPath = img.itemLink;
var imgDescription = undefined;
try {
imgDescription = imgPath.linkXmp.description;
if (imgDescription)
captionInsPts.contents = "\r" + imgDescription;
}
catch (err) {
if (debug)
$.writeln(err.message + ", line: " + err.line);
captionInsPts.contents = "\r Description metadata not available";
}
So, if no error is thrown (and if the imgDescription has any
...Okay I've had a look through the script you posted. Here's my thoughts.
1. Remove the massive try/catch in the Main function, so you can see actual errors if they arise. Try/catch should only be used in situations where you are more-or-less predicting errors that you are sure you don't care about. So clear line 39 and lines 193-196. (I say clear, rather than delete, because I'll be referring to line numbers later, so keep them.) Try/catch blocks should be short, and specific to a particular op
...Copy link to clipboard
Copied
Hi @Bridgette.Is.Enthusiastic, normally you would do something like this:
var imgPath = img.itemLink;
var imgDescription = undefined;
try {
imgDescription = imgPath.linkXmp.description;
if (imgDescription)
captionInsPts.contents = "\r" + imgDescription;
}
catch (err) {
if (debug)
$.writeln(err.message + ", line: " + err.line);
captionInsPts.contents = "\r Description metadata not available";
}
So, if no error is thrown (and if the imgDescription has any content) it will set the contents they way you want.
I couldn't tell from your code whether this is actually going to solve your problem though. Let us know if it helped.
- Mark
P.S. You don't need the `finally` block unless you want to do something no matter if error occurred or not, and when your catch block returns control or throws an error deliberately. (This is more advanced so feel free to ignore.)
Copy link to clipboard
Copied
thanks for your time!
I pulled everything I could out of the try...catch() because I kept running into issues with the variables inside of it. The code you provided resulted in the error "object is invalid" for this line:
captionInsPts.contents = "\r Description metadata not available";
even though "captionInsPts" works fine in the "try" part of the code. This was one of the many issues I ran into trying to set up error handling for this script - all something along the lines of "this part works fine outside of these catch brackets, but now that they're in here I have no idea what they are".
Copy link to clipboard
Copied
Hi @Bridgette.Is.Enthusiastic, okay please try this: After this line
captionInsPts = imgCaption.insertionPoints[-1];
add this:
if (!captionInsPts.isValid)
alert('captionInsPts is not valid.');
My guess is that this alert will trigger. If I'm right, then you need to handle a case where the imgCaption has no insertionPoints. Something like this:
if (!captionInsPts.isValid)
continue;
Maybe that will be enough for you to experiment? Or I've guessed wrong and the issue is something else!
- Mark
Copy link to clipboard
Copied
when I add that line of code in where you specified, I get an alert that says "Critical error: The requested action could not be completed because the object no longer exists., line: 142" which is referring this line of code in the "catch" area again:
captionInsPts.contents = "\r Description metadata not available";
using the other code instead (the "continue") resulted in the same error.
Copy link to clipboard
Copied
Okay I've had a look through the script you posted. Here's my thoughts.
1. Remove the massive try/catch in the Main function, so you can see actual errors if they arise. Try/catch should only be used in situations where you are more-or-less predicting errors that you are sure you don't care about. So clear line 39 and lines 193-196. (I say clear, rather than delete, because I'll be referring to line numbers later, so keep them.) Try/catch blocks should be short, and specific to a particular operation. And while you are developing your script, better to have none at all, so you can have your finger on the pulse, so to speak.
2. Change UndoModes.FAST_ENTIRE_SCRIPT to UndoModes.ENTIRE_SCRIPT. FAST_ENTIRE_SCRIPT can be flaky and doesn't provide full support of Undo. I mostly avoid using it. In this case the script was getting a weird reference error (the object no longer exists, that you mentioned) until I changed to ENTIRE_SCRIPT.
3. Lines 100-112 are causing problems. Perhaps you want something like this:
gb = container.geometricBounds;
container.geometricBounds = [
gb[0],
gb[1],
gb[0] + maxHeight,
gb[1] + maxWidth
];
But note that even though the UI says "mm" units, the script makes no attempt to enforce them. So `maxHeight` of "40mm" is actually 40pts.
Other than that, there are parts to the script that I don't understand at a quick glance, but these points are the main issues I noticed. Let me know where you get to after this.
- Mark
Copy link to clipboard
Copied
YES!!! THANK YOU THANK YOU!!
I have been working on this script off and on for months and had only gotten it this far through sheer force of will. I've never coded before so every new element I needed to use I had to learn, and by the time I got to this part I just could not figure out why it wasn't working. Thank you so much - I needed this to work for a massive project we're actively working on, and now we are going to be able to meet our deadline.
When I made all three changes you suggested the code failed at the very end (i think when it tried to write the log) and this is the error I got:
Putting the "fast" back into UndoModes.FAST_ENTIRE_SCRIPT on that line came back with the same error, so it wasn't that. I took the "fast" back out and looked at the other changes.
I commented the giant "try...catch()" back in and then the script worked! I also put in my old geometric bounds to test that and the code still worked. So the issue was the UndoModes.FAST_ENTIRE_SCRIPT which needed to be changed to UndoModes.ENTIRE_SCRIPT. After confirming, I put the new geometric bounds back in because it does look much cleaner and I trust you if you say it's glitchy.
Unfortunately, it does create a new glitch where the the code breaks now if the file itself can't be found for the tag, instead of documenting the error in the log. BUT it doesn't undo all the successful tagged file placements - so it's really easy to see which tag caused the error, make sure it's tagged correctly or that the file is where it is supposed to be, and then run the script again, picking up where it left off. In short- I can work with this.
Thank you again SO much. I really appreciate you taking the time to look over the entire thing and finding these issues. 🙂
Copy link to clipboard
Copied
Hi @Bridgette.Is.Enthusiastic, first of all I'm very impressed that this is your first scripting project! You are going super! You have the right idea: to tackle a real project and keep at it until you win. 🙂
When you say you reinstated the try / catch and the script worked, what is really happening is you are ignoring an error. The problem is that unless you know exactly what that error is, you don't know if it is wise to ignore it. It may be the reason that sometimes the script fails, but you'll never know while the try / catch is intercepting the error.
According to your error dialog you posted, it is likely that you are using code that was previously inside a catch block, for example:
catch (err) {
if (debug) $.writeln(err.message + ", line: " + err.line);
}
The var `err` is provided by the catch statement, so if that isn't part of it, the `err` will be undefined and will throw an error if you try to use it. This must be a new addition because I can't find an undefined `err` var in your posted script.
- Mark
Copy link to clipboard
Copied
About the new glitch you mention, that is easily fixed. As you say, it means that the tag found doesn't match any images in the folder. We can add a check to see if `imgFile` is undefined:
imgFile = GetFile(imgFiles, figureTagID);
if (!imgFile) {
alert('No image for "' + figureTagID + '" on page ' + pageNumber + '.');
continue;
}
fileName = imgFile.displayName;
This is at line 73 in my listing.
- Mark