2

My quest is to make a table which looks like this:

tabular with rounded corners, shadow column and title above

To good thing so far: I have succeeded in making this table.

The bad thing: I cannot include this in a normal \begin{table}\end{table} environment as the boundingbox of the tabular is not seen. All text is running over the table

Hopefully somebody can solve this. Either by giving my an alternative way to create this table, or by fixing the error in my code

The code below is using stuff from other answers I have found here: rounded corners shows how to make rounded corners around a table. The problem is: I want my first row with the column heading ABOVE line with rounded corners.

My idea to solve was easy: just adjust the clipping of the tabular such that I make a rounded corner of the first column, immediately go up, and then go to the other side:

  ------------------------------
R-|                heading cols  |
|first grey col    value cols    |
|                                |
R---------------------------------

At the locations of the R's I want to add the rounded corners.

The code I came up with is quite long, I will add it here. It is stand alone. This clipping idea comes from the first link. Also, I am adding a tikzmark A because I want the clipping path to automatically connect to the bottom of the first row. That idea was inspired by this exampleadd tikznode at corner. In order to get the y coordinates of this point A, I used this idea extract y coordinate

Here is the code, which should run stand alone

\documentclass{article}
\usepackage[dvipsnames,table]{xcolor}
\usepackage{array}
\usepackage{environ}
\usepackage{blindtext}
\usepackage{tikz}
\usepackage{etex}
\usetikzlibrary{calc, tikzmark}

\definecolor{lichtgrijs}{RGB}{236,236,236}
\newcolumntype{L}{>{\columncolor{lichtgrijs}}l}

\newsavebox{\tablebox} 

\NewEnviron{rndtable}[1]{%
  \addtolength{\extrarowheight}{1ex}%
  \savebox{\tablebox}{%
    \begin{tabular}{#1}%
      \BODY%
    \end{tabular}}%
    \begin{tikzpicture}  [overlay, remember picture]

    \ExtractCoordinate{$(pic cs:A)$}

    \begin{scope}
      \useasboundingbox;
      \clip[rounded corners=1ex] 
      (0,-\dp\tablebox) -- 
      (\wd\tablebox,-\dp\tablebox) -- 
      (\wd\tablebox,\ht\tablebox) 
      {
          [rounded corners=0ex]-- 
          (1ex,\ht\tablebox) --
          (1ex,\YCoord-\RowDepth)}--
          %(1ex,\ht\tablebox-3ex)}-- 
      (0,\YCoord-\RowDepth) -- 
      cycle;
      \node at (0,-\dp\tablebox) [anchor=south west,inner sep=0pt]{\usebox{\tablebox}};
    \end{scope}
  \end{tikzpicture}
}

\begin{document}

\setlength\arrayrulewidth{1.2pt}
\edef\RowDepth{\the\dimexpr\arraystretch\dimexpr.3\baselineskip\relax\relax}
\newdimen\XCoord
\newdimen\YCoord
\newcommand*{\ExtractCoordinate}[1]{\path (#1); \pgfgetlastxy{\XCoord}{\YCoord};}%


%\blindtext[10]

%\begin{table}[tbp]
%    \caption{bla}
\begin{rndtable}{Llr}
    \rowcolor{white}
    \tikzmark{A} 
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    LB & Lucus Radebe  & 23\\
    DC & Michael Duberry  & 84\\
    DC & Dominic Matteo  & 22\\
    RB & Didier Domi  & 34\\
    MC & David Batty  & 5\\
    MC & Eirik Bakke  & 58\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
%\end{table}

%\blindtext[10]
\end{document}

This code works and generates the tabular I have just show.

HOWEVER, apparently when I include the \begin{table} the size of the table is not recognized at all. If I would put text around the table (by uncommenting blindtext and begin{table}) it is running over the table. My suspicion is that it has to to with either the overlay option or that I use the savebox. Unfortunately I am not able to solve this. It looks like this:

enter image description here

Who knows how I can fix this script such that I can use it properly within a table environment ?

Any hints appreciated!

Regards

Eelco

EDIT:

The suggestion by Marmot about removing the overlay and useasboundingbox works. Now at least a tabular is nicely put into the table environment.

however: a new problem arises; when I want to include two or more tables, somehow every time I run the code the tables get another position. For instance, you can do

\blindtext[1]

\begin{table}[tbp]
    \caption{First table}
\begin{rndtable}{Llr}
    \rowcolor{white}
    \tikzmark{A} 
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}
\blindtext[1]

\begin{table}[tbp]
    \caption{Another table}
\begin{rndtable}{Llr}
    \rowcolor{white}
    \tikzmark{A} 
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    LB & Lucus Radebe  & 23\\
    DC & Michael Duberry  & 84\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}
