# Some OmniGraffle automation

As if I weren’t already subscribed to more podcasts than I could possibly listen to, along come David Sparks (of Mac Power Users and countless instructional videos and books) and Rosemary Orchard (of Automation Orchard and countless posts in the MPU and Drafts forums) with a new podcast about automation on Apple devices. I’m not sure what I’ll have to squeeze out to fit this one in, but I will.

As a sort of inverse tribute to David and Rosemary, who provide automations with broad appeal across all sorts of Mac and iOS users, this post is about a pair of recent automations that appeal basically to me. With luck, though, they may trigger ideas for you to create similar automations that solve your own specific problems.

Let’s start with the simpler one. I deal with architectural and engineering drawings quite a bit at work. They usually come to me as PDFs, whether scanned or generated directly from CAD. When I need to have a discussion about them, I drop the PDF into an OmniGraffle document and use OG’s tools to mark up the parts I have questions or comments about. Then I export the annotated document out as a PDF so my client can view it.

Exporting an OmniGraffle document as a PDF is a straightforward and quick process, one that I’d never thought about automating until recently, when I had about two dozen marked-up drawings that I needed to export as PDFs. I wasn’t concerned with the time it would take, but I was pretty sure I’d screw something up during the mindlessly repetitive clicking and tapping I’d need to do. So I made a Keyboard Maestro macro to do it for me. It didn’t do the job faster than I could have by hand, but it didn’t make any mistakes or forget to export any of the drawings.

Here’s the macro:

This started out as a macro that exported just one file. After I got that working, I wrapped those steps in the action that loops through all the selected files.

There are only a few tricky things in this macro:

• The pauses at several points in the macro are needed to allow OmniGraffle to catch up. It takes time to open files, bring up the export sheet, and so on, and a macro without pauses wouldn’t work. I could probably cut down on some of these delays, but it didn’t seem worth the effort to do so.
• The target image for the first click in the export sheet, telling OmniGraffle to export to PDF, is cropped very tightly to make sure it’s recognized. As you can see below, the icon for the selected format has a darker background than the others. If I included one of those backgrounds in the target image, the target wouldn’t be recognized if it had the other background.
• Similarly, the target image for the export area selection has to be the descriptive text next to the popup menu, not the popup menu itself, because the text in the popup menu changes depending on which export area was last selected. One of OmniGraffle’s clever features is the ability to direct the click some distance away from the target image; I took advantage of that here.
• After clicking the export area popup menu, the menu item is chosen by typing the first letter (or first few letters, if necessary) of the menu item and the Return key.

Because of all the pauses, this macro takes a while to run when there are a lot of files to convert. But it does the job more accurately than I can. And now that I’ve made it, I’ll use it even when I don’t have dozens of documents to convert.

The second piece of automation is an AppleScript and is also needed because of the way I use OmniGraffle to mark up drawings.

Quite often, I need to go through the drawings for a building and identify where certain features or components are located. After that, I need to provide a count of all these items. I do the identifying and locating by marking the items with circles or boxes, as in this drawing.

Here I’m marking up a plumbing drawing, showing where the valves are. The different sizes of valve have been given different colors and the circles that identify them are kept in separate layers. This is a convenient way of organizing things while I’m working on the markup, and it makes the process of counting easier.

But when I have dozens of drawings and dozens of items on each drawing, I don’t trust myself to do the counting without making mistakes. Luckily, computers are really good at counting. Here’s the AppleScript I use to count all the different parts on all the drawings:

applescript:
1:  -- Create the file for the results
2:  tell application "Finder" to set theFolder to target of front Finder window as alias
3:
4:  set fileRef to choose file name with prompt ¬
5:    "Valve count file:" default name ¬
6:    "valve-count.txt" default location theFolder
7:  open for access fileRef with write permission
8:
9:  -- Initialize the output string
10:  set output to ""
11:
12:  -- Get a list of all the files of interest.
13:  tell application "Finder"
14:    set FPFiles to the selection as alias list
15:  end tell
16:
17:  -- Count the circles in each layer of each drawing.
18:  repeat with f in FPFiles
19:    tell application "OmniGraffle"
20:      open f
21:      delay 3
22:      tell front document
24:        set output to output & name & linefeed
25:        tell front canvas
26:          -- The bottom layer has the highest number and contains
27:          -- only the drawing, no circles.
28:          repeat with i from 1 to ((count of layers) - 1)
29:            tell layer i
30:              set sCount to count of graphics
31:              -- Add the layer name and count. Skip empty layers.
32:              if sCount > 0 then
33:                set output to output & name & ": " & sCount & linefeed
34:              end if
35:            end tell
36:          end repeat
37:        end tell
38:        close
39:        set output to output & linefeed
40:      end tell
41:    end tell
42:  end repeat
43:
44:  -- Write and close the file.
45:  write output to fileRef
46:  close access fileRef


Line 2 gets the folder that contains all the selected drawings. Lines 4–6 ask the user for a file in that folder in which to save the counts. Line 7 then opens that file for writing.

Lines 13–15 create a list of all the selected files. This will be the list we loop through starting on Line 18.

For each file in the list, we open the file and loop through all the layers, getting the count of the graphic items in each layer. The output string, which was initialized to the empty string in Line 10, gets updated with each new file name and item count as we work our way through the two loops. When the outer loop is done, Line 45 writes the output string to the file we opened in Line 7, and Line 46 closes the file.

OmniGraffle numbers the layers from top to bottom. Since the bottom layer is the drawing, we don’t need to include its item count, which is why the upper limit on the repeat loop in Line 28 is one less than the number of layers.

I sometimes make layers that end up not getting used. Because I have no interest in reporting counts of zero, the condition in Line 32 filters those out.

The output of the script looks like this:

P101
.75 in: 1
1.5 inch: 4
2 inch: 6
4 inch: 12
6 inch: 2

P102
.75 in: 3
1.5 inch: 2
2 inch: 12
4 inch: 16
6 inch: 4


If I need to do further processing of the counts, this format is easy to parse.

We all know the XKCD comic about the false efficiency of automation, but automation is at least as much about accuracy and repeatability as it is about efficiency. No one thinks it’s wrong to put in more time to get more accurate and trustworthy results.