Re: Bulk replacement of text from spreadsheet or text file (& Python)

Wim Lewis <[email protected]>
Newsgroups gmane.comp.graphics.omnigraffle.user
Message-ID <[email protected]>
On Jan 7, 2009, at 5:29 AM, Mark Barclay wrote:
> Thanks so much, Wim. Those are great suggestions! I especially like  
> the DOT
> import idea - that opens up a lot of possibilities for getting some
> hierarchical formatting almost for free.

DOT is really handy for this; it's my usual way of getting data into  
OmniGraffle if I just want to quickly visualize some graph or structure.

> since I know Python pretty well and like it very much (but have not  
> used it
> on the Mac), I think I'll try the Python way. I have XCode installed  
> and
> have looked briefly at its Python support. So...
>
> Can anyone please point me to some python sample code that connects  
> through
> AppleScript, to a running instance of OmniGraffle, and creates a  
> rectangle
> with the word "foo" as it's text? In fact any sample code at all  
> that talks
> to OG would be a great starting point - I'm sure I could figure out  
> the
> specifics of creating objects easily from there.

There is, as the Perl folks say, more than one way to do it. Probably  
the simplest-to-implement way is to create an AppleScript script using  
any tool you like, and pipe it into the 'osascript' command-line tool.  
You can get an idea of how to produce various results by mocking them  
up in an OmniGraffle document and then using 'Edit>Copy  
As>AppleScript'. (The generated script isn't always perfect, but I  
find it to be a good starting point.)

Or you can convert your data to some format that you can deal with  
more directly in AppleScript --- Ian Piper's XML importer is a good  
example of that.

I'm really fond of the "appscript" module in Python (it has  
equivalents in Ruby and, I think, Perl). It lets you talk AppleEvents  
directly, without an AppleScript layer in between, but still lets you  
use the textual names supplied by the application's AppleScript  
dictionary rather than cryptic AppleEvent FourCharCodes.

(A little bit of explanation: AppleScriptable applications don't  
actually run an AppleScript interpreter. They respond to AppleEvents,  
which are sort of language-neutral --- originally, they were intended  
to be both programming-language-neutral and human-language-neutral.  
The AppleScript interpreter (which is not running in the target  
application, but instead running inside Script Editor or osascript or  
another application) handles the control flow, variables, and so on,  
as well as mapping the human-language class and property names to the  
32-bit identifiers used in AppleEvents.)

So, anyway, here's an example of using appscript:

from appscript import *
og = app('OmniGraffle Professional 5') # lots of ways to specify the  
application, check the appscript docs
ogdoc = og.make( new = k.document )
# The 'new' argument indicates the class of object to create a new  
instance of
# the 'k' object is how to specify application scripting terminology  
keywords in python; they're resolved to 4CCs when the event is  
actually sent
# At this point ogdoc is something like: app('/Applications/Local/ 
OmniGraffle Professional 5.app').documents[u'Untitled']
c = ogdoc.canvases[0]   # the document's (only) canvas, for convenience

# Make a couple of shapes
shape1 = c.make( new = k.shape );
# -->  app(...).documents[u'Untitled'].canvases.ID(1).graphics.ID(3)
# also try shape1.properties() here to see all its properties
shape1.size.set( [ 35, 35 ] )
shape1.text.set( 'I am shape 1' )
shape1.name.get()  # returns 'Rectangle', the default shape

shape2 = c.make( new = k.shape, with_properties = { k.name : 'Circle',  
k.autosizing: k.full, k.text: 'Shape #2' } )
shape2.draws_shadow.set( k.false )

# connect them. This is an example of sending a command other than  
make/get/set.
connection = shape1.connect( to = shape2 )
# returns the connecting line graphic
# --> app(...).documents[u'Untitled'].canvases.ID(1).graphics.ID(5)
connection.head_type.set( 'Arrow' )

# lay out the result
c.layout()

# save the document
ogdoc.save( )    # brings up a save panel since it's Untitled
# or: ogdoc.save( in_ = '/tmp/something' )  # saves it to /tmp/ 
something.graffle

# an example of exporting the document
og.current_export_settings.area_type.set( k.all_graphics )
ogdoc.save( in_ = '/tmp/woo', as_ = 'PNG' )


Appscript is here:
     http://appscript.sourceforge.net/py-appscript/

One thing to be careful of is that these Python variables, like  
AppleScript variables, hold object specifiers, not "hard" references  
to actual objects. So if you have a variable that specifies a document  
or canvas by name, for example, and you save it to another filename,  
that variable will no longer be useful (you'll get a "can't get  
reference" error, IIRC). Some kinds of specifiers, like ID specifiers,  
are more persistent than others.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.