8

I want to create a table with arrows between some cells, for which I've used tabularx and TkiZ. I have the following problems:

  • Text in cells aligned vertically to the center and at the same heigh (TikZ nodes are not inline with normal cells text in a same row).
  • Inability to align to the center with \begin{center}•\end{center}.
  • I don't know how to fix the size of the cells.

This is what I currently have:

Code

\documentclass{article}
\usepackage{tabularx}
\usepackage{tikz}
\tikzset{every picture/.style={remember picture}}
\begin{document}
\begin{tabularx}{\textwidth}{r|c|c|c|c|l}
    &$D_1$&$D_2$&$D_3$&$D_4$&foo\\ \cline{1-6}
    $O_1$&\tikz[baseline]{\node (a11) {50};}&\tikz[baseline]{\node (a12) {0};}&&&50\\[2em] \cline{1-6}
    $O_2$&&\tikz[baseline]{\node (a22) {60};}&&&60\\[2em] \cline{1-6}
    $O_3$&&\tikz[baseline]{\node (a32) {10};}&\tikz[baseline]{\node (a33) {30};}&\tikz[baseline]{\node (a34) {10};}&50\\[2em] \cline{1-6}
    $O_4$&&&&\tikz[baseline]{\node (a44) {50};}&50\\[2em] \cline{1-6}
    bar&50&70&30&60&210\\
\end{tabularx}
\begin{tikzpicture}[overlay]
    \path[thick,->] (a11) edge (a12);
    \path[thick,->] (a12) edge (a22);
    \path[thick,->] (a22) edge (a32);
    \path[thick,->] (a32) edge (a33);
    \path[thick,->] (a33) edge (a34);
    \path[thick,->] (a34) edge (a44);
\end{tikzpicture}
\end{document}

Output

Besides, I get the following warnings:

Underfull \hbox (badness 10000) in alignment at lines 13--13

Overfull \hbox (15.0pt too wide) in paragraph at lines 13--22

1
  • 1
    The Overfull \hbox (15.0pt too wide)... warning comes from not using \noindent right before \begin{tabularx} (your table starts a paragraph so it receives the standard indentation). Mar 2, 2014 at 4:03

4 Answers 4

8

Another possible solution where the OP code is used but slightly modified. The underfull problem is taken care by adding an X column in the last column so that \textwidth is satisfied.

The OP's tikz struture in the cell is redefined as tikzmark taking two arguments. and connected by \link macro.

Create a new column type M with horizontal and vertical centering:

