Using a command line script to export from OmniGraffle

21 August 2018

From time to time I draw a bunch of diagrams in OmniGraffle, and then need to convert them all to a format I can show in a web page. If I only have one or two, then doing it each time works ok. But if I have a dozen or more, then I find it easier to have a script. That way I can safely export them all whenever I need to.

Fortunately Omnigraffle makes this possible by providing an automation interface which allows me to talk to it via AppleScript. It does change over the years, and needed a couple of hours fiddling to get it to work this morning. So I thought I'd jot down my notes in case anyone else wants to do it.

Eventually there may be a better way to do this. The Omni Group is putting together a richer automation environment that will be callable from JavaScript. As I write this there is no access to the export functionality from JavaScript, so I relied on the AppleScript route instead.

I'm not familiar with AppleScript, and didn't like it much when I have used it. So I like to keep any code in AppleScript to a minimum. I did the usual googling around and cobbled together a small script that exports the current front document. It assumes there's only one canvas in the file, which is true for files I'm working with.

omni2png.scpt…

  on convertGraffleFile(outputFile)
    tell application "OmniGraffle"
      export front document scope "all graphics" as "SVG" to file outputFile
      close front document
    end tell
  end convertGraffleFile
  
  on run argv
     convertGraffleFile(item 1 of argv)
  end run

I want to do all this to all files in a certain folder that match a certain name pattern. Much of this logic I want to have in a familiar language, and ruby is what I use for such scripting.

omni.rb…

  module Omni
    def self.convert_file folder, name
      input = folder + (name + ".graffle")
      return unless input.exist?
      output = folder + (name + ".svg")
      return if FileUtils::uptodate?(output.to_s, [input.to_s])
      system "open #{input}"
      call_conversion(macpath(output))
    end
  
    def self.convert_rgram folder
      convert_file folder, "rgram2"
    end
  
    def self.call_conversion output
      cmd = "osascript lib/omni2png.scpt #{output}"
      result = system cmd
      puts "error processing #{output}" unless result
    end
  
    def self.convert_all_rgrams
      Pathname('catalog').children
        .select {|p| p.directory?}
        .each {|p| convert_rgram p }
    end
  
    def self.macpath arg
      return arg.expand_path.to_s.tr("/", ":")[1..-1]
    end
  end

This code looks at all child directories of catalog, for each one that contains a ggram.graffle exports into a similarly named png file. It only does it if the dates indicate that the png file needs to be rewritten.

You might find it odd that I open the file using a command line call (system) rather opening the file within the AppleScript script. The reason I do that is that sometimes I get irritating errors opening an OmniGraffle document from within AppleScript (it says there's a permission error, but has no trouble if I open it manually or by the command line)


Significant Revisions

21 August 2018: Updated as OmniGraffle changed its export approach to use the new "export" verb (instead of using save)

31 October 2017: Original post