InDesign scripting : lesson 17

here’s a quickie that’s really handy for those of you who have to (against your will, obviously) allow other users to access your InDesign files.

this script was created for a publishing workflow where the editors did their thing right in the live files. this meant there was the potential for page elements to be inadvertently moved or resized or whatever. by locking everything in a document we gain peace of mind for both the editors and designers — editors can do their editing, but there’s no danger that they’ll alter the frames themselves.

to start, we need a dialog box so the user can choose to either lock or unlock everything. as always, follow along in applescript editor (found in applications > utilities) or, for older OS versions, script editor (found in applications > applescript) and update the script to your version of InDesign :

tell application "Adobe InDesign CS4"
  activate
  set mgDialog to make dialog with properties {name:"Groovy script to either Lock or Unlock everything in a document"}
  tell mgDialog
    tell (make dialog column)
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"What do you want to do?    "}
        end tell
        tell (make dialog column)
          set mgLockButtons to make radiobutton group
          tell mgLockButtons
            make radiobutton control with properties {static label:"Lock everything", checked state:true}
            make radiobutton control with properties {static label:"Unlock everything"}
          end tell
        end tell
      end tell
      
      set mgResult to show mgDialog
      if mgResult is true then
        set mgLock to selected button of mgLockButtons
        destroy mgDialog
      else
        display dialog "OK, fine, see if I care" buttons {"Cancel"} default button 1
      end if
      if mgLock is 0 then
        my mgLockAll()
      else if mgLock is 1 then
        my mgUnlockAll()
      end if
    end tell
  end tell
end tell

massive macgrunt fans will understand pretty much all of that because they have paid attention and studied hard throughout all the previous lessons.

the first part creates a nice looking dialog box for our discerning user :
screen grab of dialog box created by Lock/Unlock script

the second part captures the results of the dialog and acts accordingly — either activating one of two subroutines or, just for shits and giggles, displaying a friendly message if the user decides to cancel instead :
screen grab of Lock/Unlock script  message if user cancels

unusually, the rest is very simple — these two subroutines just get placed after the last ‘end tell’ :

on mgLockAll()
  tell application "Adobe InDesign CS4"
    tell active document
      set locked of every page item to true
      set locked of every guide to true
    end tell
    display dialog "All items are now locked" & return & return & "" buttons {"Rock On!"} default button 1 giving up after 1
  end tell
end mgLockAll

on mgUnlockAll()
  tell application "Adobe InDesign CS4"
    tell active document
      set locked of every page item to false
      set locked of every guide to false
    end tell
    display dialog "All items are now unlocked" & return & return & "" buttons {"Bonza!"} default button 1 giving up after 1
  end tell
end mgUnlockAll

now, applescript experts will be able to streamline that script so that it only takes up about half as many lines — but who cares? it works so fast and effectively that it really doesn’t matter.

macgrunt icon

InDesign scripting : lesson 16

this is the fourth of a series of lessons about how to script the contents of documents. so far we’ve looked at how to create and do things with page items. now let’s have a closer look at colours.

if you want to follow along — open a new document. then run this script from script editor (found in applications > applescript) — as always, update the script to your version of InDesign :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make rectangle with properties {fill color:"Black", geometric bounds:{5, 5, 10, 10}}
    make rectangle with properties {fill color:swatch 2, geometric bounds:{10, 10, 15, 15}}
    make rectangle with properties {fill color:"C=50 M=100 Y=0 K=10", geometric bounds:{15, 15, 20, 20}}
  end tell
end tell

now, it’s more than likely that the script will fail on that third rectangle. and this is the frustrating thing about colours — you can’t use a colour unless it already exists as a swatch. but more about that in a moment.

the script above shows two ways to reference a colour : by name or by index (ie. position in the swatches panel). note that if you had a swatch called ‘swatch 2’ you’d reference that with double quotes (… fill color:”swatch 2″ …) but you’d NEVER name a swatch that would you!? the other thing to note is that when the rectangle is first drawn it will have whatever fill and stroke attributes are set as defaults — exactly the same as if it were drawn using the rectangle tool (not to be confused with the rectangle frame tool).

ok. to get around the missing colour issue you have to create a new swatch. notice that you don’t actually make a new swatch, you make a new colour — which just happens to appear in your swatches panel (confusing? you bet) :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make color with properties {model:process, space:CMYK, color value:{50, 100, 0, 10}, name:"C=50 M=100 Y=0 K=10"}
    make color with properties {model:process, space:RGB, color value:{250, 255, 0}, name:"R=150 G=255 B=0"}
    make rectangle with properties {fill color:"Black", geometric bounds:{5, 5, 10, 10}}
    make rectangle with properties {fill color:swatch 2, geometric bounds:{10, 10, 15, 15}}
    make rectangle with properties {fill color:"C=50 M=100 Y=0 K=10", geometric bounds:{15, 15, 20, 20}}
    make rectangle with properties {fill color:"R=250 G=255 B=0", geometric bounds:{20, 20, 25, 25}}
  end tell
end tell

note : you should always specify the name — you can leave this out but you may get swatches with incorrect names (this happens if the “Name with Color Value” check box was not selected the previous time a swatch was created). the naming convention used here is a good one to follow in InDesign generally (not only when scripting) it saves confusion with duplicate or near-duplicate swatches. calling a swatch “purplish” is just going to lead to tears somewhere down the line.

now, if you try to run that script again on the same file it will fail because you cannot make a colour if it already exists — that is, you cannot have two colours with the same name. this next snippet will work because each swatch has a different name :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make color with properties {model:process, space:CMYK, color value:{50, 100, 0, 10}, name:"Blue"}
    make color with properties {model:process, space:CMYK, color value:{50, 100, 0, 10}, name:"Another Blue"}
    make color with properties {model:process, space:CMYK, color value:{50, 100, 0, 10}, name:"Yet Another Blue"}
  end tell
end tell

but that would be just silly. however, it does highlight why you should get into good swatch naming habits.

there are a few ways to get around the problem of the previous script failing — here’s a simple one :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    try
      make color with properties {model:process, space:CMYK, color value:{50, 100, 0, 10}, name:"C=50 M=100 Y=0 K=10"}
    end try
    try
      make color with properties {model:process, space:RGB, color value:{250, 255, 0}, name:"R=150 G=255 B=0"}
    end try
    make rectangle with properties {fill color:"Black", geometric bounds:{5, 5, 10, 10}}
    make rectangle with properties {fill color:swatch 2, geometric bounds:{10, 10, 15, 15}}
    make rectangle with properties {fill color:"C=50 M=100 Y=0 K=10", geometric bounds:{15, 15, 20, 20}}
    make rectangle with properties {fill color:"R=250 G=255 B=0", geometric bounds:{20, 20, 25, 25}}
  end tell
end tell

try blocks are great. if the script CAN do the task it does — if it can’t, it just moves on to the next command.

well, that’s a quick and dirty introduction to colours. what’s up next? who knows. til then — keep grunting.

macgrunt icon

InDesign scripting : lesson 15

this is the third of a series of lessons about how to script the contents of documents. so far we’ve looked at how to do things with items on a page. now it’s time to look at how to create those items in the first place.

if you want to follow along — open a new document. then run this script from script editor (found in applications > applescript) — as always, update the script to your version of InDesign :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make rectangle
  end tell
end tell

pretty simple. eh? but who needs a tiny rectangle in the top left corner of the page? once the rectangle is created, change it to suit your needs :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make rectangle
    tell rectangle 1
      set stroke color to "Black"
      set stroke weight to 2
      set geometric bounds to {5, 5, 30, 50}
    end tell
  end tell
end tell

notice that you don’t set the width and height of a page item — you set its geometric bounds. those four figures define, in order, the top, left, bottom and right edges of the rectangle. or, if you check your control panel, the Y and X coordinates of the top left corner, then the Y and X coordinates of the bottom right corner.

you can also set all the properties in one hit :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make rectangle
    tell rectangle 1
      set properties to {stroke color:"Black", stroke weight:2, geometric bounds:{5, 5, 30, 50}}
    end tell
  end tell
end tell

but the easiest way is to set the properties as you make the page item :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make rectangle with properties {stroke color:"Black", stroke weight:2, geometric bounds:{5, 5, 30, 50}}
  end tell
end tell

there are lots of different properties you can set for rectangles (and other page items). the best way to learn what they are is to check the InDesign scripting dictionary. in script editor go file > open dictionary and choose InDesign from the list. enter ‘rectangle’ into the search field (top right corner) and look for the entry classified as ‘class’. here’s a screen grab of part of the CS2 entry (click to enlarge) :

screen grab of part of 'rectangles' entry in InDesign scripting dictionary

the entries marked ‘r/o’ are read only — meaning you can’t change their value. all the others are at your mercy.

and now for your homework…
those of you who have been studying assiduously will be able to explain why this would fail when run on a blank document :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    make rectangle with properties {stroke color:"Black", stroke weight:2, geometric bounds:{5, 5, 30, 50}}
    set properties of rectangle 1 to {content type:text type}
    select rectangle 1
  end tell
end tell

interestingly, the command that changes the content type could also be written like this in CS2 :