\blindtext[1]

\begin{table}[tbp]
    \caption{Last  table}
\begin{rndtable}{Llr}
    \rowcolor{white}
    \tikzmark{A} 
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    LB & Lucus Radebe  & 23\\
    DC & Michael Duberry  & 84\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}

This will indeed make three tables, each in its own environment, but they get another location every time I run the code. Also the aux file changes with every run. Probably this has to do with those global vars XCoord and YCoord I use, combined with the savebox trick. But I need those to be able to find the location of the upper row and clip it properly. So this solution I came up with is still not usable.

Anybody knows how to solve this?

EDIT2:

The suggestion by Marmot to leave out the ExtractCoordinate line does not work as I need it to get the location of the bottom of the first row. I found this example here add tikznode at corner and here extract y coordinate

If I leave out ExtractCoordinate (as suggested by Marmot), the table looks like this:

Image of tabular without extractcoordinate

As you can see, the upper rounded corners now always is exactly half way the table. It should be at the bottom of the first row (with the title columns).

Indeed, if I leave out this line with ExtractCoordinate, it fixes the problem of the jumping tables. But then I would need an alternative way to extract the ycoordinate from my tikzmark A. Any idea?

EDIT3:

At this point I almost got the example above working: the only thing it requires is to find an alternative way to extract the y coordinate of the tikzmark, since the trick with ExtractCoordinate is messing up the tables.

But just to be complete, I have also an alternative approach for making tables like this which is based on this idea tabular with rounded corners

My code looks like this:

\documentclass{article}
\usepackage[dvipsnames,table]{xcolor}
\usepackage{array}
\usepackage{blindtext}
\usepackage{tikz}
\usepackage{etex}
\usepackage[most]{tcolorbox}
\usepackage{tabularx}
\usetikzlibrary{calc, tikzmark}

\definecolor{lichtgrijs}{RGB}{236,236,236}
\newcolumntype{L}{>{\columncolor{lichtgrijs}}l}
\newcolumntype{Y}{>{\raggedleft\arraybackslash}X}

