InDesign scripting : lesson 33

lesson 32 started looking at how to export individual pages as separate PDFs. it looks like this topic has become popular … a fellow aussie with a passion for getting the most out of InDesign, with a particular focus on prepress, has also written about this, outlining a few solutions — Breaking up is hard to do…

as colmin8r points out, the script from lesson 32 has no user interface, so you can’t control how files are named. that’s what this lesson is all about — extending the script to give you more options. this is how scripts develop — get the basic functionality working, then expand the script to make it more user-friendly, or adaptable, or whatever.

here’s our base script — this time we’re exporting an interactive PDF, rather than using a print PDF preset — but apart from that, it’s the same as the script from lesson 32 :

tell application id "com.adobe.InDesign"
  set raster resolution of interactive PDF export preferences to one hundred forty four ppi
  set (export reader spreads of interactive PDF export preferences) to false
  set mgFolder to file path of active document
  set mgDocName to name of active document
end tell

tell application "Finder"
  if (exists folder "the pdfs" of folder mgFolder) is false then
    make folder at mgFolder with properties {name:"the pdfs"}
  end if
end tell

tell application id "com.adobe.InDesign"

  -- REST OF FUNCTIONALITY WILL GO IN HERE

  repeat with x from 1 to count pages of active document
    set mgPageName to name of page x of active document
    set page range of interactive PDF export preferences to mgPageName
    set mgFilePath to mgFolder & "the pdfs:" & mgDocName & mgPageName & ".pdf" as string
    tell active document
      export format interactive PDF to mgFilePath without showing options
    end tell
  end repeat
  display dialog "ALL DONE!" buttons {"OK"} default button 1
end tell

we’re going to give the user two options — shortening the existing filename by breaking it at the first space or underscore, and the option to add something else to the filename. the code for the dialog looks like this :

  set mgDialog to make dialog
  tell mgDialog
    tell (make dialog column)
      tell (make dialog row)
        make static text with properties {static label:"Where do you want to break the filename?"}
      end tell
      tell (make dialog row)
        set mgDelimiterButtons to make radiobutton group
        tell mgDelimiterButtons
          make radiobutton control with properties {static label:"first underscore", checked state:true}
          make radiobutton control with properties {static label:"first space"}
          make radiobutton control with properties {static label:"full stop", min width:290}
        end tell
      end tell
      tell (make dialog row)
        make static text with properties {static label:"current filename : " & mgDocName}
      end tell
      tell (make dialog row)
        make static text with properties {static label:" "}
      end tell
      tell (make dialog row)
        make static text with properties {static label:"Enter the text you'd like to append."}
      end tell
      tell (make dialog row)
        set mgSuffixField to make text editbox with properties {edit contents:"(can be blank)", min width:250}
      end tell
    end tell
  end tell
  set mgResult to show mgDialog

… and creates a user interface that looks like this :
screen grab of initial user interface
a couple of things to notice … we’ve also added the option of breaking the filename at the first full stop which, if you’re naming your files correctly, means not shortening the filename at all. the dialog also shows the existing filename (in this case “export separate pages_test_file.indd”) to make it easier for the user to make their selections.

the remainder of the code takes the information from the user interface and constructs a new filename to use when saving the PDFs :

  if mgResult is true then
    set mgDelimiterButton to selected button of mgDelimiterButtons
    if mgDelimiterButton is 0 then
      set mgDelimiter to "_"
    else if mgDelimiterButton is 1 then
      set mgDelimiter to " "
    else if mgDelimiterButton is 2 then
      set mgDelimiter to "."
    end if
    
    set text item delimiters of AppleScript to mgDelimiter
    set mgDocName to text item 1 of mgDocName
    set text item delimiters of AppleScript to ""
    
    set mgSuffix to edit contents of mgSuffixField as string
    if mgSuffix is "(can be blank)" then
      set mgSuffix to ""
    end if
    set mgDocName to (mgDocName & "_" & mgSuffix)
    destroy mgDialog
  else
    error number -128
  end if

two things to note here. we’ve added some error handling just in case the user inadvertently leaves “(can be blank)” in the text field of the user interface — we don’t want that to become part of the filename, so we change it to “” (that is, nothing) instead. also, we’re using an underscore to join the shortened filename and the suffix.

hopefully it’s pretty clear how this filenaming works. as an example — if we start with the filename “export separate pages_test_file.indd”, break it at the first space and add the suffix “concepts”, our resulting PDF filenames will be “export_concepts1.pdf”, “export_concepts2.pdf”, etc.

