Building an Org-Chart

The work of creating an organization chart dynamically is performed by a series of Omni Automation actions grouped together into a plugin you install into the Automation menu in OmniGraffle.

These scripts do the complex work of looking up the reports for the person represented by the selected graphic, and creating linked-clones of the selected graphic, each with the metadata of one of the manager’s reporting employees.

Very powerful, and fun to use!


DOWNLOAD the Org-Chart Connector OmniGraffle plugin.

To install on macOS, place the unarchived plugin file in the PlugIns folder opened by selecting “Plug-Ins…” from the OmniGraffle Automation menu.

To install on iOS, tap the download link above and choose “Open” from the dialog. In the forthcoming screen, tap “More…” and then “Copy to OmniGraffle” in the popup menu.

The PlugIn’s sub-menu in OmniGraffle’s Automation menu on macOS:


Descriptions of the individual plugin actions:

 1  About This PlugIn… summons a dialog displaying information about the plugin, including identifier string and a link to this documentation.

 2  Display Subordinates uses the metadata keys assigned to the selected graphic, with the stored database JSON to locate and identify the direct reports for the person represented by the graphic. The script then creates linked shapes for each of the reports, and assigns their Employee Name and Employee ID to the created shapes.

 1  Delete Other Diagram Items is used to remove all tagged graphic except the one currently selected.

 1  Show Record for Person switches to FileMaker and displays the record whose data is represented by the currently selected graphic. Note that in order to display the related record in FileMaker, this script creates and executes a fmp:// protocol link using the metdata assigned to the selected graphic. The link triggers the execution of a FileMaker script for looking up a record using an Employee ID.

The Display Subordinates Script

Here is the script for creating subordinate objects:

/*{ "type": "action", "author": "Nyhthawk Productions", "description": "Dynamically creates hierarchic diagrams by displaying the subordinates of the selected hierarchical graphic.", "label": "Display Subordinates", "paletteLabel": "Display Subordinates" }*/ var _ = function(){ var action = new PlugIn.Action(function(selection, sender){ // action code var cnvs = selection.canvas var sourceGraphic =[0] console.log( // get employee ID from user data employeeID = sourceGraphic.userData['Employee ID'] // get JSON from canvas notes var orgJSON = cnvs.background.notes reports = getReportsForID(orgJSON,employeeID) if (reports != []){ console.log('adding subordinates') reports.forEach(function(empID){ empName = getOtherKeyValueForObjWithKeyValue(orgJSON,'Employee ID',empID,'Name') cloneConnectRename(sourceGraphic,empName,empID) }) console.log('performing layout')[0].selection.canvas.layout() if (cnvs.automaticLayout === false){ console.log('bounds of canvas content') var g =[0] var gr = new Group(g) var rect = gr.geometry gr.ungroup() console.log('zoom and center')[0].selection.view.visibleRect = rect[0].centerVisiblePoint = } console.log('select source graphic')[0][sourceGraphic],false) console.log( } }) action.validate = function(selection, sender){ // validation code if( === 1){return true} else {return false} }; return action; }(); _; function getReportsForID(data,empID){ jObj = JSON.parse(data) var reports = [] for (i = 0; i < jObj.length; i++) { jItem = jObj[i] if (jItem['Employee ID'] == empID){ reports = jItem['Reports'] break } } return reports } function getOtherKeyValueForObjWithKeyValue(data,pivotKey,pivotValue,targetKey){ jObj = JSON.parse(data) for (i = 0; i < jObj.length; i++){ jItem = jObj[i] if (jItem[pivotKey] == pivotValue){ return jItem[targetKey] } } return null } function cloneConnectRename(graphic,empName,empID){ cnvs =[0].selection.canvas graphic.allowsConnections = true geo = graphic.geometry offset = 72 clone = graphic.duplicateTo(new Point(geo.minX, geo.maxY + offset),cnvs) line = cnvs.connect(graphic,clone) line.lineType = LineType.Straight if(graphic.strokeColor == null){ lcolor = } else { lcolor = graphic.strokeColor } line.strokeColor = lcolor line.shadowColor = null line.strokeThickness = 4 line.strokeType = StrokeType.Single line.headType = 'Arrow' line.tailType = 'None' clone.setUserData('Employee ID',empID) clone.setUserData('Employee Name',empName) = empName + ' ' + empID clone.text = empName + '\n' + empID cnvs.layout() }

 1-52  The main action code. Note that this version includes a metadata header  1-7  to enable it to be used as a stand-alone solitary action if desired.

 67-76  A supporting function for looking up a record based upon the contents of its unique identifier field. In other words, you could derive the employee’s name by using the employee’s ID.

 78-102  The routine for creating a new diagram object linked from the selected graphic.

Creating an Org-Chart


DOWNLOAD the Org-Chart OmniGraffle template file. Open in OmniGraffle to install.

To create an organization chart, create a new document using the downloaded template. The new document will contain a single graphic. Simply select the top-level graphic and run the “Show Subordinates” script. A new row of graphics will be created.

Next, select one the subordinates and run the script again. A row of graphics representing the subordinates will be created.

Fill in the chart as desired, by selecting solitary graphics and running the script. If there are no subordinates of the represented employee, none will be created.


To start over, select the top-level graphic and run the “Delete Other Diagram Items” script.


In the next section, we’ll examine how to display the source FileMaker for a selected graphic.


This webpage is in the process of being developed. Any content may change and may not be accurate or complete at this time.