\newtcolorbox{twocoltable}[4][]{%
    tabularx*={\renewcommand{\arraystretch}{1.2}}%
    {>{\columncolor{lichtgrijs}\hsize=#3\linewidth}X>{\hsize=#4\linewidth}Y},
    enlarge top initially by=1.5em,
    enlarge bottom finally by=0em,
    enhanced,
    fontupper=\footnotesize,
    breakable,
    colframe=lichtgrijs,
    colback=white,
    arc=1mm,
    outer arc=1mm,
    clip upper,
    rightrule=0pt,
    sharp corners=east,
    width=1\linewidth,
    overlay=%
    {
        \node[anchor=south east] (ycoltit) at  %
        ([xshift=-0cm, yshift=0.0\baselineskip]frame.north east)%
        {{\footnotesize\textbf{#2}}};
    },
    #1
}


\begin{document}


\blindtext

\begin{table}[tbp]
    \caption{Last  table}
\begin{twocoltable}%
    {\textbf{Leeftijd}}{0.8}{0.2}
    Paul Robinson & 45\\
    Lucus Radebe  & 23\\
    Michael Duberry  & 84\\
    Jody Morris  & 75\\
    Jamie McMaster  & 13\\
    Alan Smith  & 70\\
    Mark Viduka  & 30\\
\end{twocoltable}
\end{table}

\blindtext

\end{document}

and the result looks like this enter image description here

The only problem is that I need to add the column titles explicitly using the overlay inside newtcolorbox, which I don't like since I fix the number of columns in the definition (in this case two columns only). But this was the only way to get the column title above the line with the rounded corners. I case somebody knows a better way of doing this, it would be great as well

EDIT4:

Ignasis answer is the best so far. Still I was trying to vary some formats of the table which I know I am going to need, such as fixing the width of the column. The example I tried look like this

\begin{table}
\centering
\begin{tikzpicture}
\matrix[mymatrix,
        column 3/.style={nodes={anchor=center}},
        column 4/.style={nodes={anchor=east}, text width=2cm}] (A) {
            Label & Naam & Leeftijd & Length  in centimeters\\
            MC & Jody Morris  & 75 & 174\\
            FW & Jamie McMaster  & 13 & 184\\
            ST & Alan Smith  & 70 & 150\\
            ST & Mark Viduka  & 30 & 190\\ };
    \tableback{A}{5}{4}
\end{tikzpicture}
\caption{Shorter on}
\end{table}

The result looks like this

tikz with matrix

As you can see, the column at the east is not aligned to the right anymore, and also to first row with the title should align with the bottom of the row. Any idea how to fix this?

EDIT 5:

In parallel with the solution of Ignasis with the matrix environment I have tried to fix my first attempt using the savebox. As Marmot pointed out I need to get rid of the ExtractCoord. This is what I did. My solution now looks like this

\documentclass{article}
\usepackage[dvipsnames,table]{xcolor}
\usepackage{array}
\usepackage{environ}
\usepackage{blindtext}
\usepackage{tikz}
\usepackage{etex} % required for savebox
%\usetikzlibrary{calc, tikzmark}
\usetikzlibrary{tikzmark}

\definecolor{lichtgrijs}{RGB}{236,236,236}
\newcolumntype{L}{>{\columncolor{lichtgrijs}}l}


%\renewcommand{\tikzmark}[2][]{%
%  \tikz[remember picture,overlay]\coordinate[#1](#2);%
%}
%


\NewEnviron{rndtable}[2][\tablebox]{%
  \addtolength{\extrarowheight}{1ex}%
  \def\locbox{#1}
  \savebox{\locbox}{%
    \begin{tabular}{#2}%
      \BODY%
    \end{tabular}}%
    \begin{tikzpicture}  [remember picture]

    \def\radius{1mm};
    \edef\RowDepth{\the\dimexpr\arraystretch\dimexpr.3\baselineskip\relax\relax}
    \coordinate (southwest) at (0,-\dp\locbox);
    \coordinate (southeast) at (\wd\locbox,-\dp\locbox);
    \coordinate (northeast) at (\wd\locbox,\ht\locbox);
    \coordinate (northwest) at (0,\ht\locbox);
    \coordinate (Pt) at ([xshift=\radius]northwest);
    \coordinate (A) at (pic cs:A);
    \coordinate (cellborder) at ([yshift=-\RowDepth]A);
    \coordinate (Pb) at (cellborder -| Pt);
    \coordinate (west) at (Pb -| northwest);

    \begin{scope}
      \clip[rounded corners=\radius] 
      (southwest) -- 
      (southeast) -- 
      (northeast)
      {
      % make straight corners for the cutout
          [rounded corners=0ex]-- 
          (Pt) --
          (Pb) 
      }--
      (west) --
      cycle;
      \node at (0,-\dp\locbox) [anchor=south west,inner sep=0pt]{\usebox{\locbox}};

      % debugging circels
      %\draw[red, fill] (Pt) circle[radius=2pt];
      %\draw[green, fill] (A) circle[radius=2pt];
      %\draw[blue, fill] (cellborder) circle[radius=2pt];
      %\draw[yellow, fill] (Pb) circle[radius=2pt];
      %\draw[orange, fill] (west) circle[radius=2pt];
    \end{scope}
  \end{tikzpicture}
}

\begin{document}

\setlength\arrayrulewidth{1.2pt}


\blindtext[1]

\newsavebox{\tablebox}
\begin{table}[tbp]
    \caption{First table}
\begin{rndtable}[\tablebox]{Llr}
    \rowcolor{white}
    \tikzmark{A}
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}
\blindtext[1]

\newsavebox{\otherbox}
\begin{table}[tbp]
    \caption{Second table}
\begin{rndtable}[\otherbox]{Llr}
    \rowcolor{white}
    \tikzmark{A}
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}
\blindtext[1]

\end{document}

For one table this works fine again. For two tables LaTeX keeps getting two alternating solutions for the table positions: one with the two tables at one page, one with the two tables as separate pages. I think it has to do with the savebox, that why I tried to add an extra parameter such that I can define a savebox for every table. Unfortunately this does not work. If I compare the aux files of two subsequent runs of xelatex, a diff on both files will show the following output:

9,13c9,13
< \@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Second table}}{1}}
< \savepicturepage{pgfid3}{1}
< \pgfsyspdfmark {pgfid3}{9192734}{33349459}
< \savepicturepage{pgfid4}{1}
< \pgfsyspdfmark {pgfid4}{8799518}{30733844}
---
> \@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Second table}}{2}}
> \savepicturepage{pgfid3}{2}
> \pgfsyspdfmark {pgfid3}{9192734}{41880784}
> \savepicturepage{pgfid4}{2}
> \pgfsyspdfmark {pgfid4}{8799518}{39265169}

