• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Find broken link name using placedItem name property

Community Beginner ,
Nov 06, 2020 Nov 06, 2020

Copy link to clipboard

Copied

Hello,

I'm trying to relink broken link with an input file path based on broken link name.

 

function updateLinks(inputFileName, inputFilePath)

{

   var activeDocument = app.activeDocument;

   for (var i = 0; i < activeDocument.placedItems.length; i++)

   {

       try {
          var file = activeDocument.placedItems[i].file;
           if (file && file.exists) {
             // Do nothing

          }
      }
      catch (e) {

         alert("Link is missing");
         var name = activeDocument.placedItems[i].name;
         if(name == inputFileName) {
             //Relink with input file path
            activeDocument.placedItems[i].relink(File(inputFilePath));

        }
     }
   }

}

 

placedItem.name is supposed to return image name right? this returns empty string

Any help is much appreciated!

 

TOPICS
Bug , Scripting

Views

1.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Nov 18, 2020 Nov 18, 2020

I'm don't have a perfect answer. Could you try this:

 

Check if item has a file property (ie. item.file doesn't throw an error) and get the file suffix from the file name.

var item = app.activeDocument.pageItems[0];
var suffix = getItemFileSuffix(item);
if (suffix != undefined) {
    // now you know the file format is not N/A
    if (suffix == 'jpg') {
        //do something?
    }
}

function getItemFileSuffix(item) {
    var suffix;
    if (item.typename == 'PlacedItem' || item.typename == 'Raste
...

Votes

Translate

Translate
Adobe
Guide ,
Nov 06, 2020 Nov 06, 2020

Copy link to clipboard

Copied

No.  placedItem.name is the name of the placedItem, as it appears in the layers panel.  If it returns an empty string, it's because it's unnamed.  If you want the name of the image file, try this

 

var name1 = activeDocument.placedItems[i].file.name.replace(/\.[^\.]+$/, "");

 

Also, don't call your variable "name".  Call it name1, for example. 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 06, 2020 Nov 06, 2020

Copy link to clipboard

Copied

for broken link placedItem.file doesn't exist, so unable to get image name using activeDocument.placedItems[i].file.name

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 07, 2020 Nov 07, 2020

Copy link to clipboard

Copied

Hi Janaki5FF1, I tried this out and yes you are right. I couldn't get the filepath when the link is broken. That's a huge shortcoming!

 

You can see the path in the XMP manifest, by choosing File > File Info menu item and clicking "Raw data". Scroll down to the <xmpMM:Manifest> element. Not pretty, but the path is there.

 

To work out how to edit it there, try looking at this question. Not sure if they got it to fully work though.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 07, 2020 Nov 07, 2020

Copy link to clipboard

Copied

Ok, I've had a play with it myself and put together a script that *should* relink broken placed images.

 

It currently just looks for them in a folder specified by the user, but you could modify it for your particular case. For example, instead of providing a new path, you might prefer to use a regex replacement on the broken path to fix it. This is just to demonstrate the concepts. Most of the info I got from the question I linked to above.

 

Here's the script. Not tested much at all, so please let me know how you go.

 

 

// ask for path - script will look for broken link files here
var newPath = Folder.selectDialog();
if (newPath != null) {
    newPath = newPath.fullName + "/";

    // 1. get all the placedItems
    var items = app.activeDocument.placedItems;

    // 2. get the paths of all the placedItems
    if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
    var xmp = new XMPMeta(app.activeDocument.XMPString);
    var paths = [];
    for (var i = 1; i <= xmp.countArrayItems(XMPConst.NS_XMP_MM, 'Manifest'); i++) {
        var xpath = 'xmpMM:Manifest[' + i + ']/stMfs:reference/stRef:filePath';
        paths.push(xmp.getProperty(XMPConst.NS_XMP_MM, xpath).value);
    }

    // 3. relink all the broken links
    var relinked = [], notFound = [];
    for (var i = 0; i < items.length; i++) {
        try {
            var triggerErrorIfBrokenLink = items[i].file;
        } catch (error) {
            var filename = paths[i].split('/').pop();
            var linkPath = newPath + filename;
            if (File(linkPath).exists) {
                items[i].file = new File(linkPath);
                relinked.push(filename);
            } else {
                notFound.push(filename);
            }
        }
    }

    // 4. report
    app.redraw();
    var report = relinked.length > 0 ? 'Relinked:\n' + relinked.join('\n') + '\n\n' : '';
    report += notFound.length > 0 ? 'Not found:\n' + notFound.join('\n') : '';
    alert(report);
}

 

 

(Aside: there must be a better way to handle a missing file property than I use here, ie. deliberately triggering an error, but I couldn't work it out in a hurry.)

 

Edit: I forgot to mention, this script relies on the fact that the placedItems are in the same order as the XMP manifest resources. I think it's a reasonable assumption, but if I'm wrong, the script will get the files mixed up! IMPORTANT: xmp data is only loaded when a file is opened, and isn't updated until it is again opened. So if you were to open your document, rearrange the placedItems in layer order, the script will get mixed up because the xmp data won't reflect the new order. In this case, save and close the document, then re-open, then run the script.

 

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 09, 2020 Nov 09, 2020

Copy link to clipboard

Copied

Hi Mark,

Thank you for the details.

As you know images can be either linked or embedded in Illustrator.

I haven't found linked or embedded information in XMP. It would be nice to get filepath of only placedItems (linked images) from XMP.

I'm trying to update broken file path for images which are linked.

I have tried the following and this works:

function updateLinks(inFileName, inFilePath) {

  // 1. get the paths of all the linked or embedded images
  if (ExternalObject.AdobeXMPScript == undefined) 
    ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
  
  //Read xmp string - You can see document XMP in Illustrator -> File-> File Info -> Raw Data
  var xmp = new XMPMeta(app.activeDocument.XMPString);

  //Read file paths from XMP - this returns file paths of both embedded and linked images
  var xmpFilePaths = [];
  for (var i = 1; i <= xmp.countArrayItems(XMPConst.NS_XMP_MM, 'Manifest'); i++) {
    var xpath = 'xmpMM:Manifest[' + i + ']/stMfs:reference/stRef:filePath';
    xmpFilePaths.push(xmp.getProperty(XMPConst.NS_XMP_MM, xpath).value);
  }

  // 2. relink all the broken links
  //Assumption - order of file paths from XMP matches order of elements retrieved from active doc
  var artItems = app.activeDocument.pageItems;
  alert("number of page items = " + artItems.length);

  //Counter to keep track of linked (PlacedItem) and embedded (RasterItem) images
  var cnt = -1;

  //Loop through all the items on the artwork
  for(var i = 0; i < artItems.length; i++) {
    
    var artItem = artItems[i];
    var itemType = artItem.typename;
    alert("itemType = " + itemType);

    if("RasterItem" == itemType) {
      cnt++;
      continue;
    }
    else if("PlacedItem" == itemType) {
      cnt++;
      try {
        var triggerErrorIfBrokenLink = artItem.file;
      } catch (error) {

        //Get broken link file name from xmp
        //var filename = xmpFilePaths[cnt].split('/').pop();
        var filename = File(xmpFilePaths[cnt]).fsName;
        alert("xmp filename = " + filename);

        if(filename == inFileName) {
          artItem.relink(File(inFilePath));
        }
      }
    }
  }//end of for loop
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 10, 2020 Nov 10, 2020

Copy link to clipboard

Copied

Excellent work!

 

One question though... why don't you just get PlacedItems from the start? eg.

  var artItems = app.activeDocument.placedItems;

 Then you won't have to worry.

 

Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 10, 2020 Nov 10, 2020

Copy link to clipboard

Copied

"stRef:filePath" from XMP gives list of all filepaths (includes both linked and embedded images)

var xpath = 'xmpMM:Manifest[' + i + ']/stMfs:reference/stRef:filePath';

 

whereas placedItems gives list of only linked items

var artItems = app.activeDocument.placedItems;

 

I need a way to map index of filepath retrieved from XMP with the item on active document.

Hence I'm checking for RasterItem (embedded) or PlacedItem (linked file)

 

To be more precise, for embedded items you can still see the image on artwork even if the filepath is missing (as embedded item is part of document).

But for linked items if the filepath is not found, when the document is opened, Illustrator pops up a message saying that some of the links are missing and you won't see the linked item (whose filepath is not found) on document. You won't get this warning for embedded items.

Illustrator Missing Link Warning.PNG

Hope this is clear.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 10, 2020 Nov 10, 2020

Copy link to clipboard

Copied

Yes, very well explained, and taught me something. Thanks! Again, excellent work. 🙂

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 07, 2020 Nov 07, 2020

Copy link to clipboard

Copied

Hi femkeblanco, I would call the variable 'name' in the case you mention. I think its actually perfect. Why is it bad? - Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Nov 08, 2020 Nov 08, 2020

Copy link to clipboard

Copied

Labels like "name", "path", "selection", etc are application defined properties.  Redefining them can cause unexpected behaviour.  Using "path" caused me such a headache once, until I found out why. 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 10, 2020 Nov 10, 2020

Copy link to clipboard

Copied

Oh, that's good to know.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 17, 2020 Nov 17, 2020

Copy link to clipboard

Copied

How to get item Format property displayed in Links Panel?
Can we get this from app.activeDocument.pageItem?

For embedded items shown in Links panel, "typename" is "RasterItem"

For images placed using Illustrator->File->Place command, information like Format (ex: JPG(Embedded File)) is displayed in Links panel
When I select any item like Text from document and rasterize (using Illustrator->Object->Rasterize), the item is rasterized and displayed in Links panel. For these types of rasterized items, Format is NA(Embedded File)
I need to differentiate between Raster item whose Format is NA and other types like JPG, PNG etc.

LinkFormatProperty.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 18, 2020 Nov 18, 2020

Copy link to clipboard

Copied

I'm don't have a perfect answer. Could you try this:

 

Check if item has a file property (ie. item.file doesn't throw an error) and get the file suffix from the file name.

var item = app.activeDocument.pageItems[0];
var suffix = getItemFileSuffix(item);
if (suffix != undefined) {
    // now you know the file format is not N/A
    if (suffix == 'jpg') {
        //do something?
    }
}

function getItemFileSuffix(item) {
    var suffix;
    if (item.typename == 'PlacedItem' || item.typename == 'RasterItem') {
        try {
            suffix = examplePageItem.file.fullName.split('.').pop();
        } catch (error) { }
    }
    return suffix;
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 19, 2020 Nov 19, 2020

Copy link to clipboard

Copied

I have tried this.

Rasterized text doesn't have file property.
But in case of embedded image, if the file path seen in the links panel is not available on user's machine, then in this case too app.activeDocument.pageItems[0].file doesn't exist.

So I'm not able to differentiate between embedded image which has Format like JPG, PNG etc and rasterized text whose Format is NA as displayed in Links panel.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 19, 2020 Nov 19, 2020

Copy link to clipboard

Copied

LATEST

Just checking: you are also considering the path from the XMP manifest entry? (Sorry I don't have time to test right now, but I assume you have.)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines