InDesign scripting : lesson 21

here’s a script to accompany the cool feature covered in InDesign tip : #19 which showed how to quickly place a whole bunch of images into a neat grid. the technique is perfect for creating contact sheets — all we need to do now is label those suckers. this script will add image filenames to the page.

as always, to follow along, just copy the script samples into applescript editor (found in applications > utilities) or, for older OS versions, script editor (applications > applescript). then update the first line to your version of InDesign. hopefully the script will run nicely, unless the syntax has changed between versions.

first we need to do a little setting up — change the view preferences, create a layer and create a paragraph style :

tell application "Adobe InDesign CS4"
  tell active document
    set mgOrigPrefs to properties of view preferences
    set ruler origin of view preferences to spread origin
    
    try
      set mgLayer to layer "Image Labels"
    on error
      set mgLayer to make layer with properties {name:"Image Labels"}
    end try
    
    try
      set mgPara to paragraph style "Image Labels"
    on error
      set mgPara to make paragraph style with properties {name:"Image Labels", justification:center align, point size:12, applied font:"Arial Narrow	Bold", fill color:"Black"}
    end try

    -- other script elements will go in here

    set properties of view preferences to mgOrigPrefs
  end tell
end tell

whenever you use applescript to change preferences, it’s good practice to first capture the current settings so that you can reset the preferences once you’re done — this is what the start and end of that script are doing.

the other bits are pretty self explanatory. if you don’t understand why the make layer and make paragraph style parts are contained in try blocks — just ask.

just one thing : you may not have or want the font “Arial Narrow Bold”. just plonking in another font name may not work (notice the big gap in the script’s font name — this is a necessary element for that font). so what’s the easiest way to get the correct name of the font you DO want to use? just open a new InDesign file with one text frame containing some text in the font you prefer. then run this script :

tell application "Adobe InDesign CS4"
  tell active document
    get applied font of story 1
  end tell
end tell

the correct font name (with any weird spacing and whatnot) will appear in the results window. just copy/paste it across.

ok, let’s keep going. the next part of the script goes after that last end try. first we set up a repeat loop to process every page in the document. for each page we have to get all the page items that could contain an image (mgItems). and, because groups are treated as their own special kind of page item, we use a try block to look through any groups for other frames to add to the mgItems list.

next, we set up another repeat loop to process each page item in the mgItems list. since we don’t yet know if the page item contains a link, we try to get the name of any image (raster) or graphic (vector). then we set up an if/then statement to create a label wherever required :

set mgItemTypes to {rectangle, oval, polygon}
repeat with mgCountPage from 1 to (count pages)
  set mgPage to page mgCountPage
  set mgGroups to (every page item of mgPage whose class is group)
  set mgItems to (every page item of mgPage whose class is in mgItemTypes)
  
  try
    repeat with x from 1 to count of mgGroups
      set mgGroupedItems to (every page item of (item x of mgGroups) whose class is in mgItemTypes)
      repeat with z from 1 to count mgGroupedItems
        set end of mgItems to item z of mgGroupedItems
      end repeat
    end repeat
  end try
  
  repeat with mgCountItems from 1 to (count mgItems)
    set mgPageItem to (item mgCountItems of mgItems)
    set mgLinkName to ""
    try
      set mgLinkName to name of item link of image 1 of mgPageItem as string
    on error
      try
        set mgLinkName to name of item link of graphic 1 of mgPageItem as string
      on error
        set mgCountItems to mgCountItems + 1
      end try
    end try
    
    if mgLinkName is not "" then
      set mgGeoBounds to geometric bounds of mgPageItem
      set mgY2 to text item 3 of mgGeoBounds
      set text item 1 of mgGeoBounds to mgY2
      set text item 3 of mgGeoBounds to (mgY2 + 5)
      
      set mgLinkLabel to make text frame in mgPage with properties {geometric bounds:mgGeoBounds, fill color:swatch 2}
      set contents of mgLinkLabel to mgLinkName
      move mgLinkLabel to layer "Image Labels"
    end if
  end repeat
end repeat

the interesting bits are in that last if/then statement. first we get the geometric bounds (mgGeoBounds) of the page item containing the image or graphic (mgPageItem). for an explanation of geometric bounds, see InDesign scripting : lesson 15. we use these as the basis for creating geometric bounds for the label. items 2 and 4 of mgGeoBounds are left unchanged — these are the left and right edges of the frame. item 1 (top) is reset to match item 3 (bottom) and item 3 is reset to 5mm further down (or 5 of whatever measurement units you’re using). so, we end up with a 5mm high text frame whose top edge aligns exactly with the bottom edge of the image frame. hope that makes sense.