The third run will have an aux file equal to the first run again. If this can be solved I prefer this solution above all since it makes use of a original tabular environment. If it cannot be solved I will fall back on the matrix solution, which is a great alternative

  • 2
    Just remove overlay and \useasboundingbox;. – user121799 Jul 31 at 22:23
  • So easy: these to were messing it up. Thanks! It works now – Eelco van Vliet Jul 31 at 22:31
  • There is one more problem I am runnig into : if I include more than one table, every time I compile the code the tables get another location. Also the aux file keeps changing since I see the latex warning about the changed labels every time I run the code. You can reproduce it by using the code above (without the overlay and useasboundingbox) and then include two or three tables. Any idea how to fix this too ? – Eelco van Vliet Jul 31 at 22:50
  • Just remove \ExtractCoordinate{$(pic cs:A)$}. As far as I can see it is not good for anything here. You may give a pointer to the original code (if it exists) such that others can gauge what all these things were originally good for. – user121799 Jul 31 at 22:56
  • I cannot leave it out as this calculates the location of the bottom of the first row and stores it in YCoord. I will make an edit to show you what happens – Eelco van Vliet Jul 31 at 23:03
7

I peopose this short code based on pstricks

\documentclass{article}
\usepackage[dvipsnames,table]{xcolor}
\usepackage{array, booktabs, caption}
\usepackage{blindtext}
\usepackage{pst-node}

\definecolor{lichtgrijs}{RGB}{236,236,236}

\begin{document}

\blindtext[10]

\begin{table}[tbp]
\centering
 \caption{bla}
 \setlength{\belowrulesep}{0pt}
\setlength\arrayrulewidth{1.2pt}
\begin{tabular}{llr}
 \rowcolor{white}
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
  \arrayrulecolor{lichtgrijs}
 \cmidrule[1.2pt]{2-3}
  \pnode[-6pt, 0.96em]{A} \pnode{R1}\phantom{GK}&\pnode[-6pt, 0.96em]{B} Paul Robinson & 45\\
    \pnode{R2} & Lucus Radebe & 23\\
    \pnode{R3} & Michael Duberry & 84\\
    \pnode{R4} & Dominic Matteo & 22\\
    \pnode{R5} & Didier Domi & 34\\
    \pnode{R6} & David Batty & 5\\
    \pnode{R7} & Eirik Bakke & 58\\
    \pnode{R8} & Jody Morris & 75\\
    \pnode{R9} & Jamie McMaster & 13\\
    \pnode{R10}& Alan Smith & 70\\
  \pnode[-6pt, -1.52ex]{C} \pnode{R11} & \pnode[-6pt, -1.52ex]{D}Mark Viduka & 30\\
    \arrayrulecolor{lichtgrijs}\cmidrule[1.2pt]{2-3}
\end{tabular}
\pscustom[linestyle=none, fillstyle=solid, fillcolor=lichtgrijs]{\psline[linearc=0.2](B)(A)(C)(D)\closepath}
\foreach \i/\txt in {1/GK, 2/LB, 3/DC, 4/DC, 5/RB, 6/MC, 7/MC, 8/MC, 9/FW, 10/ST, 11/ST}{\rput[Bl](R\i){\txt}}
\end{table}

\blindtext[10]

\end{document} 

enter image description here

  • Many thanks Bernard, this works and makes the table as I want it. The only disadvantages is that it requires quite some code per table, and I have many tables to work with. So I would prefer a new tabular environment taking care of the details. So in case somebody can solve the issue of my solution above I would prefer that one, as no coding is required in the tabular itsself. In any case, this works and would be a good alternative. – Eelco van Vliet Aug 1 at 7:04
