Automating Ai Illustrator with AppleScript

For the last few days I’ve been enjoying–perhaps ‘enjoying’ is the wrong word–revelling in a blast from the past, AppleScript.

AppleScript occupies a special place in my heart, because AppleScript is the language that introduced me to programming.  It seems I spend all my time programming in C and C++, and learning Swift these days, but alas I find all of those languages lacking when it comes to soft-automation. So it seems AppleScript has risen from the dead and reared its simplistic, yet surprisingly versatile head once again. (Plus, now that I have learned so much C, C++ and Swift, I’ve brought a much more formulaic style to my new AppleScript.)

So, the premise.

I have been asked to do some topological surveys, and then draw up those surveys using Illustrator. I, however, do not want to spend a hundred years learning Illustrator, nor do I want to spend a hundred years drawing up survey maps. I do, however, have a great interest in automation, and while I cannot currently automate the actual survey itself (although I have some ideas about that), I have managed to automate a good deal of the Illustrator work. And it’s taken me less than a week. . . there’s still a bit to do, mind you, but progress is progress and that’s an end of it!

So, the problem.

I had assumed that the main problem would be having to learn how to use Adobe’s “Actions”, which is Adobe’s version of OS X Automater as far as I could tell, but I quickly decided that I couldn’t be bothered with that. The little time I did spend looking into them revealed that they weren’t nearly as variable and automatic as I wanted them to be.

Having used AppleScript before to control other applications, I was pleased to discover that Adobe programmes have extensive AppleScript support. The next problem was tackling Adobe’s 317 page Adobe-AppleScript documentation.

For the sake of argument, let’s assume that I read that document.

Moving on.

Whilst dicking about in Illustrator, I discover that Illustrator operates on an invisible grid of Points (pts). I also find that the top left of a document is point x=0, y=0. This means that if you move right along the x-axis, the x-coordinate increases, but as you move down along the y-axis, the y-coordiate decreases. This means that the centre of an A4 page looks like this {x=297.64, y=-420.945} (Illustrator’s toolbar tells you that the y point is actually positive, but that is a lie.)

I find this whole points business slightly irritating because while I am aware that I can change the units from points to millimetres in the preferences, that change doesn’t make any difference if you are controlling Illustrator with AppleScript, you simply must use pts. No matter, I’ll just have to convert all my mm to pts by dividing by 0.352777777778.

That, dear reader (who definitely exists and isn’t just me in the future re-reading this), is far from the end of the problems, no, no.

In fact the problems are so great that really, the best way to deal with them is to use Excel.

I’m not going to go into too much detail covering the workings of the spreadsheet, because let’s face it, most people don’t like spreadsheets. I, on the other hand, quite like spreadsheets, but I shall spare you the toil of trying to seem interested in something you don’t care about.

So, the spreadsheet.

My spreadsheet is beautiful. There, I said it.

I, unlike most people, was delighted to discover that Excel can handle IF statements. In fact I discovered that you can chain up to seven of them to create IF ELSE statements. Up until now I had never had any call to use Excel’s IF formulas, and if in the past I did have reason to use them, I guess I just thought that Excel couldn’t do IF statements. But now that I have found that out, by golly have I used them to death in this marvellous spreadsheet. For example, one of my IF statements looks like this:

=IF(A2="h","r",IF(A2="d","o",IF(A2="c","o",IF(A2="r","o","l"))))

Work that out if you will! Brackets, it’s actually very simple, close brackets. And that’s not even a long one, there’s one that uses up the whole formula bar, and I have a 23″ screen so that takes some doing.

Anyway, while the spreadsheet is massive and somewhat unwieldy, it is actually quite simple because it’s just the same thing over and over again.

So we’ll look at one row from each of the sheets.

Sheet 1.

So, sheet 1.

Sheet 1 is the “Input” sheet. This is where you (I) enter the survey measurements.