set content type of rectangle 1 to text type

but that functionality is broken in CS4 and CS5 (well, at least as far as script editor is concerned) — go figure.

next we’ll look at colours and swatches.

go to lesson 16

macgrunt icon

InDesign scripting : lesson 14

lesson 13 started talking about how to script the contents of documents — specifically, how to select items on a page. let’s continue by having a look at some things you can do with page items.

if you want to follow along — open a new document and put a bunch of different page items on the first page — make sure you have more than one ‘rectangle’ (text frames are not rectangles — even if they are rectangular). then run this script from script editor (found in applications > applescript) — as always, update the script to your version of Indesign :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    select every rectangle of page 1
    move selection by (5,1)
  end tell
end tell

the numbers in the brackets are the X (horizontal) and Y (vertical) locations and the unit increments will be whatever you have set as your default. you could replace those two lines with this instead if you like :

move rectangles of page 1 by (5,1)

notice the difference? the rectangles are moved without having to select them first. if you want to include items on the pasteboard, use this instead :

move rectangles of spread 1 by (5,1)

contrast the ‘move by’ command with the results of ‘move TO’ :

move rectangles of page 1 to (5,1)

which is similar to when you try to move items to a new page :

move rectangles of page 1 to page 2

that’s a problem if you want your page items to maintain their relative positions. you could get around the first problem like this :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    select rectangles of page 1
    set newGroup to make group with properties {group items:selection}
    move newGroup to {5, 1}
    ungroup newGroup
  end tell
end tell

… and the second problem like this :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    select rectangles of page 1
  end tell
  cut
  tell active document
    set newPage to page 2
    tell layout window 1
      set active page to newPage
    end tell
  end tell
  paste in place
end tell

notice in this one how you can not tell a document to cut and paste — you have to tell the application. when developing your own scripts, once you get a script like this to work — it’s a good idea to go back through it to see if it can be streamlined. here’s one way to simplify the previous script :

tell application "Adobe InDesign CS4"
  activate
  select rectangles of page 1 of active document
  cut
  set newPage to page 2 of active document
  set active page of layout window 1 of active document to newPage
  paste in place
end tell

this next script demonstrates a few other commands. before running it, make sure you have at least two rectangles on page 2. can you work out how InDesign determines which is rectangle 1 and which is rectangle 2? :

tell application "Adobe InDesign CS4"
  activate
  tell page 2 of active document
    set horizontal scale of rectangle 1 to 150
    set rotation angle of rectangle 1 to 10
    set stroke weight of rectangle 1 to 10
    set stroke color of rectangle 1 to "Paper"
    set shadow mode of rectangle 1 to drop
    set vertical scale of rectangle 2 to 200
    set fill color of rectangle 2 to "Black"
    set shear angle of rectangle 2 to 20
    set feather mode of rectangle 2 to standard
    set feather width of rectangle 2 to 5
  end tell
end tell

that’s it for now. the next lesson will show how to make new page items.

go to lesson 15

macgrunt icon

InDesign scripting : lesson 13

the first dozen lessons dealt with scripts that address InDesign documents or the application itself. the next few will focus on addressing the contents of files — the pages and the stuff on them. if you’re unconvinced that scripting the contents of files is useful to you — check out the short videos on youtube — one of those may change your mind.

the things on a page are collectively called page items — these include rectangles, text frames, ovals, polygons, graphic lines and, the frequently problematic, groups. fill a single-page file with different types of page items and then run this from script editor (found in applications > applescript) — as always, update the script to your version of Indesign :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    select every page item
  end tell
end tell

then change “page item” to “rectangle” and run it again. cool eh? you can use “rectangles” instead of “every rectangle” if it makes more sense to you.

if you wanted to select the rectangles and text frames but not the other page items, you could do it like this (notice that you can’t use “select every rectangle and every text frame”) :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    select every rectangle
    select every text frame existing selection add to
  end tell
end tell

well, that all works fine if you’ve only got stuff on one page. but it will fail with most documents because you cannot simultaneously select items on multiple pages — and “every rectangle” means every rectangle in the entire document. most of the time you need to specify a page or spread :

select every page item of page 3

you could also use “…in page 3″ — whatever takes your fancy.

previous lessons have mentioned how torturous applescript syntax can be. well, check this out — the way to select items of a particular layer of a particular page :

tell application "Adobe InDesign CS4"
  activate
  tell active document
    select (page items of page 3 whose (name of item layer is "Layer 2"))
  end tell
end tell

all these examples have used the command “select”. no doubt you can work out what would happen if you substituted another command — such as “delete”, “duplicate” or “bring to front”.

go to lesson 14

macgrunt icon