6

Following code uses a TikZ matrix to build the table and an additional command to draw the background.

The matrix style is already defined, therefore you can use a tabular syntax to define the contents (don't forget \\ at last line).

Background is drawn with command \tableback which uses three parameters: matrix name, number of rows and number of columns.

That's all.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix, positioning, backgrounds}

\definecolor{lichtgrijs}{RGB}{236,236,236}

\tikzset{
    mymatrix/.style={%
        matrix of nodes,
        nodes={anchor=west, text height=1.5ex, text depth=.25ex},
        row 1/.style={font=\bfseries},
        column 3/.style={nodes={anchor=east}},
    }
}

\newcommand{\tableback}[3]{
\begin{scope}[on background layer]
\filldraw[thick, lichtgrijs,rounded corners] (#1-1-1.south east)-| (#1-#2-1.west)|-(#1-#2-1.south)[sharp corners]-|cycle;
\draw[lichtgrijs,thick] (#1-1-1.south east)--(#1-1-#3.south east) (#1-#2-1.south east)--(#1-#2-#3.south east);
\end{scope}
}

\begin{document}
\begin{table}
\centering
\begin{tikzpicture}
\matrix[mymatrix] (A) {
 Label & Naam & Leeftijd \\
    GK & Paul Robinson & 45\\
    LB & Lucus Radebe  & 23\\
    DC & Michael Duberry  & 84\\
    DC & Dominic Matteo  & 22\\
    RB & Didier Domi  & 34\\
    MC & David Batty  & 5\\
    MC & Eirik Bakke  & 58\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\ };
    \tableback{A}{12}{3}
\end{tikzpicture}
\caption{A nice table made with a TikZ array}
\end{table}
\end{document}

enter image description here

Update: Trying to solve EDIT 4 problem

To be able to declare columns width, we need to forget text height and text depth parameters and declare a text width in desired column.

But as soon as we forget text depth, nodes with descendants (jpq) are misaligned. Therefore I've changed the reference from west to south west and added execute at begin cell={\vphantom{j}} to restore the correct alignment.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix, positioning, backgrounds}

\definecolor{lichtgrijs}{RGB}{236,236,236}

\tikzset{
    mymatrix/.style={%
        matrix of nodes,
        nodes={anchor=south west}, 
        row 1/.style={font=\bfseries},
        column 3/.style={nodes={anchor=south east}},
        execute at begin cell={\vphantom{j}}
    }
}

\newcommand{\tableback}[3]{
\begin{scope}[on background layer]
\filldraw[thick, lichtgrijs,rounded corners] (#1-1-1.south east)-| (#1-#2-1.west)|-(#1-#2-1.south)[sharp corners]-|cycle;
\draw[lichtgrijs,thick] (#1-1-1.south east)--(#1-1-#3.south east) (#1-#2-1.south east)--(#1-#2-#3.south east);
\end{scope}
}

\begin{document}
\begin{table}
\centering
\begin{tikzpicture}
\matrix[mymatrix,
        column 3/.style={nodes={anchor=south}},
        column 4/.style={nodes={anchor=south east, text width=2cm}}] (A) {
            Label & Naam & Leeftijd & Length  in centimeters\\
            MC & Jody Morris  & 75 & 174\\
            FW & Jamie McMaster  & 13 & 184\\
            ST & Alan Smith  & 70 & 150\\
            ST & Mark Viduka  & 30 & 190\\ };
    \tableback{A}{5}{4}
\end{tikzpicture}
\caption{Shorter on}
\end{table}
\end{document}

enter image description here

Update 2: Question about alignments in comments

To understand what happens with alignments you need to understand that a matrix is not a tabular. A matrix only arranges nodes on a grid but nodes keep their size. See following image where nodes shows their border.

enter image description here

As you can see columns 1, 2 and 3 show minimum size nodes with centered contents and their alignment to left, center or right is forced with anchors. But the fourth column has a text length defined, therefore node's anchor and inner contents alignment are different things. In this case you need to fix an align value to force the right alignment for this column.

The code for the figure is:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix, positioning, backgrounds}

\definecolor{lichtgrijs}{RGB}{236,236,236}

\tikzset{
    mymatrix/.style={%
        matrix of nodes,
        nodes={draw, anchor=south west}, 
        row 1/.style={font=\bfseries},
        column 3/.style={nodes={anchor=south east}},
        execute at begin cell={\vphantom{j}}
    }
}

\newcommand{\tableback}[3]{
\begin{scope}[on background layer]
\filldraw[thick, lichtgrijs,rounded corners] (#1-1-1.south east)-| (#1-#2-1.west)|-(#1-#2-1.south)[sharp corners]-|cycle;
\draw[lichtgrijs,thick] (#1-1-1.south east)--(#1-1-#3.south east) (#1-#2-1.south east)--(#1-#2-#3.south east);
\end{scope}
}

\begin{document}
\begin{table}
\centering
\begin{tikzpicture}
\matrix[mymatrix,
        column 3/.style={nodes={anchor=south}},
        column 4/.style={nodes={text width=2cm, align=right}},
        row 1 column 4/.style={nodes={align=center}}] (A) {
            Label & Naam & Leeftijd & Length  in centimeters\\
            MC & Jody Morris  & 75 & 174\\
            FW & Jamie McMaster  & 13 & 184\\
            ST & Alan Smith  & 70 & 150\\
            ST & Mark Viduka  & 30 & 190\\ };
    \tableback{A}{5}{4}
\end{tikzpicture}
\caption{Shorter on}
\end{table}
\end{document}
  • I like this solution as the table contents itself is really simimar to a tabular environment. Still I wonder how I can mimick the features of a real tabular. For instance, quiet often I want to fix the width of the column, so that the heading can become a multi-row text. I tried that with your format by adding 'text width=2cm' (and make the title a bit longer), but then I see that the alingment (which you imposed with the anchor=east) is not working any more. Any idea how I could do this in the matrix environment ? – Eelco van Vliet Aug 1 at 11:22
  • @EelcovanVliet: You can fix the text width but you also need to apply some align format which is center by default`. If you show me what do you want, I can try to solve the problem. Ups! I've seen your edit 4. Let me try to solve. – Ignasi Aug 1 at 12:30
  • @EelcovanVliet Updated answer. Is it better now? – Ignasi Aug 1 at 12:49
  • In this way indeed I can make a proper aligned narrow collumn, thanks for this update! The problem now only is that I dont exactly understand how those allignments influence each other. For instance: if I copy the last table and then change the anchor of that column 4 from south east to south west, I would expect that the third table should have a right alligned fourth column but this is not the case: it stay left alinge just as the second table. So apparently the table allignment is influenced by each other. Could you explain this? – Eelco van Vliet Aug 1 at 18:48
  • @EelcovanVliet I've updated again the answer trying to solve your question. Hope it helps. – Ignasi Aug 2 at 7:26
1

The problem with your code from EDIT 5 is that you are reusing the same pic name when doing \tikzmark{A} in all your rndtable environments. So, the position of mark A written to the .aux file is that corresponding to the last \tikzmark{A} you did, i.e. your last rndtable environment. When you recompile, non-last rndtable environments find that this A mark has moved, of course. This doesn't happen if there is only one rndtable environment in your document, as you can easily verify.

If you use a different pic name every time, there is no problem. In order to do so, I added a third argument to the rndtable environment, which gives the name of the \tikzmark to use. I also removed the use of the etex package, removed spurious spaces and simplified a bit (\locbox isn't needed).

\documentclass{article}
\usepackage[dvipsnames,table]{xcolor}
\usepackage{array}
\usepackage{environ}
\usepackage{blindtext}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\definecolor{lichtgrijs}{RGB}{236,236,236}
\newcolumntype{L}{>{\columncolor{lichtgrijs}}l}

\NewEnviron{rndtable}[3][\tablebox]{%
  \addtolength{\extrarowheight}{1ex}%
  \sbox{#1}{%
    \begin{tabular}{#2}%
      \BODY%
    \end{tabular}}%
    \begin{tikzpicture}[remember picture]

    \def\radius{1mm}
    \edef\RowDepth{\the\dimexpr\arraystretch\dimexpr.3\baselineskip\relax\relax}
    \coordinate (southwest) at (0,-\dp#1);
    \coordinate (southeast) at (\wd#1,-\dp#1);
    \coordinate (northeast) at (\wd#1,\ht#1);
    \coordinate (northwest) at (0,\ht#1);
    \coordinate (Pt) at ([xshift=\radius]northwest);
    \coordinate (A) at (pic cs:#3);
    \coordinate (cellborder) at ([yshift=-\RowDepth]A);
    \coordinate (Pb) at (cellborder -| Pt);
    \coordinate (west) at (Pb -| northwest);

    \begin{scope}
      \clip[rounded corners=\radius]
      (southwest) --
      (southeast) --
      (northeast)
      {
      % make straight corners for the cutout
          [rounded corners=0ex]--
          (Pt) --
          (Pb)
      }--
      (west) --
      cycle;
      \node at (0,-\dp#1) [anchor=south west,inner sep=0pt]{\usebox{#1}};
    \end{scope}
  \end{tikzpicture}
}

\begin{document}

\setlength\arrayrulewidth{1.2pt}
\blindtext[1]

\newsavebox{\tablebox}
\begin{table}[tbp]
    \caption{First table}
\begin{rndtable}[\tablebox]{Llr}{A}
    \rowcolor{white}%
    \tikzmark{A}%
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}
\blindtext[1]

\newsavebox{\otherbox}
\begin{table}[tbp]
    \caption{Second table}
\begin{rndtable}[\otherbox]{Llr}{B}
    \rowcolor{white}%
    \tikzmark{B}%
    \textbf{Label} & \textbf{Naam} & \textbf{Leeftijd}\\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45\\
    MC & Jody Morris  & 75\\
    FW & Jamie McMaster  & 13\\
    ST & Alan Smith  & 70\\
    ST & Mark Viduka  & 30\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}
\end{table}
\blindtext[1]

\end{document}

Screenshot

(showing only the first two lines of the first \blindtext[1]).

  • Thanks for clarifying this. But what would be the benefit of using a tikzmark above the use of a normal tikz node ? I think that the benefit of using the \cornercell macro as I have defined it that you are not exposing the user of rndtable to the details of the name of the node for instance, so the interface is a bit simpeler without using the tikzmark. Or do you see another clear benefit for using tikzmark? – Eelco van Vliet Aug 2 at 9:40
  • I haven't had time to look at the code you posted later. I only analyzed the non-convergence problem, since you were asking me in comments. – frougon Aug 2 at 9:41
  • Ok, well I am gladd that we understand now why it happened. Thanks for that – Eelco van Vliet Aug 2 at 9:45
1

I appreciate all the answers I got so far; with the help of your input I was able to fix my initial solution. I think this solution is still the easiest way to make these rounded tables as it is based on a normal tabular environment.

The reason of the strange behavior of the non-converging latex code was the use of the tizkmark combined with the commando to turn a tikzmark in a node (cs:pic).

To get rid of this, I am not using the tikzmark anymore to add a location in the first tabular cell, but instead I use a normal tikz node. It all seems to work as I want. The code looks now like this

\documentclass{article}
\usepackage[dvipsnames,table]{xcolor}
\usepackage{array}
\usepackage{environ}
\usepackage{blindtext}
\usepackage{tikz}
\usepackage{etex} % required for savebox
%\usetikzlibrary{calc, tikzmark}

\definecolor{lichtgrijs}{RGB}{236,236,236}
\newcolumntype{L}{>{\columncolor{lichtgrijs}}l}
\newcolumntype{B}{>{\columncolor{lichtgrijs}}b}
\newcolumntype{M}{>{\centering\arraybackslash}m}

% this defines the distance of the cell characters and the row line
\edef\RowDepth{\the\dimexpr\arraystretch\dimexpr.3\baselineskip\relax\relax}

% the tablebox only needs to be defined once
\newsavebox{\tablebox}

% this node must be used in the top left corner of every tabular using the
% rndtable
\newcommand{\cornercell}[1]{
    \tikz[remember picture]{\node[%shape=rectangle, draw,
    anchor=south west, inner sep=0pt](A){#1};}
}


\NewEnviron{rndtable}[2][0pt]{%
    % the rndtable draws a tabular with the first column grey with rouned
    % corners
    \addtolength{\extrarowheight}{1ex}%
    \savebox{\tablebox}{%
        \begin{tabular}{#2}
            \BODY
        \end{tabular}%
    }
    \begin{tikzpicture} [remember picture]

    % Define the cardinal points of the table
    \def\radius{1mm};
    \coordinate (southwest) at (0,-\dp\tablebox);
    \coordinate (southeast) at (\wd\tablebox,-\dp\tablebox);
    \coordinate (northeast) at (\wd\tablebox,\ht\tablebox);
    \coordinate (northwest) at (0,\ht\tablebox);
    \coordinate (Pt) at ([xshift=\radius]northwest);
    % with respect to node A create a point at the table line
    % In case we need an offset downwards, this can be given optionally
    \coordinate (cellborder) at ([yshift=-\RowDepth-#1]A.south west);
    \coordinate (Pb) at (cellborder -| Pt);
    \coordinate (west) at (Pb -| northwest);

    \begin{scope}
      % draw the clipping frame with the rouned corners saving the
      % to row. Everythin outside this frame is clipped
      \clip[rounded corners=\radius] 
      (southwest) -- 
      (southeast) -- 
      (northeast)
      {
          % make straight corners for the cutout
          [rounded corners=0ex]-- 
          (Pt) --
          (Pb) 
      }--
      (west) --
      cycle;

      % draw the table from the savedbox
      \node at (southwest) [anchor=south west,inner sep=0pt]{\usebox{\tablebox}};
      % debugging circels
      %\draw[red, fill] (cellborder) circle[radius=2pt];
    \end{scope}
  \end{tikzpicture}
}

\begin{document}

\setlength\arrayrulewidth{1.2pt}

%
\blindtext[1]
%
\begin{table}[tbp]
    \caption{First table}
    \label{tab:first}
    \begin{rndtable}{Llr}
        \rowcolor{white}
        \cornercell{\textbf{Label}} & \textbf{Naam} & \textbf{Leeftijd}\\
        \arrayrulecolor{lichtgrijs} \hline
       GK & Paul Robinson & 45\\
        MC & Jody Morris  & 75\\
        FW & Jamie McMaster  & 13\\
        \arrayrulecolor{lichtgrijs}\hline
    \end{rndtable}
\end{table}
%
\begin{table}[tbp]
    \caption{Second table with narrow last column and heigh head line}
    \label{tab:second}
    \begin{rndtable}[0.68\baselineskip]{LlrM{2cm}}
       \rowcolor{white}
       \cornercell{\textbf{Label}} & \textbf{Naam} & \textbf{Leeftijd} 
                                    & \textbf{Length in centimeter} \\
        \arrayrulecolor{lichtgrijs} \hline
        GK & Paul Robinson & 45 & 178\\
        MC & Jody Morris  & 75 & 182\\
       FW & Jamie McMaster  & 13 & 150\\
        \arrayrulecolor{lichtgrijs}\hline
    \end{rndtable}
\end{table}

Reference to \ref{tab:first} and \ref{tab:second} table. 


\blindtext[1]

\end{document}

The result looks like this

tables with rounded corners

Exactly as I want it. The good thing of this code is that you can just replace tabular for rndtable; all the rest remains the same compared to a normal tabular. The only thing is that the first cell needs to contain the cornercell tikz node which places a node (A) in the first cell. This node is used in the macro to get to the bottom table line of the first row.

There is one catch: In case you have a multi-line columns (such as in the second table), the RowDepth is not the valid distance between the bottom of the text to the rowline anymore. To fix this I have added an optional argument to allow for an extra shift downwards. Perhaps it would be better to align all text of the first row to the bottom of the cells, but for now I could not find how to do this.

EDIT: to aling the top row of the second table to the bottom I now use b for the tabular specifier:

\newcolumntype{G}{>{\columncolor{lichtgrijs}\raggedright\arraybackslash}b}
\newcolumntype{L}{>{\raggedright\arraybackslash}b}

\begin{rndtable}{G{2cm}llL{2cm}}
   \rowcolor{white}
   \cornercell{\textbf{Label}} & \textbf{Naam} & \textbf{Leeftijd}
                                & \textbf{Length in centimeter} \\
    \arrayrulecolor{lichtgrijs} \hline
    GK & Paul Robinson & 45 & 178\\
    MC & Jody Morris  & 75 & 182\\
   FW & Jamie McMaster  & 13 & 150\\
    \arrayrulecolor{lichtgrijs}\hline
\end{rndtable}

In this way the column title get aligned at the bottom and you don't have to specify the offset anymore

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.