ok, that’s one way you could do it — but you could also make it more complex again by giving the user the option to break the filename in a different place. of course, more complex options mean more complex code. so this :

  set mgDialog to make dialog with properties {name:"Where do you want to break the filename?"}
  tell mgDialog
    tell (make dialog column)
      set mgPlaceButtons to make radiobutton group
      tell mgPlaceButtons
        make radiobutton control with properties {static label:"first", checked state:true}
        make radiobutton control with properties {static label:"second"}
        make radiobutton control with properties {static label:"third", min width:100}
      end tell
    end tell
    tell (make dialog column)
      set mgDelimiterButtons to make radiobutton group
      tell mgDelimiterButtons
        make radiobutton control with properties {static label:"space", checked state:true}
        make radiobutton control with properties {static label:"underscore"}
        make radiobutton control with properties {static label:"full stop", min width:130}
      end tell
    end tell
    tell (make dialog column)
      tell (make dialog row)
        make static text with properties {static label:"current filename : "}
      end tell
      tell (make dialog row)
        make static text with properties {static label:mgDocName}
      end tell
      tell (make dialog row)
        make static text with properties {static label:" ", min width:300}
      end tell
      tell (make dialog row)
        make static text with properties {static label:"Enter the text you'd like to append."}
      end tell
      tell (make dialog row)
        set mgSuffixField to make text editbox with properties {edit contents:"(can be blank)", min width:250}
      end tell
    end tell
  end tell
  set mgResult to show mgDialog

is what you need to create a user interface that looks like this :
screen grab of revised user interface

and the rest of the code is more complex too. this time we’re using the chosen break character to join the filename to the suffix (rather than forcing it to be an underscore) :

  if mgResult is true then
    set mgPlaceButton to selected button of mgPlaceButtons
    if mgPlaceButton is 0 then
      set mgPlace to "1"
    else if mgPlaceButton is 1 then
      set mgPlace to "2"
    else if mgPlaceButton is 2 then
      set mgPlace to "3"
    end if
    set mgDelimiterButton to selected button of mgDelimiterButtons
    if mgDelimiterButton is 0 then
      set mgDelimiter to " "
    else if mgDelimiterButton is 1 then
      set mgDelimiter to "_"
    else if mgDelimiterButton is 2 then
      set mgDelimiter to "."
    end if
    
    set text item delimiters of AppleScript to mgDelimiter
    try
      set mgDocName to text items 1 thru (mgPlace + 1) of mgDocName
      set mgDocName to text items 1 thru mgPlace of mgDocName
    on error
      display dialog "come on dude — that's not possible" & return & "there are not " & mgPlace & " \"" & mgDelimiter & "\" in the filename" & return & return & "have another go" buttons "sorry"
      error number -128
    end try
    set mgDocName to mgDocName as string
    set text item delimiters of AppleScript to ""
    
    set mgSuffix to edit contents of mgSuffixField as string
    if mgSuffix is "(can be blank)" or mgSuffix is "" then
      set mgSuffix to ""
      set mgDocName to (mgDocName & mgSuffix)
    else
      set mgDocName to (mgDocName & mgDelimiter & mgSuffix)
    end if
    destroy mgDialog
  else
    error number -128
  end if

so this time — if we start with the filename “export separate pages_test_file.indd”, break it at the second space and add the suffix “concepts”, our resulting PDF filenames will be “export separate concepts1.pdf”, “export separate concepts2.pdf”, etc.

notice in the above code we’ve added some error handling to make sure the user’s choices make sense. that is, if they choose to break the filename at the third space, and there are not three spaces in the filename, rather than the script simply failing, they’ll get a message stating why it’s not going to work :
screen grab of error message presented to user

and, of course, you can keep on expanding the script until you have as many different options as suits your needs.

the next lesson will look at a couple of other ways we could approach the naming of these separate page PDFs — automatically generating filenames based on data already existing in the document.

until then, keep grunting.

macgrunt icon

InDesign scripting : lesson 11

this is the fourth in a series of lessons on exporting pdfs using applescript. lessons 08 and 09 showed how to export all open InDesign files at once. this next script will create separate pdfs for different page ranges within the one document. this is really handy in a publishing environment where you often export just portions of a file, rather than the whole document.

as with the first script, this one begins by creating an interface to get user input. InDesign offers scripters an excellent range of UI elements — this dialog has two sets of radio buttons and a text edit field. copy this into your script editor (found in applications > applescript) :

tell application "Adobe InDesign CS4"
  activate
  set mgDialog to make dialog with properties {name:"This script exports specified pages as separate PDFs"}
  tell mgDialog
    tell (make dialog column)
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Export preset to use :    "}
        end tell
        tell (make dialog column)
          set mgExportButtons to make radiobutton group
          tell mgExportButtons
            make radiobutton control with properties {static label:"Press Quality", checked state:true}
            make radiobutton control with properties {static label:"Inhouse Printing"}
            make radiobutton control with properties {static label:"Screen Resolution"}
          end tell
        end tell
      end tell
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Page range to export :    "}
        end tell
        tell (make dialog column)
          set mgPageRange to make text editbox with properties {edit contents:""}
        end tell
      end tell
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Export spreads as :    "}
        end tell
        tell (make dialog column)
          set mgSpreadsButtons to make radiobutton group
          tell mgSpreadsButtons
            make radiobutton control with properties {static label:"Separate pages", checked state:true}
            make radiobutton control with properties {static label:"Spreads"}
          end tell
        end tell
      end tell
    end tell
  end tell
  set mgResult to show mgDialog