and the final part of the script goes immediately after that last end repeat and contains a number of interesting bits and pieces too — but it should be pretty easy to understand just by reading it — set text frame options, apply the paragraph style we created first up, and deal with any overset text :

tell every text frame of layer "Image Labels"
  set vertical justification of text frame preferences to center align
  set ignore wrap of text frame preferences to true
  set inset spacing of text frame preferences to {0.5, 2, 0.8, 2}
end tell

tell parent story of every text frame of layer "Image Labels"
  set applied paragraph style to "Image Labels"
  set applied character style to "[No character style]"
  clear overrides overrides to clear all
end tell

try
  tell (parent story of every text frame of layer "Image Labels" whose overflows = true)
    set leading to 10
    set point size to 10
  end tell
end try
try
  tell (parent story of every text frame of layer "Image Labels" whose overflows = true)
    set leading to 8
    set point size to 8
  end tell
end try
try
  tell (parent story of every text frame of layer "Image Labels" whose overflows = true)
    set leading to 6
    set point size to 6
  end tell
end try

screen shot showing page of labelled images

putting the labels on a separate layer makes it easy to select and move them if you need to (or delete them) :
screen shot of page after labels have been moved

of course, you’re not restricted to labelling images with just a filename. you could add a file size, filepath, xmp data, whatever. this script can be easily adapted to place captions for each image — if the captions are saved as metadata with the image file. go sick.

go here if you want a copy of the complete image labelling script

macgrunt icon

InDesign tip : #19

ok, here’s another follow-up post to cover stuff you weren’t told the first time around. InDesign tip : #12 showed how to place multiple images — a really brilliant feature we’ve had since CS4. that tip showed how to load a bunch of images into the cursor and place them one at a time throughout your document.

this tip is about the other cool trick — placing all images on the page in one hit. the images are arranged in a nice, neat grid which makes it a perfect technique for creating contact sheets.

first, grab all your images :
screen grab showing loading multiple images in the place cursor

as usual, your cursor will show a counter and a ghosted version of the first image. click and drag to begin making a frame (this will be in the proportions of your first image) before letting go of the mouse button, use your up and right arrows to add rows and columns to make a grid :
screen grab showing grid being drawn

now you can drag the grid to whatever proportions you like. if you need to remove rows or columns, just use your down and left arrows. when you’re happy with the way your grid looks, let go of the mouse button and your images will all be placed, in order, in the new grid :
screen grab of final grid with all images in place

what you end up with is a whole bunch of individual frames (not a grouped grid). only enough frames are created for the number of images you are placing — so, if you draw a 12-frame grid but only have 10 images loaded, only ten frames are created. if your grid isn’t big enough to hold all your images, the remaining images remain loaded in the cursor ready to be placed elsewhere.

but that’s not all…
if you find the grid you’ve drawn isn’t quite right, just undo (command-z) — all the frames disappear and all the images are reloaded into the cursor — ready to try again. you can change the spaces between the frames while you’re drawing the grid by using the command key with your arrows. and if you hold command-shift before you start drawing your grid — you’ll get a grid with the same columns, rows and spaces as the last grid you drew.
cool, eh?

but wait, that’s (still) not all…
this isn’t just for when you’re placing images. you can use the same technique if you just want a grid of rectangles, ovals, polygons, text frames or even graphic lines. some of you will have noticed that this new ‘gridify’ functionality stuffs the ability to adjust polygons (arrows) and stars (command-arrows) on the fly like in the old days. but, if you hit the space bar while drawing a polygon you’ll deactivate the grid thing and get the old functionality back. hit the space bar again to reactivate gridify.

can you believe that’s still not all?…
you could use the same technique to create text frames and add live captions to include name labels for your images, but the next scripting lesson will show you an easier way to label all images in a file in one sweep. making contact sheets is easy as.

incidentally, if you like those funky little icons, you can find them over at shutterstock — an excellent source of good value stock images. just search in the contributor field for ‘samer’.


• related post : InDesign scripting : lesson 21 : label all images in document quickly.

macgrunt icon

InDesign tip : #18

InDesign tip : #14 talked about different ways of zooming about an InDesign document. but it missed one really cool little trick which has, apparently, been with us since CS4 — when the navigator panel was dropped — and it’s called, impressively, power zoom.

