# Quick LaTeX tables using TextExpander

When I want to include a numerical table in a LaTeX document I often already have the data collected together in a Numbers spreadsheet with the desired layout. For example, I might want to go from:

to

The following TextExpander snippet (gist) lets me simply copy the data from Numbers, including the column headers, to the clipboard, and then insert it into a LaTeX document as a nicely formatted table by typing ;ptable:[1]

#!/usr/local/bin/ruby

class Line

@@max_length = nil
@@eol = ' \\\\'

def initialize( data )
@contents = data
@@max_length = [0]*@contents.size if @@max_length.nil? # initialize array if this is the first Line instance
@contents.each_with_index{ |element, i| @@max_length[i] = [element.length, @@max_length[i]].max } # update column widths
end

def to_tex
@contents.zip( @@max_length ).collect { |entry, length| entry.ljust(length).sub(/ \|\$/,'').gsub('&','\\\&') }.join(' & ') + @@eol
end

def define_format
@contents.inject('|'){ |string, entry| /\|/.match(entry) ?  string + 'c|' : string + 'c' } + '|'
end

end

\\begin{table}[htb]
\\begin{center}
\\begin{tabular}{FORMAT} \\hline
END # FORMAT is replaced by a format string generated by define_format

table_footer = <<END
\\hline
\\end{tabular}
\\caption{\\label{tab:NEW_LABEL}CAPTION}
\\end{center}
\\end{table}
END

contents = "%clipboard".split( /[\n\r]/ ).collect{ |line| Line.new( line.split( /\t/ ) )}

puts table_header.sub( 'FORMAT', contents[0].define_format )
puts contents.collect{ |line| line.to_tex }.join("\n")
puts table_footer


Running this snippet with the data shown above produces the following LaTeX code:

\begin{table}[htb]
\begin{center}
\begin{tabular}{|c|c|c|} \hline
A     & B     & C     \\
12.62 & 12.62 & 33.88 \\
3.96  & 4.39  & 4.55  \\
2.00  & 2.30  & 2.56  \\
\hline
\end{tabular}
\caption{\label{tab:NEW_LABEL}CAPTION}
\end{center}
\end{table}


The script assumes centred justification of each column. A limited amount of table formatting can be specified in the Numbers data: any cells in the topmost row can include a pipe character | to indicate that this column should be bounded by a vertical line on the right side, e.g. column 1 | will add a c| format string to the begin{tabular}{FORMAT} code in the LaTeX header via the define_format method.

1. Inspired by a similar workflow by Dr Drang for copying tables from Numbers to Markdown.  ↩