8

How can I place two multicolumn tables (tableA and tableB) side by side and draw arrows from cell in tableA to another cell in tableB?

I have tried this Arrows between two tables and its also working ok with simple tables. But if I try to use nested nodes to create multiple columns it goes wrong.

What to do?

This is what I have tried, but if I change the labels to longer words like "Copenhagen" the whole cell gets very wide and it looks weird on the page. Is it something with the margin I have to change? How should I add border in nested nodes?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart,matrix,positioning}
\begin{document}
\begin{tikzpicture}
\node[rectangle split, rectangle split parts=3,draw,inner sep=2ex] (A) at (0,1)
{
\begin{tikzpicture}
\node[rectangle,text height=2em] (1st) {a11};
\node[rectangle,text height=2em,right=of 1st] (2nd) {a21};
\end{tikzpicture}
\nodepart{two}
\begin{tikzpicture}
\node[rectangle,text height=2em] (1st) {a12};
\node[rectangle,text height=2em,right=of 1st] (2nd) {a22};
\end{tikzpicture}
\nodepart{three}
\begin{tikzpicture}
\node[rectangle,text height=2em] (1st) {a13};
\node[rectangle,text height=2em,right=of 1st] (2nd) {a23};
\end{tikzpicture}};

\node[rectangle split, rectangle split parts=3,draw,inner sep=2ex] (B) at (7,1)
{\begin{tikzpicture}
\node[rectangle,text height=2em] (1st) {b11};
\node[rectangle,text height=2em,right=of 1st] (2nd) {b21};
\end{tikzpicture}
\nodepart{two}
\begin{tikzpicture}
\node[rectangle,text height=2em] (1st) {b12};
\node[rectangle,text height=2em,right=of 1st] (2nd) {b22};
\end{tikzpicture}
\nodepart{three}
\begin{tikzpicture}
\node[rectangle,text height=2em] (1st) {b13};
\node[rectangle,text height=2em,right=of 1st] (2nd) {b23};
\end{tikzpicture}};
\draw[->] (A.two east) -- (B.text west);
\draw[->] (B.two west) -- (A.text east);
\end{tikzpicture}
\end{document}
freddy
  • 83
  • 1
    Welcome to the site! The link you provide is very helpful; it would be great if you could post a small complete minimal working example (MWE) that demonstrates the trouble that you're having. Welcome! – cmhughes Jul 04 '14 at 13:03
  • In particular, are we talking tikzpictures, tabulars or floats? – John Kormylo Jul 04 '14 at 13:56
  • @cmhughes I've added my code, I hope you guys understand my problem. Thanks. – freddy Jul 04 '14 at 14:25
  • 1
    Please make your example compilable. We can not work with just a snippet. Thanks. – LaRiFaRi Jul 04 '14 at 14:26
  • You are using nested tikzpictures, which makes the problem harder. Why don't use one matrix per "table", all in the same tikzpicture? – JLDiaz Jul 04 '14 at 14:59
  • Do you really need to typeset the tables as tikz pictures or could you use regular tabulars? – cfr Jul 06 '14 at 01:55
  • @JLDiaz No I do not have to use tikzpictures. – freddy Jul 06 '14 at 16:08
  • @cfr would be fine with regular tabulars. It was just because I found the example from the link and I don't know how to add lines on top of two regular tabulars. – freddy Jul 06 '14 at 16:10
  • @freddy Good. That makes it a lot easier. You can use whatever packages and commands you wish for the tabulars and then just draw arrows on top using tikzmark. See my answer for a basic illustration of how this might be done. – cfr Jul 06 '14 at 19:24

3 Answers3

7

If regular tabulars are an option, then I would suggest drawing your tabulars in the normal way (i.e. use whichever packages etc. you usually use and like) and then adding the arrows as an overlay using tikzmark. This library lets you add marks in the LaTeX code of the tabulars (or whatever else) and then use those marks to position drawing commands which can overlay the text.

For example:

\documentclass{article}
\usepackage{array,tikz}
\usetikzlibrary{tikzmark,arrows.meta}
\newcolumntype{M}{>{\centering\mbox{}\vfill\arraybackslash}m{50pt}<{\vfill}}
\begin{document}

  \begin{tabular}{|*{2}{M|}}
    \hline
    \tikzmark{la11}a11\tikzmark{ra11}   &   \tikzmark{la21}a21\tikzmark{ra21}\\\hline
    \tikzmark{la12}a12\tikzmark{ra12}   &   \tikzmark{la22}a22\tikzmark{ra22}\\\hline
    \tikzmark{la13}a13\tikzmark{ra13}   &   \tikzmark{la23}a23\tikzmark{ra23}\\\hline
  \end{tabular}
  \hskip 50pt
  \begin{tabular}{|*{2}{M|}}
    \hline
    \tikzmark{lb11}b11\tikzmark{rb11}   &   \tikzmark{lb21}b21\tikzmark{rb21}\\\hline
    \tikzmark{lb12}b12\tikzmark{rb12}   &   \tikzmark{lb22}b22\tikzmark{rb22}\\\hline
    \tikzmark{lb13}b13\tikzmark{rb13}   &   \tikzmark{lb23}b23\tikzmark{rb23}\\\hline
  \end{tabular}

  \begin{tikzpicture}
    [
      remember picture,
      overlay,
      -latex,
      color=blue!75!green,
      yshift=1ex,
      shorten >=1pt,
      shorten <=1pt,
    ]
    \draw ({pic cs:ra21}) -- ({pic cs:lb13});
    \draw ({pic cs:ra23}) -- ({pic cs:lb21});
    \draw ({pic cs:ra13}) -- ({pic cs:la21});
    \draw ({pic cs:rb13}) -- ({pic cs:lb22});
    \draw ({pic cs:lb12}) -- ({pic cs:ra22});
    \draw ({pic cs:lb23}) to [bend left] ({pic cs:ra13});
    \draw ({pic cs:ra11}) to [bend left] ({pic cs:lb11});
  \end{tikzpicture}

\end{document}

I've added two marks for each cell but obviously you really only need to add the marks you go onto use in the tikzpicture environment.

Arrows positioned over tabulars using <code>tikzmark</code>

Note that I've added a central line to each tabular dividing the two columns as you mentioned wanting this in the comments on JLDiaz's answer but the nice thing about this is that you can adjust the tabulars using all the usual formatting commands however you like.

cfr
  • 198,882
4

Following my own advice in a previous comment, there is a solution which uses \matrix for creating the tables, which makes easy to connect the individual cells as shown at the end.

The only problem was to draw the lines which separate rows. I was unable to do it via some style for the matrix, so I had to resort to coding a macro specific for this task (but generic enough for any matrix dimensions).

\usetikzlibrary{matrix,positioning}

\tikzset{  % Define some styles
  my table/.style = {
    matrix of nodes,
    nodes = {minimum width=3em, minimum height=2.5em, inner sep=3pt},
    draw,
    inner sep=0pt,
  },
  my arrow/.style = {
    -latex,
    shorten >= -5pt,
    shorten <= -5pt,
    blue!50!black!60,
  }
}

% Macro to draw the lines between rows
\def\drawLineBelowRow#1#2{% #1: row number, #2: matrix name
  \draw (#2.west|-#2-#1-1.south) -- (#2.east|-#2-#1-1.south);
}

\begin{tikzpicture}   
\matrix[my table] (A) { % First table (it is called A)
   a11        & a21 \\
   a21        & a22 \\
   Copenhagen & a22 \\
};
\drawLineBelowRow{1}{A}
\drawLineBelowRow{2}{A}

\matrix[my table, right=of A] (B) { % Second table (it is called B)
   b11 & b21 \\
   b21 & b22 \\
   b31 & b22 \\
};
\drawLineBelowRow{1}{B}
\drawLineBelowRow{2}{B}

% Drawing arrows between particular cells of each table is easy:
\draw[my arrow] (A-2-2) -- (B-1-1);
\draw[my arrow] (A-3-1) -- (B-2-2);

\end{tikzpicture}

Result:

Result

JLDiaz
  • 55,732
  • Better solutions than mine, but how do I add an border between the cells in the tables? – freddy Jul 04 '14 at 23:25
  • @freddy Your original code didn't have borders either. Your question implied you wanted to add arrows to the existing tables but apparently that's not the case. Please update your question to make clear *exactly* what you are trying to do. For example, based on your original question and current comment, I wouldn't use tikzpictures for the tables at all. But I guess you have reasons for this so please explain them. – cfr Jul 04 '14 at 23:40
2

You can draw two tabulars with {NiceTabular} of nicematrix and use TikZ to draw the arrows by using the TikZ nodes created by {NiceTabular} under the cells of the array.

\documentclass{article}
\usepackage{nicematrix,tikz}
\usetikzlibrary{bending,arrows.meta}

\begin{document}

\begin{center} \NiceMatrixOptions{columns-width=1cm,hvlines} \renewcommand{\arraystretch}{2} \begin{NiceTabular}{cc}[name=a] a11 & a12 \ a21 & a22 \ a31 & a32 \end{NiceTabular} \hspace{1cm}% \begin{NiceTabular}{cc}[name=b] b11 & b12 \ b21 & b22 \ b31 & b32 \end{NiceTabular} \begin{tikzpicture} [remember picture , overlay , -> , blue, shorten < = 3pt, shorten > = 3pt] \draw (a-1-1) to [bend left] (b-1-1) ; \draw (a-3-1) to (a-1-2) ; \draw (b-2-1) to (a-2-2) ; \draw (a-3-2) to (b-1-2) ; \draw (b-3-1) to (b-2-2) ; \draw (a-1-2) to (b-3-1) ; \draw (b-3-2) to [bend left] (a-3-1) ; \end{tikzpicture} \end{center}

\end{document}

Output of the above code

F. Pantigny
  • 40,250