Working With InDesign Library Assets

Adobe InDesign has provided some great built-in functionality for working with Libraries and Assets.For instance, you may not be aware of the following functionality provided in the Object Library panel menu:

  • ChooseItem Information with a library asset selected to have all of its information displayed in a dialog
  • Choose Add Items On Page [Number] to have all of the assets from a library added to a given page
  • Select Sort to arrange the assets in the active library by name, by newest, by oldest,or by type
  • Choose Place Item(s) with an asset (or assets) selected, to add the assets to the active page at the original page coordinates
  • Choose Show Subset… to show only those items that meet a certain criteria for the active library

Show Subset

When you use Show Subset all items not meeting your established criteria become invisible. If there are no items meeting the criteria, you end up with a blank library panel. Of course, you can make the assets all visible again by choosing Show All from the menu.

The Show Subset dialog is very powerful. If you click More Choices you have the added option to Match All or Match Any One.

Custom Functionality

What do you do if you are not sure where that blasted library asset you want is stored?

Of course that never happens because you are so careful in managing your libraries, right? But, just in case you do forget where that asset is stored, you can get a list of all assets meeting a given criteria in all of the libraries that are open. Hopefully, your list of libraries would not be extensive as a script to search a number of libraries could take a fair amount of time to run. But then, that may be better than your having to manually do the search.

Consider a Find Asset Script

It would be nice if we could create a dialog box the same as InDesign’s Show Subset box that would allow a multi-library search. To keep things simple you may want to stick with InDesign’s modal dialog. For this, the dialog would need to have four enabling groups: one each for Item NameDescriptionCreation Date, and Object Type.

Each Enabling Group will need to provide two fields:

  1. Item Name: a drop down (Contains and Does Not Contain) plus a text field for text entry
  2. Description: a drop down (Contains and Does Not Contain) plus a text entry field
  3. Creation Date: drop down (Greater Than, Less Than, Equal, and Not Equal) plus a text entry field with the current date displayed so user will know the format required
  4. Object Type: drop down (Equal and Not Equal), plus a drop down listing the object types (Image, EPS, PDF, Geometry, Page, Text, Structure, and InDesign File).

The dialog created would look something similar to the screenshot below.

Depending on the Enabling Group selected, the script would pass the results of the user’s selection back to the main part of the script.

Script Functionality

Once the user’s preferences are returned from the dialog, the fun begins. The following is suggested:

  • get a list of the open libraries
  • repeat through the list and check for assets meeting the given criteria
  • if an asset (or assets) is found, add a reference to the asset to a list (assetRefList)
  • if the assetRefList is not empty, allow the user to choose from the list found
  • otherwise, alert the user that assets were not found
  • if the user checked place the image(s) on the active page, the script will need to get a reference to the active page in the active document and then place the items

Script Handlers

So far the script looks fairly straightforward. But, as they say, the devil is in the details. There are a couple of issues that need to be solved. One issue I found to be interesting had to do with comparing dates.

Working With Dates

There are two places in the script where dates are involved.

1. The script needs to create a date string to place in the date field of the custom dialog. This is used to show the user the format expected. It also serves as a default date. This can be done using the current date as in the code following:

   (*returns current date in format of mm/dd/yy
   set dateString to getDateString()
   on getDateString()
	set d to (current date)
	set theMonth to (month of d as number)
	set theDay to day of d as string
	set theYear to text 3 thru 4 of (year of d as string)
	return "" & theMonth & "/" & theDay & "/" & theYear
   end getDateString

Notice that the value of theMonth can now be coerced to a number value. Earlier versions of AppleScript did not allow this, but this coercion has been around long enough to be reliable.

Also, notice the return value starts out with an empty string. Remember that the month value is a number. Without the empty string to coerce it to a string value, the value returned would be a list.

2. Where the fun begins with dates is when doing date mathematics and date comparisons. If the user chooses to find assets by the date created option, the script needs to compare asset creation dates with the string entered in the date field. The creation date for an asset is returned as a date reference:

   date "Thursday, October 16, 2014 at 8:01:56 AM"

So how do we compare the asset’s creation date with the string entered by the user, for example:


The answer is: we don’t. We simply tell AppleScript to convert the date string to a date object, and let it do the rest. To work with dates, AppleScript internally converts the date to seconds. You can see how this is accompished in the following:

   --values returned from custom dialog
   set dateOption to "Greater Than"
   set compareString to "06/14/14"
   set theResult to findByDate(dateOption, compareString)
   on findByDate(dateOption, compareString)
      set foundList to {}
      --set user entered date string value to date object
      set uDate to date compareString 
      tell application "Adobe InDesign CC 2014"
         set libraryList to name of libraries
         repeat with i from 1 to length of libraryList
            set theLib to item i of libraryList
            tell theLib
               if dateOption = "greater than" then	
                  set assetList to (every asset whose date is greater than uDate)
               else if dateOption = "is less than" then	
                  set assetList to (every asset whose date is less than uDate)
               else if dateOption is "Not Equal" then
                  set assetList to (every asset whose date is not equal to uDate)
                  set assetList to (every asset whose date is equal to uDate)
               end if
            end tell
            if length of assetList > 0 then
               set foundList to foundList & assetList
            end if
         end repeat
      end tell
      return foundList
   end findByDate 

Working With Lists

Another little AppleScript novelty found in the handler above involves adding lists to lists.

Normally, we add items to a list by setting the beginning or end of a list to the value. But, in the case of adding a list, we have several options.

For example, consider a list such as {1, 2, 3, 4}.
To this list we want to add a second list {100, 200 300}
We can do this by setting the end of the first list to the second. In this event, the second list is added as a single item to the first:

   set listToAdd to {1, 2, 3, 4}
   set myList to {100, 200, 300}
   set the end of myList to listToAdd
   --result is {100, 200, 300, {1, 2, 3, 4}}

Should you want to combine the lists, as in the findByDate routine above, concatenation needs to be used. For our example lists, this would be:

   set listToAdd to {1, 2, 3, 4}
   myList to {100, 200, 300}
   set myList to myList & listToAdd
   --result is {100, 200, 300, 1, 2, 3, 4}

Unward and Upward

This should give you plenty to chew on if you were so inclined to write a script to search for all of the assets in your open libraries. You could even search for assets in libraries that were closed For this, you would need to temporarily open the library and then close it.

Admittedly, the functionality for a custom dialog (modal dialog) is not as cool as a full-functioning window, but that is a little out of our scope for the moment.