\renewcommand\tabularxcolumn[1]{m{#1}}
\newcolumntype{M}{>{\centering\arraybackslash}m{1cm}}

enter image description here

Code

\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{tabularx}
\usepackage{tikz}
%\tikzset{every picture/.style={remember picture}}

\renewcommand\tabularxcolumn[1]{m{#1}}
\newcolumntype{M}{>{\centering\arraybackslash}m{1cm}}

\newcommand\tikzmark[2]{%
\tikz[remember picture,baseline] \node[inner sep=2pt,outer sep=0] (#1){#2};%
}

\newcommand\link[2]{%
\begin{tikzpicture}[remember picture, overlay, >=stealth, shift={(0,0)}]
  \draw[->] (#1) to (#2);
\end{tikzpicture}%
}

\begin{document}

\noindent
\begin{tabularx}{\textwidth}{M|M|M|M|M|MX}
         &$D_1$           &$D_2$           &$D_3$    &$D_4$& foo  &\\ \cline{1-6}
    $O_1$&\tikzmark{a}{50}&\tikzmark{b}{0} &         &     & 50   &\\[2em] \cline{1-6}
    $O_2$&                &\tikzmark{c}{60}&         &     &60 &\\[2em] \cline{1-6}
    $O_3$&                &\tikzmark{d}{10}&\tikzmark{e}{30}&\tikzmark{f}{10}&50 &\\[2em] \cline{1-6}
    $O_4$&                &                &         &\tikzmark{g}{50}&{50} &\\[2em] \cline{1-6}
    bar&50&70&30&60&210  \\ 
\end{tabularx}

\link{a}{b}
\link{b}{c} 
\link{c}{d}
\link{d}{e} 
\link{e}{f} 
\link{f}{g}
\end{document}
3
  • 1
    very nice, I like this solution best; did you know that tikzmark has its own package?
    – cmhughes
    Mar 2, 2014 at 6:09
  • @cmhughes -- Thank you sir, quite encouraging. As to the question: Yes, but thinking the tikzmark macro should be sufficient to give a shot.
    – Jesse
    Mar 2, 2014 at 6:35
  • In the last row bar&50&70&30&60&210 \\ I would add an ampersand, i.e., bar&50&70&30&60&210& \\ . Otherwise if the height is changed, e.g., \\[2em], the 210 is on the row's ceiling. May 24, 2018 at 20:09
8

I'd suggest you to draw the whole matrix as a TikZ matrix; this gives you easy control over the attributes of the cells (I added some colors just optionally):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\tikzset{ 
table/.style={
  matrix of nodes,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={rectangle,text width=3em,align=center},
  text depth=1.25ex,
  text height=2.5ex,
  nodes in empty cells
},
row 1/.style={nodes={fill=green!10,text depth=0.4ex,text height=2ex}},
row 6/.style={nodes={text depth=0.4ex,text height=2ex}},
column 1/.style={nodes={fill=green!10}},
}

\begin{document}

\begin{tikzpicture}
% the matrix entries
\matrix (mat) [table]
{
& $D_1$ & $D_2$ & $D_3$ & $D_4$ & foo \\
$O_1$ & 50  & 0 & & & 50 \\
$O_2$ & & 60 & & & 60 \\
$O_3$ & & 10 & 30 & 10 & 50 \\
$O_4$ & & & & 50 & 50 \\
bar & 50 & 70 & 30 & 60 & 210 \\
};
% the matrix rules
\foreach \x in {1,...,5}
{
  \draw 
    ([xshift=-.5\pgflinewidth]mat-\x-1.south west) --   
    ([xshift=-.5\pgflinewidth]mat-\x-6.south east);
  }
\foreach \x in {1,...,5}
{
  \draw 
    ([yshift=.5\pgflinewidth]mat-1-\x.north east) -- 
    ([yshift=.5\pgflinewidth]mat-6-\x.south east);
}    
% the arrows
\begin{scope}[shorten >=7pt,shorten <= 7pt]
\draw[->]  (mat-2-2.center) -- (mat-2-3.center);
\draw[->]  (mat-2-3.center) -- (mat-3-3.center);
\draw[->]  (mat-3-3.center) -- (mat-4-3.center);
\draw[->]  (mat-4-3.center) -- (mat-4-4.center);
\draw[->]  (mat-4-4.center) -- (mat-4-5.center);
\draw[->]  (mat-4-5.center) -- (mat-5-5.center);
\end{scope}
\end{tikzpicture}

\end{document}

enter image description here

0
4

Here is a way to do it with laps and stacks:

\documentclass{article}
\usepackage{tabularx}
\usepackage{graphicx}
\usepackage{stackengine}
\def\RA{\rlap{\scalebox{1.6}{$\rightarrow$}}}
\def\DA{\bclap{\scalebox{1.6}{$\downarrow$}}}
\def\mystrut{\rule{0ex}{3ex}}
\begin{document}
\setstackgap{S}{6pt}
\begin{tabularx}{\textwidth}{r|c|c|c|c|l}
    &$D_1$&$D_2$&$D_3$&$D_4$&foo\\ \cline{1-6}
    \mystrut$O_1$&50\RA&\stackunder{0}{\DA}&&&50\\[2em] \cline{1-6}
    \mystrut$O_2$&&\stackunder{60}{\DA}&&&60\\[2em] \cline{1-6}
    \mystrut$O_3$&&10\RA&30\RA&\stackunder{10}{\DA}&50\\[2em] \cline{1-6}
    \mystrut$O_4$&&&&50&50\\[2em] \cline{1-6}
    \mystrut bar&50&70&30&60&210\\
\end{tabularx}
\end{document}

enter image description here

And here is an alternative presentation:

\documentclass{article}
\usepackage{tabularx}
\usepackage{graphicx}
\usepackage{stackengine}
\def\RA{\rlap{\scalebox{1.6}{$\rightarrow$}}}
\def\DA{\smash{\bclap{\scalebox{1.6}{$\downarrow$}}}}
\def\mystrut{\rule[-2ex]{0ex}{6ex}}
\begin{document}
\setstackgap{S}{6pt}
\setstackgap{L}{7pt}
\begin{tabularx}{\textwidth}{r|c|c|c|c|l}
    &$D_1$&$D_2$&$D_3$&$D_4$&foo\\ \cline{1-6}
    \mystrut$O_1$&50\RA&\stackunder{0}{\DA}&&&50\\ \cline{1-6}
    \mystrut$O_2$&&\stackunder{60}{\DA}&&&60\\ \cline{1-6}
    \mystrut$O_3$&&10\RA&30\RA&\stackunder{10}{\DA}&50\\ \cline{1-6}
    \mystrut$O_4$&&&&50&50\\ \cline{1-6}
    \mystrut bar&50&70&30&60&210\\
\end{tabularx}
\end{document}

enter image description here

1

With {NiceTabular} of nicematrix and TikZ to draw the arrows.

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

\begin{document}

\begin{center}
\setlength{\tabcolsep}{0pt}
\begin{NiceTabular}
   [columns-width=1cm,hvlines-except-borders]
   {>{\rule[-4mm]{0pt}{1cm}}*{6}{c}}
         & $D_1$ & $D_2$ & $D_3$ & $D_4$ & foo \\
   $O_1$ & 50  & 0 & & & 50 \\
   $O_2$ & & 60 & & & 60 \\
   $O_3$ & & 10 & 30 & 10 & 50 \\
   $O_4$ & & & & 50 & 50 \\
   bar & 50 & 70 & 30 & 60 & 210 \\
\CodeAfter
   \begin{tikzpicture} [->, shorten < = 1mm, shorten > = 1mm]
   \draw (2-2) -- (2-3) ;
   \draw (2-3) -- (3-3) ; 
   \draw (3-3) -- (4-3) ; 
   \draw (4-3) -- (4-4) ; 
   \draw (4-4) -- (4-5) ; 
   \draw (4-5) -- (5-5) ; 
   \end{tikzpicture}
\end{NiceTabular}
\end{center}

\end{document}

Output of the above code

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .