# Convert table in LaTeX

I copy the table from Calc (or Tracker)

In my research I know three ways:

1: Record a macro: @a0f cw & <ESC>;.;.I\hline <ESC>A \\ (the spaces count ;) )
And then VG:normal @a<ENTER>

2: VG:s/ / \& /gv:<UP><ENTER>gv:<UP><ENTER>
and then other macro for the \hline and \\

3: f <C-v>kkk23jc & <ESC>;.;.
And again I\hlineA \\<ESC>

Is there another way?

Sample input:

0.79    0.80    5.40    6.48
0.86    0.87    4.57    5.81
0.93    0.94    4.04    5.32


Output:

\hline 0.79 & 0.80 & 5.40 & 6.48 \\
\hline 0.86 & 0.87 & 4.57 & 5.81 \\
\hline 0.93 & 0.94 & 4.04 & 5.32 \\

-
Do you have a short sample of input and wanted output? –  Sukminder Mar 30 '13 at 6:35
Thanks @Sukminder, there is :). In the 3er way, 23 represent the number of lines (I reduce the number of lines to three in the i/o) –  David Mar 30 '13 at 6:40
I may be missing something (what kind of macros is that? for LibreOffice Calc or the like?), but what about exporting to CSV and then running sed on the CSV? –  njsg Mar 30 '13 at 7:46
@njsg: Q is tagged vim. –  Sukminder Mar 30 '13 at 8:02
What about exporting to CSV and reading in the file directly with LaTeX instead of converting it to LaTeX tables? That way changing the data is much easier, too. –  Marco Mar 30 '13 at 10:08

This is perhaps not what you want, but: When I come across such situations, and if it is likely that I'm going to do it more then a few times I usually write a function for it. (One problem with this is that I tend to go a bit overboard.)

The procedure can be done using macro as well, but what I like about using functions is the flexibility to customize it.

As macro c, record by:

qc:s/\s\+/ \& /g<Enter>:s/^/\\hline /<Enter>:s/$/\\\\/<Enter>q s/\s\+/ \& /g Substitute 1+ spaces with " & ", globally. s/^/\\hline / Substitute start of line with \hline. s/$/\\\\/       Substitute end of line with \\.


Select range:

<Ctrl>+v23j
:norm @c


Here is an example using function. Add to .vimrc, or better, to a file in some auto-load directory.

What this does is execute LaTeXTable() on selected lines. In addition it adds header and footer for table unless argument 1 is 0. So:

• Ctrl+v
• Select lines.
• :LEXTABLEEnter Create table lines including start and end.
• :LEXTABLE 0Enter Create table lines only.
• :LEXTABLE c l l cEnter Create table lines and use 'c l l c' as column specifiers.

Sample code:

function! LaTeXTable(...) range
" Replace consecutive spaces with " & "
'<,'>s/\s\+/ \& /g
'<,'>s/^\s*/\\hline /
" Replace end with \\
'<,'>s/\s*\$/ \\\\/

" If argument is 0 then do not add table def
if a:1 == "0"
return
" Else if argument is not empty use it as column specifier
elseif a:1 != ""
let cc = a:1
" Else split first line on & and make all center c
else
let ands = split(getline(a:firstline), '&')
call map(ands, '"c"')
let cc = join(ands, " ")
endif

call append(a:firstline - 1,"\\begin{tabular}{ " . cc . " }")
call append(a:lastline  + 1,"\\end{tabular}")
endfun

" -nargs=? allow 0 or 1 argument
" -range   use range
" LEXTABLE name
" silent   do not echo what is done
" <line.>  range
" <q-args> Quote argument
command! -nargs=? -range LEXTABLE silent <line1>,<line2>call LaTeXTable(<q-args>)


If one usually do not want to add start/end of table one can easily change the function to say:

if arg is empty or 0, then do not create,
if arg=1 auto, then auto generate
else use as string
.

It would perhaps be preferable:

if a:1 == "" || a:1 == "0"
return
elseif a:1 != "1"
let cc=a:1
else
let ands = split(getline(a:firstline), '&')
call map(ands, '"c"')
let cc = join(ands, " ")
endif


So then:

:'<,'>LEXTABLE<Enter>           # Only parse lines, no header.
:'<,'>LEXTABLE 0<Enter>         # Only parse lines, no header.
:'<,'>LEXTABLE 1<Enter>         # Auto generate column specifiers.
:'<,'>LEXTABLE c l<Enter>       # Use 'c l' as column specifiers.
:'<,'>LEXTABLE c | l l<Enter>   # Use 'c | l l' as column specifiers.


By this one could further expand to use profiles for tables, as in e.g. if argument is "P1" use "c c c c c", if "P2" use "c l c l c" etc.

All this and more one would perhaps try to take a look at Vim-LaTeX and the like.

From the above one would get:

Selected lines:

0.79    0.80    5.40    6.48
0.86    0.87    4.57    5.81
0.93    0.94    4.04    5.32


Command:

:'<,'>LEXTABLE c | l l l


Result:

\begin{tabular}{ c | l l l }
\hline 0.79 & 0.80 & 5.40 & 6.48 \\
\hline 0.86 & 0.87 & 4.57 & 5.81 \\
\hline 0.93 & 0.94 & 4.04 & 5.32 \\
\end{tabular}

-
Excelent post! I uses Vim-LaTeX, your function must be in that suite. –  David Mar 30 '13 at 17:34