end tell

that script gives you a dialog something like this :
screen grab of user interface created by script

well, that’s OK, but it’s a bit fugly. to get things lining up, you need to specify some minimum widths. the static text elements should all be the same width, and the interactive elements should all be the same width :

tell application "Adobe InDesign CS4"
  activate
  set mgDialog to make dialog with properties {name:"This script exports specified pages as separate PDFs"}
  tell mgDialog
    tell (make dialog column)
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Export preset to use :    ", min width:170}
        end tell
        tell (make dialog column)
          set mgExportButtons to make radiobutton group
          tell mgExportButtons
            make radiobutton control with properties {static label:"Press Quality", checked state:true}
            make radiobutton control with properties {static label:"Inhouse Printing", min width:150}
            make radiobutton control with properties {static label:"Screen Resolution"}
          end tell
        end tell
      end tell
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Page range to export :    ", min width:170}
        end tell
        tell (make dialog column)
          set mgPageRange to make text editbox with properties {edit contents:"", min width:150}
        end tell
      end tell
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Export spreads as :    ", min width:170}
        end tell
        tell (make dialog column)
          set mgSpreadsButtons to make radiobutton group
          tell mgSpreadsButtons
            make radiobutton control with properties {static label:"Separate pages", checked state:true}
            make radiobutton control with properties {static label:"Spreads", min width:150}
          end tell
        end tell
      end tell
      make static text with properties {static label:" "}
      make static text with properties {static label:"Commas = separate PDFs (eg. 1, 2, 3, 4 gives four PDFs)"}
      make static text with properties {static label:"Hyphens = the same PDF (eg. 1, 2-3, 4 gives three PDFs)"}
    end tell
  end tell
  set mgResult to show mgDialog
end tell

notice how the static text elements align right by default — you just have to get used to it because there’s no way around it. this version of the dialog also has a couple of hints for the user at the bottom :
screen grab of revised user interface

aawww — nicer. ok, now to capture the results of the dialog. you’ll remember from lesson 08 that you have to check that the ‘OK’ button is clicked, that radio buttons are numbered from 0 and that this is where you must use the exact name of your pdf export presets (case sensitive). this portion of the script comes immediately before the last end tell :

  if mgResult is true then
    set mgExport to selected button of mgExportButtons
    set mgPageList to edit contents of mgPageRange as string
    set mgSpreads to selected button of mgSpreadsButtons
    destroy mgDialog
  else
    destroy mgDialog
    error number -128
  end if
  
  if mgExport is 0 then
    set mgExport to "Offset Printing"
    set mgSubFolder to "Prepress Files"
  else if mgExport is 1 then
    set mgExport to "Xerox Printing"
    set mgSubFolder to "Xerox PDFs"
  else if mgExport is 2 then
    set mgExport to "[Smallest File Size]"
    set mgSubFolder to "Low Res PDFs"
  end if
  if mgSpreads is 1 then
    set mgSpreads to "true"
  end if

  set text item delimiters of AppleScript to " "
  set mgPageList to text items of mgPageList
  set text item delimiters of AppleScript to {""}
  set mgPageList to mgPageList as string
  set text item delimiters of AppleScript to ","
  set mgPageList to text items of mgPageList
  set text item delimiters of AppleScript to ""

now, you’ll understand most of that because you studied lesson 08 so well. here’s an explanation of that last bit where we process mgPageList through three coercions… imagine your user is a keyboard hack — a really shocking typist who enters this in the text editbox :

"1, 2-3, 14 -15, 26 - 27,   38,   49  "

you could just let them suffer and have the script fail, or you could take pity on them and add some processing to make everything right. the first coercion above gives you this monstrosity :

{"1,", "2-3,", "14", "-15,", "26", "-", "27,", "", "", "38,", "", "", "49", "", ""}

but don’t panic, because the second coercion renders this :

"1,2-3,14-15,26-27,38,49"

and the third coercion makes it all ok. a nice neat list, each item of which will be its own pdf. this example will export six pdfs :

{"1", "2-3", "14-15", "26-27", "38", "49"}

well, that’s it for now. we’ll complete this script in the next lesson. the finished script will add the page ranges to a truncated version of the filename — so exporting from “54321 ThisFile Name.indd” gives a pdf named, for example, “54321 ThisFile_2-3.pdf”. you’ll learn how flexible that process is — so you can tailor the renaming to your specific needs.

