InDesign scripting : lesson 27

here is a variation on the slug form script from lesson 25. this version does not use a pre-existing form on the page — it creates a simple text frame holding information similar to the ‘page information’ you can add to your printouts, with three important improvements : it’s more readable ; it includes the page dimensions and ; it includes the user name.

the full version of the script prints the document and exports a pdf to an email attachment — functionality that you can find lessons for elsewhere on this site. today we’ll just focus on the core problem of creating the slug info which will look something like this :
screen grab of slug information

the first part of the script demonstrates a handy little scripting trick — the script property :

property mgUser : ""

if mgUser is "" then
  --bit to collect new user name
  tell application id "com.adobe.InDesign"
    activate
    set mgDialog to make dialog
    tell mgDialog
      tell (make dialog column)
        tell (make dialog row)
          make static text with properties {static label:"Enter the name you'd like to be known by."}
        end tell
        tell (make dialog row)
          set mgTextField to make text editbox with properties {edit contents:"Who you then?", min width:250}
        end tell
        tell (make dialog row)
          make static text with properties {static label:"(you won't be hassled with this again)"}
        end tell
      end tell
    end tell
    
    set mgResult to show mgDialog
    if mgResult is true then
      set mgUser to edit contents of mgTextField as string
      destroy mgDialog
    else
      error number -128
      destroy mgDialog
    end if
  end tell
  mgRunThisSucker()
else
  mgRunThisSucker()
end if

you’ll notice that we set the property mgUser to “” right at the start, and then go on to ask if mgUser is “”… — now that might seem nonsensical, but it’s not — because script properties have persistent data. the first time we run the script mgUser starts off as “” but is given a different value by the user when they enter their name in the dialog that’s generated (eg. ‘macgrunt’). that new value gets saved as an integral part of the script so that the next time it is run mgUser is “macgrunt”, not “”. by wrapping that whole script in an if/then statement, we ensure that the user only has to enter their name the first time the script is run. every subsequent run skips everything down to the second last line — mgRunThisSucker().

the user will be presented with a dialog something like this :
screen grab of user dialog
of course, you can change the various text elements in that dialog to read however you like.

the next part of the script captures a bunch of data we need :

on mgRunThisSucker()
  with timeout of 36000 seconds
    set mgHour to do shell script "date '+%H'"
    set mgMinute to do shell script "date '+%M'"
    if mgHour is less than 12 then
      set mgAmPm to "am"
    else
      set mgAmPm to "pm"
    end if
    if mgHour is more than 12 then
      set mgHour to mgHour - 12
    end if
    set mgDate to do shell script "date '+%d/%m/%y'"
    set mgDate to mgDate & "  :  " & mgHour & ":" & mgMinute & mgAmPm
    
    tell application id "com.adobe.InDesign"
      tell active document
        set mgName to name
        set mgFolder to file path
        set text item delimiters of AppleScript to "."
        set mgShortName to text item 1 of mgName
        set text item delimiters of AppleScript to ":"
        set mgClient to text item -4 of (mgFolder as string)
        set text item delimiters of AppleScript to ""

we’re capturing both the date and time for this version of the slug form. notice that …”date ‘+%H'” captures the hours in 24-hour time — but we want our time to appear as “2:00pm” rather than “14:00” — hence the bit of extra mucking around. if you’re happy with 24-hour time you could capture mgDate like this :

do shell script "date '+%d/%m/%y  :  %H:%M'"

note also that the way you capture mgClient depends on where the InDesign file sits in your folder hierarchy — text item -2 of (mgFolder as string) is the folder containing the InDesign file — text item -3 of (mgFolder as string) is the next folder up, etc.

next we create a layer and paragraph style for the slug information (if they don’t already exist) and the slug offset at the bottom of the page :

        try
          set mgLayer to layer "SLUG"
          set locked of layer "SLUG" to false
          delete every text frame of layer "SLUG"
        on error
          set mgLayer to make layer with properties {name:"SLUG"}
        end try
        try
          set mgPara to paragraph style "SLUG"
        on error
          set mgPara to make paragraph style with properties {name:"SLUG", justification:left align, point size:7, applied font:"Minion Pro  Regular", fill color:"Black"}
        end try
        
        set mgBleed to document bleed bottom offset of document preferences
        set mgSlug to mgBleed + 5
        
        if slug bottom offset of document preferences is less than mgSlug then
          set properties of document preferences to {document slug uniform size:false}
          set properties of document preferences to {slug bottom offset:mgSlug}
        end if

the first part has a couple of try blocks — the first time the script is run on a particular file it will create a new layer and para style — but on subsequent runs the layer and style will already exist and trying to create them again will cause an error. so, instead, we cover off all eventualities with the try blocks. notice that the first try block deletes all the text frames on the slug layer — new frames are created with fresh content on each run. the rest of that part of the script is dedicated to setting the slug offset to 5mm outside the bleed (unless it’s already bigger than that).

the next part captures the rest of the data we need and puts all the elements together into one long text string (mgContents) :

        repeat with mgspread from 1 to count spreads
          set active spread of layout window 1 to spread mgspread
          tell active spread of layout window 1
            set mgPage to name of page 1
            set mgWidth to item 4 of bounds of page 1
            set mgWidth to mgWidth as integer
            set mgHeight to item 3 of bounds of page 1
            set mgHeight to mgHeight as integer
            set mgDimensions to ((mgHeight as string) & "x" & mgWidth as string) & "mm"
          end tell
          
          set mgContents to mgShortName & "  :  " & mgClient & "  :  page " & mgPage & "  :  " & mgDimensions & "  :  " & mgUser & "  :  " & mgDate

notice that we’ve opened a repeat loop here — because we want to add a separate slug to each spread (this script was created for a workflow where it is possible that a single file could have pages of varying sizes).

and finally the last bit — create the text frame, fill it with text, style the text, move the frame to the right layer and, when all frames are done, lock the layer so it can’t be inadvertently used for other content :

          set mgBounds1 to mgHeight + mgBleed
          set mgBounds3 to mgBounds1 + 4
          set mgFrameBounds to {mgBounds1, "0", mgBounds3, mgWidth}
          set mgSlug to make text frame in page mgPage with properties {geometric bounds:mgFrameBounds, fill color:swatch 1}
          set properties of text frame preferences of mgSlug to {inset spacing:{0, 2, 0, 2}}
          set vertical justification of text frame preferences of mgSlug to bottom align
          set contents of mgSlug to mgContents
          set applied paragraph style of parent story of mgSlug to "SLUG"
          move mgSlug to layer "SLUG"
        end repeat
        set locked of layer "SLUG" to true
      end tell
    end tell
  end timeout
end mgRunThisSucker

cobble all that together and you’ll have a script that looks something like this :
screen grab of entire script in script editor

save that as a script (.scpt) into your scripts panel folder. as discussed in the previous post, lesson 26, if you save it in text format (.applescript) the property mgUser will not be saved as persistent data and will have to be entered every time the script is run — and that would be tedious.

if you can’t be bothered compiling this yourself, you can go here to get the complete slug script

keep grunting

macgrunt icon