A2: The measurement type. In this cell you put one of the following letters {h, l, r} (that’s a lower case L). (In the future there will also be {c, d, i}.

h: House. This is a measurement of type House. By default it is a running measurement, meaning subsequent h’s need to have the preceding h’s value deducted from there own.

l: Line. This is a measurement of type Line. Horizontal only (for now)

r: Radius. This is a measurement of type Radius. By default its height == its width, but this can be overridden.

c: Will be Circumference.

d: Will be Diameter.

i: Will be Intersect–“Chuck! No!”

B2: The measurement name. This can be anything you want, but certain single letters provide default values for height.

C2: Width in millimetres.

D2: Height in millimetres.

E2: Running? Whether or not the measurement is part of a running measurement, or is an independent measurement. Values are {S, y, n}.

S: Start a new running measurement here.

y: Continue from previous running measurement.

n: Independent measurement, not part of previous running measurement.

F2: Shape. The object to be drawn is of shape {r, l, o}.

r: Rectangle. Anchor A = Bottom Left corner. Anchor B = Top Right corner. Anchor C = Top Left corner. Anchor D = Bottom Right corner.

l: Line. Anchor A = Left most corner. Anchor B = Right most corner.

o: Circle. Anchor A = An invisible point at the top left of a square that surrounds the circle. Anchor O = Centre point of the circle.

G2: Draw. Draw is currently unused, but remains as a remnant.

H2: Most Important Anchor First. Which anchor point on this new object is the most important?

a, b, c, d: Anchor points respectively.

!: If !, then use spreadsheet defined default anchor points.

I2: Connect to Previous Anchor. Which anchor of a previous object should the most important anchor of the new object connect to?

a, b, c, d: Anchor points respectively.

n: Do not connect to a previous object’s anchor.

J2: Triangulation Point. Do you want to generate a new Triangulation Point?

y, n: Yes, no. (No is optional).

K2: Triangulation Name: If you are creating a new Triangulation Point (or you are trying to connect to a Triangulation Point) Name that point here.

A thru G.

L2: Centre on Anchor. If you are creating a new Triangulation Point, which Anchor of the new object should become the Triangulation point?

a, b, c, d: Anchor points respectively.

M2: Running Total. If the measurement is part of a running total, subtract the previous measurement from this one.

N2: Colour. What colour should this new object be?

Sheet 2.

So, sheet 2.

Conversion.

Columns A thru E are copies of columns from sheet 1, namely: Type, Name, Width, Height & Running Total.

F2: Width (pts). Width, but converted into points. ((Width/Scale) / 0.352777777778).

G2: Height (pts). As above.

H2: Running Total (pts). As above.

Sheet 3 & 4.

So, sheet 3 & 4.

Quadrilaterals & Lines.

Sheet 4 is a duplicate of sheet 3. It exists for the sake of clarity as each sheet has different Conditional Formatting.

Everything on sheets 3 & 4 is in pts.

A2: Ax Anchor. The X Anchor for Point A on the new object.

B2: Ay Anchor. The Y Anchor for Point A on the new object.

C2: Bx Anchor. The X Anchor for Point B on the new object.

D2: By Anchor. The Y Anchor for Point B on the new object.

E2: Bx Anchor (offset). The X Anchor for Point B on the new object offset to account for elongation.

F2: Cx Anchor. The X Anchor for Point C on the new object.

G2: Cy Anchor. The Y Anchor for Point C on the new object.

H2: Dx Anchor. The X Anchor for Point D on the new object.

I2: Dy Anchor. The Y Anchor for Point D on the new object.

J2: Centre X Anchor. The X Anchor for Point O on the new object.

K2: Centre Y Anchor. The Y Anchor for Point O on the new object.

L2: Triangulation Point X Anchor. The X Anchor for the designated triangulation anchor on the new object.

M2: Triangulation Point Y Anchor. The Y Anchor for the designated triangulation anchor on the new object.

Sheet 5.

So, sheet 5.

Ellipses.

Columns A thru M are identical to those in sheets 3 & 4. Again, this is due to differences in Conditional Formatting.

N2: Diameter.

O2: Land Centre Anchor on. A column to aid readability.

P2: X. The X coordinate of the Centre anchor without taking into account offsetting for triangulation.

Q2: Y. The Y coordinate of the Centre anchor without taking into account offsetting for triangulation.

R2: Offset Correction. An empty column.

S2: X. The post triangulation offset for the X coordinate.

T2: Y. The post triangulation offset for the Y coordinate.

Sheet 6.

So, finally, sheet 6.

Triangulation Points.

This sheet is filled in only by the AppleScript. It reads sheet 1 to find triangulation points, then saves those points as cell references in sheet 6 for use by sheet 5.

So, the maths.

There is a lot of maths going on in this spreadsheet. Originally I was trying to do it within the AppleScript, but that got far too complicated far too quickly, so after 4 days of doing that and getting nowhere, the marvellous spreadsheet was born. Taking all the maths away from the AppleScript was the best thing to do, but that meant that I now had to work out all the grid anchors for each measurement in every shape, and that is why there are six sheets.

In sheets 3 & 4, you may have noticed (if you hadn’t keeled over by that point) this line about offsetting:

E2: Bx Anchor (offset). The X Anchor for Point B on the new object offset to account for elongation.

That sounds complicated, but really all it means is this: “move the X anchor of Point B left by a specified amount to account for the running measurement”.

In fact, the Y-axis stabilisation offset is arguably more important, and yet I haven’t even mentioned it, because it would bore you to tears. In short, the By Anchor points for all the type h shapes must be the same. If they aren’t you end up drawing a house that looks like the side profile of a set of stairs, and nobody wants that.

A similar thing happens in sheet 5, only this time we are stabilising for both X and Y offsets. Shapes that come out of sheet 5 use both of the stabilised anchors. Shapes that come out of sheets 3 or 4 may or may not use both stabilised anchors.

But this is getting tedious now.

So, the AppleScript.

The AppleScript is also beautiful, although not terribly efficient, but then again, it’s not finished, so there’s still plenty of time for that.

Considering how large the spreadsheet is, the AppleScript is very small.

Ignoring all the housekeeping, we simply run a loop for as many times as there are rows of usable data. This is why empty cells in the A column of sheet one contain “eof” (end of file).

The script begins by reading one row of data from sheet 1, saves some of that information and, based on whether is needs to draw a rectangle, a line or a circle, it then reads one row of information from either sheet 3, 4 or 5.

(I am missing steps out, even I tire of this now).

So, long story short.

The important things you need to know if you are trying to automate Adobe Illustrator using AppleScript are as follows:

Draw a line:

make path item at layer "Layer 1" with properties {entire path:{{Ax, Ay}, {Bx, By}}, stroke width:2, name:"Line", stroke color:{red:0.0 thru 255.0, green:0.0 thru 255.0, blue:0.0 thru 255.0}}

Draw a rectangle:

make new rectangle at layer "Layer 1" with properties {name:"Rectangle", bounds:{Ax, Ay, Bx, By}, stroke color:{red:0.0 thru 255.0, green:0.0 thru 255.0, blue:0.0 thru 255.0}}

Draw a circle:

make new ellipse at layer "Layer 1" with properties {name:"Circle", position:{Ax, Ay}, width:100.0, height:100.0, stroke color:{red:0.0 thru 255.0, green:0.0 thru 255.0, blue:0.0 thru 255.0}}

So, the limitations.

There are limitation of this current build, and that is one of the reasons I am not making this script or spreadsheet public.

1. Objects will only be drawn left to right.

2. Triangulation circles must be intersected by hand.

To name just a couple.

Also, I’m being paid to draw these surveys, so I’m hardly going to make my automation tools public. I will however, share this video of the script drawing a plan.

Author: Dan

Share This Post On