until then, keep grunting.

go to lesson 12

macgrunt icon

InDesign scripting : lesson 08

this is the first of a series of lessons on exporting pdfs using applescript in script editor (found in applications > applescript). the end result of the first two lessons will be a script that will export all your open InDesign files while you go off to get a hot bevvie — rather than you having to sit there exporting each file individually. the script relies on pdf presets — you can use your own, or the defaults, or both.

first we’ll build a user interface (UI) which will ask you to select a pdf export preset. InDesign offers scripters an excellent range of UI elements — text fields, check boxes, dropdowns and, in this case, radio buttons. here is a very simple version of a UI and the script to produce it :

screen grab of simple export pdfs user interface

tell application "Adobe InDesign CS4"
  activate
  set mgDialog to make dialog with properties {name:"Export preset to use :  "}
  tell mgDialog
    make dialog column
    tell the result
      set mgExportButtons to make radiobutton group
      tell mgExportButtons
        make radiobutton control with properties {static label:"Press Quality", checked state:true}
        make radiobutton control with properties {static label:"Inhouse Printing"}
        make radiobutton control with properties {static label:"Screen Resolution"}
      end tell
    end tell
  end tell
  show mgDialog
end tell

the basic structure is this : make dialog > put stuff in the dialog > show dialog. the observant will notice that in order to put stuff in a dialog you first need to make a dialog column. if you miss this step, it ain’t gonna work. you’ll also notice that you need to make a radiobutton group to contain the individual radiobutton controls. if you scroll right, you’ll see that you can set which of the radio buttons will be highlighted by default. you can add a bunch more radio buttons if you like, and you can label them however suits you — the labels do not have to exactly match the names of your pdf export presets — that bit comes later.

InDesign also let’s you play around with the layout a bit too — to give your UI windows a bit more presence. this comes in handy later when you start building more complex dialogs :

screen grab of export pdfs user interface

this version of the dialog has three dialog columns : the first one has a border around it and contains the other two ; the second contains the text “Export preset to use : ” ; and the third contains the radio buttons. here’s how to script it :

tell application "Adobe InDesign CS4"
  activate
  set mgDialog to make dialog with properties {name:"Export all open PDFs"}
  tell mgDialog
    tell (make dialog column)
      tell (make border panel)
        tell (make dialog column)
          make static text with properties {static label:"Export preset to use :  "}
        end tell
        tell (make dialog column)
          set mgExportButtons to make radiobutton group
          tell mgExportButtons
            make radiobutton control with properties {static label:"Press Quality", checked state:true}
            make radiobutton control with properties {static label:"Inhouse Printing"}
            make radiobutton control with properties {static label:"Screen Resolution"}
          end tell
        end tell
      end tell
    end tell
  end tell
  show mgDialog
end tell

this script uses the form “tell (make dialog column)” instead of “make dialog column > tell the result”. choose whichever suits you — one’s easier to understand, the other requires less lines of code.

next we need to capture the results of the dialog. first we need to determine which of the two buttons was clicked — ‘ok’ = true and ‘cancel’ = false. there are different ways to handle these two possibilities, here’s one — it goes immediately after show mgDialog, before that last end tell :

if result is true then
  set mgExport to selected button of mgExportButtons
  destroy mgDialog
else
  error number -128
end if

if the result is true then the ‘ok’ button was clicked — in which case we capture the radio button selected into a new variable (mgExport), ready for further processing. if the result is false then the cancel button was clicked — in which case we tell the script to quit immediately (error number -128). it’s good to get in the habit of destroying a dialog once you’ve captured the data you need. this prevents funky things happening in scripts that reference multiple dialogs.

ok, finally, we need to tell the script what to do, depending on the radio button selected. radio buttons are numbered from zero — so, for this script, mgExport could be 0, 1 or 2. again, this goes before the last end tell :

if mgExport is 0 then
  set mgExport to "Offset Printing"
  set mgSubFolder to "Prepress Files"
else if mgExport is 1 then
  set mgExport to "Xerox Printing"
  set mgSubFolder to "Xerox PDFs"
else if mgExport is 2 then
  set mgExport to "[Smallest File Size]"
  set mgSubFolder to "Low Res PDFs"
end if

here is an example of how you can change the value of a variable — mgExport starts as a number (0, 1 or 2) but gets changed to the name of an export preset. this is where we have to use the exact name (case sensitive) of the Adobe PDF export preset. notice that default presets need to be in square brackets — that’s exactly as they are in the InDesign menu. the other thing we are doing here is setting the name for the folder the final PDFs will be saved in. this folder doesn’t have to already exist — the script will create it if it’s not there already.

ok, that’s it for the first part. we’re actually more than half way through. the next lesson will cover the guts of the export process.

go to lesson 09

macgrunt icon