15

I'm trying to improve the lines in a tabular with colored rows (lines above a colored row can disappear in the adobe reader at some zoom levels) by redrawing the line above a row after the row itself has be created. I have p-columns so I can't use David's solution here https://tex.stackexchange.com/a/129835/2388.

So I thought to use tikzmark (or some other mark) but can't figure[1] out how to find the right edge. Whatever I do the right mark is at the right side of the page:

\documentclass[]{article}

\usepackage{tikz}
\usetikzlibrary{tikzmark}

\begin{document}
\renewcommand\arrayrulewidth{4pt}

\begin{tabular}{l}
abc    \\\noalign{\hrule height \arrayrulewidth}
blub   \\\noalign{\pgfmark{testa}\hfill\pgfmark{testb}}
abc\tikz [remember picture] \draw [overlay,->] (pic cs:testa)--(pic cs:testb);
\end{tabular}

\end{document}

Is there anyway to put the marks in the \noalign so that they respect the size of the tabular box like \hrule does it?

[1] I naturally can find the edge by putting a mark at the right end of some cell and then calculate the intersection but this is cheating ;-).

  • Well, I just have to vote up this question, don't I?! – Loop Space Sep 20 '13 at 16:05
11

As egreg said, but as you hinted you were using colortbl it is already putting a coloured rule under the cell, so you can just ask it to stick a tikzmark at each end of that, so you know where it is:

enter image description here

\documentclass[]{article}
\usepackage{colortbl}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\makeatletter
\newcount\U@CT@
\def\CT@@do@color{%
\U@tm
  \global\let\CT@do@color\relax
        \@tempdima\wd\z@
        \advance\@tempdima\@tempdimb
        \advance\@tempdima\@tempdimc
        \kern-\@tempdimb
        \leaders\vrule
%^^A                     \@height\p@\@depth\p@
                \hskip\@tempdima\@plus  1fill
\U@tm
        \kern-\@tempdimc
        \hskip-\wd\z@ \@plus -1fill }


\def\U@tm{%
\global\advance\U@CT@\@ne
\tikzmark{test\the\U@CT@}}
%
\makeatother
\begin{document}
\renewcommand\arrayrulewidth{4pt}

\begin{tabular}{l}
\rowcolor{yellow}abc    \\
blub   \\
abc\tikz [remember picture] \draw [overlay,->] (pic cs:test1)--(pic cs:test2);
\end{tabular}

\end{document}

If you want the left edge of the arrow to be the left edge of the colour rather than the cell contents, move the first \U@tm down a few lines after the \kern-\@tempdimb

  • That's a quite interesting idea. I could even put the code for line directly in the \U@tm. Is there a way to know the height of the cell at this moment so that I can shift the line to the top? – Ulrike Fischer Sep 20 '13 at 16:55
  • Not directly (that's why colortbl uses a \leaders\vline\hskip.. as it doesn't know the vertical extent. However you could of course also do you as you did originally and put another tikzmark in a \noalign before the row and use its vertical position. – David Carlisle Sep 20 '13 at 17:45
  • yes. While sitting in the concert I realized that this the same situation as in the horizontal case: only hrule and vrule "know" the space. – Ulrike Fischer Sep 20 '13 at 20:24
  • Getting the vertical position of a hline in longtable isn't easy: The simple \hline\noalign{\tikzmark{hline}} doesn't work at page breaks: The hline is not repeated on the second page and the tikzmark is on the wrong page. And when redefining \LT@@hline one must be careful as colortbl redefines it too at the begin of the document. – Ulrike Fischer Sep 23 '13 at 14:04
  • @UlrikeFischer sorry:-) In a future life I'll write longtable knowing about colortbl, and with the necessary hooks so colortbl doesn't need to redefine it:-) – David Carlisle Sep 23 '13 at 15:08
11

The contents of \noalign is appended to the enclosing vertical list at the specified point; the enclosing vertical list is a \vbox, \vtop or \vcenter depending on the optional argument to tabular (default \vcenter).

Your \hfill starts a paragraph, which will use the current \hsize, so you get an unwanted vertical space and the arrow will be as wide as \linewidth.

The enclosing box's width is not known until the \halign is unpacked as a list of horizontal boxes. For measuring it one can hook in \endtabular, after the \crcr\egroup that finishes off the \halign, using \lastbox tricks.

For instance,

\def\endtabular{\crcr\egroup\tabularhook\egroup$\egroup}
\newdimen\tabularwidth
\def\tabularhook{%
  \setbox0=\lastbox
  \global\tabularwidth=\wd0
  \nointerlineskip\box0 }

will store in \tabularwidth the width of the just ended tabular. But it's too late for your purposes.

Inserting a “phantom line” does the job:

\documentclass[]{article}

\usepackage{tikz}
\usetikzlibrary{tikzmark}

\makeatletter
\newcommand{\measureit}[3]{%
  \\[-\ht\@arstrutbox]
  \multicolumn{#1}{@{}c@{}}{%
    \pgfmark{#2}\hfill\pgfmark{#3}}%
  \\[-\dp\@arstrutbox]}
\makeatother

\begin{document}
\renewcommand\arrayrulewidth{4pt}

\begin{tabular}{l}
abc    \\\noalign{\hrule height \arrayrulewidth}
blub   \measureit{1}{testa}{testb}
abc\tikz [remember picture] \draw [overlay,->] (pic cs:testa)--(pic cs:testb);
\end{tabular}%
\begin{tabular}{l}
abc    \\\noalign{\hrule height \arrayrulewidth}
blub   \\
abc
\end{tabular}

\end{document}

enter image description here

Not a nice syntax and probably improvable.

  • I want to use the code in longtable too, so patching \endtabular is not really an option. The multicolumn-approach is neat, but one needs to know the number of cell. – Ulrike Fischer Sep 20 '13 at 16:56
  • @UlrikeFischer With longtable you can access at the table width, at least the "tentative" one, which stabilizes to the final one after some runs; I'm sure David will be able to concoct something for this. The \endtabular trick might be used for storing the width in the .aux file and reuse the information at the next run for building a zero height box to feed into \noalign with the pgfmarks inside it. – egreg Sep 20 '13 at 17:03
  • @UlrikeFischer For longtable you could just look in \LT@i or whatever the table number is. looking after the tabular with \lastbox is exactly what longtable is doing anyway. – David Carlisle Sep 20 '13 at 17:47
  • @davidcarlisle : I know how how to get the width of a longtable. There is some code here somewhere (from Heiko i think) . But at first I'm trying to find code which works with tabular too. – Ulrike Fischer Sep 20 '13 at 20:41

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.