you start with the hand tool. as always, you do not have to select the hand tool from the tool panel — you activate it temporarily in one of three ways :
• if you have one of the selection tools active — hold down the space bar;
• if the text tool is active but no text frame is selected — use option-space;
• if the text tool is active in a text frame — use option only.
why the developers insisted on making it this complicated is a mystery.

anyway, once you have the hand tool up, click and hold the mouse button. after a couple of seconds the screen will zoom out a little and present you with a red outline (and you can let go of whichever keys you’re holding down). drag the red outline to wherever you want in the document — scroll up or down (or use your arrows) to resize the red outline — let the mouse button go and you’ll zoom into the new outlined area. now THAT’S cool :
screen grab of view before power zoom
screen grab of view during power zoom
screen grab of view after power zoom

incidentally, if you like that groovy little image by dek wid, you can find a tutorial showing how it’s done over at photoshop tutorials.

macgrunt icon

InDesign scripting : lesson 20

this is a perfect example of how becoming familiar with applescript will save you (well, at least your time). just last week a new problem presented itself. artwork for thirty signs had to be sent to a signwriter who required all text be converted to outlines.

now that’s not too difficult — select all (command-a), create outlines (command-shift-o), repeat for remaining 29 pages. but, when you know a little applescript (and when you know you’ll be doing this for future projects for the same signwriter) it makes sense to create an automated solution.

if you check the scripting dictionary you’ll see that the command create outlines can address a whole bunch of stuff — characters, words, lines, stories, text frames, etc. the first attempt at this script addressed stories :

tell application "Adobe InDesign CS4"
  tell active document
    tell every story
      create outlines
    end tell
  end tell
end tell

… and got more complex with each attempt :

tell application "Adobe InDesign CS4"
  tell active document
    repeat with thisStory in every story
      tell thisStory
        create outlines
      end tell
    end repeat
  end tell
end tell
tell application "Adobe InDesign CS4"
  tell active document
    repeat with x from (count every story) to 1 by -1
      tell story x
        try
          create outlines with delete original
        end try
      end tell
    end repeat
  end tell
end tell

these sort of worked, kind of ok, some of the time — in other words, they were bloody useless.

so it made sense to try a different tact — surprisingly, perhaps (or perhaps not), this simple variation of the original script works much better :

tell application "Adobe InDesign CS4"
  tell active document
    tell every text frame
      create outlines
    end tell
  end tell
end tell

so far, only one other hassle has presented itself — groups. applescript doesn’t recognise text frames if they are part of a group (unless you specify to check inside groups). to check this for yourself, create an InDesign document with three text frames — group two of the text frames together — then run this script :

tell application "Adobe InDesign CS4"
  tell active document
    set theFrames to count text frames
    set theGroups to count text frames of group 1
    
    display dialog "text frames = " & theFrames & return & "text frames in groups = " & theGroups
  end tell
end tell

no worries — for this workflow we could just ungroup all the groups before converting to outlines :

tell application "Adobe InDesign CS4"
  tell active document
    repeat until (count of groups) = 0
      ungroup every group
    end repeat
    tell every text frame
      create outlines
    end tell
  end tell
end tell

the repeat loop ensures we get every group — that means groups within groups within… etc.

your homework for today is to come up with a solution which does not involve ungrouping the groups.

macgrunt icon

InDesign tip : #17

lovers of typography love a well designed ligature. those who are indifferent to typography generally say “what’s a ligature?”. and those who are entirely ignorant don’t even notice a ligature even when they are looking straight at one. although, that’s actually the point of the ligature in the first place — you’re not supposed to notice the typographic trick, because the ligature is intended to make reading easier.

just to make clear the foregoing blather — here are some standard ligatures in well-known fonts. you’ll notice that not all fonts have been designed with a full complement of ligatures :
screen grab of a selection of ligatures in various fonts

that’s right, ligatures are those little joined-together thingies that are generated by default in InDesign. unfortunately, ligatures do not always lead to improved readability and sometimes you’re better off just using the standard letterforms.

you can turn ligatures off in the dropdown menu in the character panel. if you’re doing the right thing and using styles for your text formatting, you’ll find ligatures as one of the options under basic character formats. you can set no-ligatures as your default for all future documents by unchecking it in the character panel when you have no documents open.

the only way to turn ligatures off for an entire document in one hit is with a script something like this one :

tell application "Adobe InDesign CS4"
  tell active document
    tell every story
      set ligatures to false
    end tell
  end tell
end tell

of course, the Adobe CS being what it is, you do NOT turn ligatures off in Illustrator the same way you do in InDesign. for Illustrator you have to go to the opentype panel instead.

macgrunt icon