A little table cleanup

One of the things I like about blogging is that blog posts can meander a bit. I don’t have to stay focused on a single topic, as I do when writing a report. Also, I don’t feel the need to know everything I’m going to write about before starting a post. I often leave my text editor mid-paragraph and spend an hour or more checking sources or testing code snippets. That’s not very efficient, but I’m not doing this for money, so efficiency doesn’t matter.

On the other hand, this relaxed approach—especially when combined with writing late at night—sometimes leads me to omit things. Thursday night’s post about tables was a good example of this.

When I started that post, I intended to include another reason why complicated tables are messing up my report-writing workflow: they break the connection between the Markdown source and the rendered PDF. Here’s what happens:

Let’s say I write a report in Markdown with a table that needs some tweaking in LaTeX. I start by including the table in the (Multi)Markdown source, but because of some formatting need, I know I’ll eventually have to dig into the generated LaTeX code for the table and do some editing. Ideally, I’d write all the text of the report first, generate the LaTeX, edit the table portion of the LaTeX, and then make the PDF.

But the ideal never happens. After editing the table and making the PDF of the report, I notice that something in the text of the report needs to be changed. Sometimes a lot needs to be changed. I now have to choose between editing the Markdown source, which means I have to first save the LaTeX source of my carefully crafted table and then paste it back into place every time I regenerate the report LaTeX from Markdown; or abandoning the Markdown source and doing all the subsequent editing in LaTeX.

For a while, I was doing the former because I prefer writing and editing in Markdown—that’s why I’m writing in Markdown in the first place. But the back and forth with the table code was annoying and continually editing two text files often led writing new material in the wrong file. So I’ve switched to the latter approach. Once I’ve had to do any editing of the generated LaTeX, I throw away the original Markdown and work exclusively in LaTeX from that point on.

This is not the way I want to write, and this is another reason I’ve been casting about for a new way to include tables in my reports.

As another followup on Thursday night’s post, I’ve been playing around with making tables in OmniGraffle. Here’s an example:

Bolt table

Not especially complex, but it has both column and row spans and some extra spacing to indicate grouping. Here’s what the layout of the individual items looks like in OmniGraffle:

OmniGraffle table items

This started out as two OmniGraffle tables, one for coarse threads and one for fine, that I filled with the pitch and diameter information (more on that in a bit). I then added the headers and rules and split up the tables—using the Arrange‣Ungroup command—and adjusted the spacing to give a little extra separation between

  1. the pitch column and the three diameter columns; and
  2. the coarse and fine blocks.

Finally, I added the units note just below the bottom rule.

Overall, the it was pretty easy to make in OmniGraffle, especially considering I’ve just learned how its tables work. The most time-consuming part would normally be entering the data, but I got around that by writing this Keyboard Maestro macro that takes a set of tab-separated values (TSV) on the clipboard and enters it into the cells of the OmniGraffle table:

Type in Table macro

There are, as you might expect, a few tricks to this.

First, you can’t just copy a TSV table from a Numbers spreadsheet and paste it into an OmniGraffle table. If you try that, it’ll paste a graphic of the cells you selected in Numbers.

Second, the way you move from cell to cell while editing a table in OmniGraffle is to hit the Tab key. This is probably what you expect for moving across a row; what’s unexpected is that when you’re at the end of a row, Tab also moves you to the first cell of the next row.

Third, when you have an OmniGraffle table selected, hitting the Return key selects the text in the top left cell of the table.

The Keyboard Maestro macro uses these last two tricks to get around the problem posed by the first trick. It assumes I’ve copied a block of cells from a spreadsheet and have selected the table in OmniGraffle. At this point, the clipboard holds at least three versions of that block:

  1. As a block of cells that can be pasted elsewhere in a spreadsheet.
  2. As a graphic (see the first trick above).
  3. As a TSV set of text, with tabs between the cells in each row and a newline character between each row.

The macro manipulates the TSV version of the clipboard, first changing all the newlines to tabs (that accommodates the second trick above) and then trimming the trailing whitespace. Don’t ask me why the trimming is necessary. As far as I’m concerned, there should’t be any trailing whitespace on the clipboard, but when I first wrote this macro—without the trimming step—there was always one last tab.

With the clipboard text now prepared, the macro simulates a tap on the Return key to select the text in the top left cell of the OmniGraffle table (third trick) and then types out all the text on the clipboard. The regular text gets entered in the cells, and the tabs move the selection to the next cell. The key here is the “Insert text by typing” setting in the last action. If that setting were “Insert text by pasting,” all the data from the clipboard would go into the first cell of the OmniGraffle table. It’s the simulation of typing that gets the selection to move from cell to cell.

The upshot is that if I have a table of data in a spreadsheet or some TSV output from a program, I can use this macro to populate an OmniGraffle table without much fuss.

I’m still not sure this is the way I want to handle tables in my reports, but it’s looking promising so far.