17 thoughts on “InDesign scripting : lesson 27

  1. Can you update this script to display the Pantone colours along with a swatch box that are used in the document. I am currently able to do this via live captions but it only displays the Pantone name.

    • yes, I expect it probably could do that. In its current form you’d need find a way to paste coloured frames into the text frame.
      unfortunately, I don’t have time to create a solution for that just now.
      but I’d be happy to review your trial script if you hit a problem.

      m.

  2. Hi macgrunt, the script is partially working for me. I have tried to set it up to work in CS6. My document size is 2.5×2.5. When I run the script it creates the slug frame but it is not recognizing the .5 part of the dimension so the script is being offset way off the page rather than just beneath the artwork. Also the dimensions in the slug only display 2×2.

    Thanks in advance.
    Richard.

    • G’day Richard
      Over here we work in mm, but you must be working in inches, so you’ll need to adjust the script.

      The line which makes the box too big is this:
      set mgBounds3 to mgBounds1 + 4
      That’s 4mm added to the coordinate of the top of the frame — giving the total height of the frame.
      You may want something more like this :
      set mgBounds3 to mgBounds1 + .2

      We sometimes get weird page dimensions when working with mm — but because they are such small units we can always round out to the nearest whole number.
      But inches are great big clunky units, so you don’t really want to change them to integers, so just remove these two lines from the script entirely :
      set mgWidth to mgWidth as integer
      set mgHeight to mgHeight as integer

      Hopefully that will get you closer
      m.

  3. This is wonderful! I can finally track ID documents at our little newspaper here in Yellow Springs, OH. I can now output filename, path, user name, plus time last modified. But in order to make this script truly valuable, I need to also output the file’s creation date; I cannot seem to get the script to do that. I get an error, “Can’t get creation date of “filename”. I’ve searched everywhere for syntax issues, helpful tips, etc. Nothing. Any recourse, suggestions, etc.? THANKS in advance! —MM (Running InDesign CS on Mac OSX 10.6.8)

    • G’day Matt

      it looks like creation date is a property of metadata preferences.
      hopefully that’s also the case with CS. try this :
      tell application id "com.adobe.InDesign"
      tell active document
      set mgDate to creation date of metadata preferences
      end tell
      end tell

      that will give you a date like this :
      date "Tuesday, 7 May 2013 10:38:34 "

      if you want to break the date string up into a different format — see this post.

      hope that gets you a little closer.

      m.

      • That did it! Amazing! I wish I could say my coworkers will never again lose a document, but now that I need to train them to click that script icon, I can confidently say I’ll be searching for files until I die. THANKS again! —MM

      • G’day, as well! I hate to bother you again, but my plan of having individual slugbox scripts for each writer doesn’t seem to work. I copied the script to each person’s ID folder, tried to make a new document at a co-worker’s machine and got MY initials in the slugbox instead of being asked who I am. Is there a way to remedy this? THANKS! MM

      • no worries mate.

        from within InDesign, hold down your option key and double-click the script. this will open the script in Applescript Editor. hit the compile button (hammer) and then save. this basically saves it out as a new script — so mgUser is reset to ” ”

        m.

      • Is it magic? Can it be?! THANKS again! It works like a charm. Now for the workflow….MM

      • G’Day once again! I’m slinking back here sheepishly, because all my attempts to help myself have failed. What I need to do now is to “tell application to set active layer to “Layer 1”, i.e., bring the user back to the unlocked, default Layer 1, since your script leaves said user stranded in the locked SLUG. This has rankled some of my co-workers. It should be easy, but I can’t seem to get it. THANKS!MM

      • g’day matt

        yep, rankling co-workers is part of the deal. they really just need to get over themselves.

        make sure you’re telling the document :

        tell application id "com.adobe.InDesign"
        tell active document
        -- other bits
        set locked of layer "SLUG" to true
        set active layer to layer -1
        end tell
        end tell

        layer -1 is the bottom most layer, layer 1 is the top most layer.
        or you can address the layer by name — layer “Layer 1”

        m.

      • G’Eve (here in the states)! Well, it’s not working. I’m getting the message “InDesign CS got an error: Can’t set active layer of active document to last layer of active document.” Does the layer have to be defined above? I did previously try addressing “Layer 1” but got a similar error. Maybe addressing it as “Mister Layer 1”? But seriously, there’s something I’m overlooking, sorry!—MM

      • yes, sometimes you’ll resort to pleading (but it doesn’t work)

        with the old versions of InDesign you may need to address the layout window
        (although I would expect set locked to fail as well then ??)

        try :
        tell application id "com.adobe.InDesign"
        tell active document
        -- other bits
        tell layout window 1
        set locked of layer "SLUG" to true
        set active layer to layer -1
        end tell
        end tell
        end tell

        m.

      • G’day AGAIN! I really appreciate the personal attention I’m getting here on my scripting issues, and as such, need to report that 1) the “set active layer…” does not work, even when using the older “layout window 1” (the “set locked layer of SLUG…” DOES work, however); and 2) there are other elements to this slug script I’d like to implement (like forcing the script with a dialog box each time the doc is opened, for example), for which I’d like to offer remuneration, via PayPal, if you’re up for it, because I really hate to take advantage of your knowledge and generosity. I think you have my direct email, if you are so inclined! —MM

      • no worries Matt

        happy to try to help you get where you’re going. that’s why i set up macgrunt in the first place.
        just be aware that i’m an amateur scripter and macgrunt is a side project that i can’t spend time on during work hours — so the going could be slow.
        but, then again, sometimes things come together quickly too — you never know.

        next step with the active layer thing is to stop guessing :-)+)
        in script editor, open up the library panel (window > library)
        if indesign doesn’t appear in the list, hit the plus button to add it.
        open the indesign scripting dictionary (button looks like set of books)
        in the search field (top right) type in “active layer”
        send me a screen grab of what you get.

        we can continue this offline — please email me at macgrunt.au@gmail.com

        there’s a donate button on the site you can hit when you feel you’ve got some value.

        m.

thoughtful and respectful comments welcome

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s