Strike out a table cell

I'm trying to strike out cells in a table, without specifying the cell width. To do so, I looked at the code of colortbl as this seems to a very decent job with filling cells.

Now I played around with all those \@tempdim but without any success. Honestly I have no idea what I'm doing.

If possible, I'd like to get rid of tikz.

What I have tried so far

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage{tikz,colortbl}
\makeatletter
\newcommand*\notableentry{%
\@tempdima\wd\z@
\tikz[remember picture]{\coordinate (X) at (-.5\tabcolsep-\@tempdima-\@tempdimb-\@tempdimc,-1.1\tabcolsep);}
\hskip\@tempdima\@plus 1fill
\kern-\tabcolsep
\hskip-\wd\z@ \@plus -1fill
\tikz[remember picture]{\coordinate (Y) at (.5\tabcolsep+\@tempdima+\@tempdimb,\@tempdima-.25\tabcolsep);}
}
\makeatother
\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
cagja & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}
\tikz[remember picture,overlay]{%
\draw[red] (X) -- (Y);
\draw[red] (X |- Y) -- (Y |- X);
}

\begin{tabular}{|p{4cm}|p{3cm}|}
\hline
alghreaiog & bghsah \\
\hline
cagja\par bla & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \par xyz \\
\hline
\end{tabular}
\tikz[remember picture,overlay]{%
\draw[red] (X) -- (Y);
\draw[red] (X |- Y) -- (Y |- X);
}
\end{document}


Output

It seems to work for c columns, but fails for all other purposes, while \cellcolor always works.

-
does it have to be a cross (which is a bit harder) or can it be a horizontal line (which you can do directly with colortbl) – David Carlisle Jan 27 '14 at 10:26
@DavidCarlisle A cross is desirable (...my supervisor, etc...), but I will also accept an answer (and reward it with a bounty) featuring a horizontal line, if you explain, why a cross is not possible. – Henri Menke Jan 27 '14 at 10:29
a cross is possible, but more likely to need tikz (or at least some back end support) – David Carlisle Jan 27 '14 at 10:51

The following example uses package zref-savepos to get the positions of the cell. \vadjust pre (a newer feature invented by pdfTeX and also available in LuaTeX and XeTeX) puts the position marker right above the current cell and \vadjust puts the marker below.

\notableentry uses \multicolumn{1}{@{}c@{}|} to get the full cell width without \tabcolsep spacings. \hspace{0pt plus 1filll} is used to override the c specifier to get a position marker to the left and right of the cell.

The label names for the position markers (\zsavepos) are automatically generated with the help of counter NoTableEntry.

Finally the coordinates of the cell's bounding box are calculated and the cross drawn via tikz.

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage{tikz,colortbl}
\usetikzlibrary{calc}
\usepackage{zref-savepos}

\newcounter{NoTableEntry}
\renewcommand*{\theNoTableEntry}{NTE-\the\value{NoTableEntry}}

\newcommand*{\notableentry}{%
\multicolumn{1}{@{}c@{}|}{%
\stepcounter{NoTableEntry}%
\zsavepos{\theNoTableEntry l}% left
\hspace{0pt plus 1filll}%
\zsavepos{\theNoTableEntry r}% right
\tikz[overlay]{%
\draw[red]
let
\n{llx}={\zposx{\theNoTableEntry l}sp-\zposx{\theNoTableEntry r}sp},
\n{urx}={0},
\n{lly}={\zposy{\theNoTableEntry b}sp-\zposy{\theNoTableEntry r}sp},
\n{ury}={\zposy{\theNoTableEntry t}sp-\zposy{\theNoTableEntry r}sp}
in
(\n{llx}, \n{lly}) -- (\n{urx}, \n{ury})
(\n{llx}, \n{ury}) -- (\n{urx}, \n{lly})
;
}%
}%
}

\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
cagja & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}

\begin{tabular}{|p{4cm}|p{3cm}|}
\hline
alghreaiog & bghsah \\
\hline
cagja\par bla & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \par xyz \\
\hline
\end{tabular}
\end{document}


Restriction to package pgf

The following modification restricts the drawing to the low level package pgf instead of using the front-end package tikz.

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage{colortbl}
\usepackage{pgf}
\usepackage{zref-savepos}

\newcounter{NoTableEntry}
\renewcommand*{\theNoTableEntry}{NTE-\the\value{NoTableEntry}}

\newcommand*{\notableentry}{%
\multicolumn{1}{@{}c@{}|}{%
\stepcounter{NoTableEntry}%
\zsavepos{\theNoTableEntry l}% left
%
\begin{pgfpicture}%
\pgfsetlinewidth{.4pt}%
\pgfsetstrokecolor{red}%
\edef\llx{0sp}%
\edef\urx{%
\the\numexpr
\zposx{\theNoTableEntry r}%
-\zposx{\theNoTableEntry l}%
\relax sp%
}%
\edef\lly{%
\the\numexpr
\zposy{\theNoTableEntry b}%
-\zposy{\theNoTableEntry l}%
\relax sp%
}%
\edef\ury{%
\the\numexpr
\zposy{\theNoTableEntry t}%
-\zposy{\theNoTableEntry l}%
\relax sp%
}%
\pgfpathmoveto{\pgfpoint{\llx}{\lly}}%
\pgfpathlineto{\pgfpoint{\urx}{\ury}}%
\pgfpathmoveto{\pgfpoint{\llx}{\ury}}%
\pgfpathlineto{\pgfpoint{\urx}{\lly}}%
\pgfusepath{stroke}%
\pgfresetboundingbox
\end{pgfpicture}%
%
\hspace{0pt plus 1filll}%
\zsavepos{\theNoTableEntry r}% right
}%
}

\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
cagja & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}

\begin{tabular}{|p{4cm}|p{3cm}|}
\hline
alghreaiog & bghsah \\
\hline
cagja\par bla & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \par xyz \\
\hline
\end{tabular}
\end{document}


Without pgf

The next solution uses \rotatebox to rotate a rule with the length of the hypotenuse/diagonal and \reflectbox to get the other diagonal of the cross. The calculations of the length of the hypotenuse and the rotation angle are done via package l3fp.

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage{colortbl}
\usepackage{zref-savepos}
\usepackage{graphicx}
\usepackage{xparse, l3fp}

\ExplSyntaxOn
\NewDocumentCommand { \NTECalcHypotenuse } { m m } {
\fp_to_int:n { sqrt ( #1 * #1 + #2 * #2 ) - 0.5 }
}
\NewDocumentCommand { \NTECalcAngle } { m m } {
\fp_to_decimal:n { atand ( #1 / #2 ) }
}
\ExplSyntaxOff

\newcounter{NoTableEntry}
\renewcommand*{\theNoTableEntry}{NTE-\the\value{NoTableEntry}}

\newcommand*{\notableentry}{%
\multicolumn{1}{@{}c@{}|}{%
\stepcounter{NoTableEntry}%
\zsavepos{\theNoTableEntry l}% left
%
\sbox0{%
\color{red}%
\edef\llx{0}%
\edef\urx{%
\the\numexpr
\zposx{\theNoTableEntry r}%
-\zposx{\theNoTableEntry l}%
\relax
}%
\edef\lly{%
\the\numexpr
\zposy{\theNoTableEntry b}%
-\zposy{\theNoTableEntry l}%
\relax
}%
\edef\ury{%
\the\numexpr
\zposy{\theNoTableEntry t}%
-\zposy{\theNoTableEntry l}%
\relax
}%
\edef\w{\the\numexpr\urx-\llx\relax}%
\edef\h{\the\numexpr\ury-\lly\relax}%
\ifnum\w=0 %
\else
\setbox0=\hbox{%
\edef\angle{\romannumeral-x\NTECalcAngle{\h}{\w}}%
\raisebox{\the\numexpr\zposy{\theNoTableEntry b}%
-\zposy{\theNoTableEntry l}\relax sp%
}{%
\rotatebox{\angle}{%
\vrule width\NTECalcHypotenuse{\h}{\w}sp height.2pt depth.2pt%
}%
}%
}%
\rlap{\unhcopy0}%
\reflectbox{\unhcopy0}%
\fi
}%
\wd0=0pt %
\ht0=0pt %
\dp0=0pt %
\copy0 %
%
\hspace{0pt plus 1filll}%
\zsavepos{\theNoTableEntry r}% right
}%
}

\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
cagja & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}

\begin{tabular}{|p{4cm}|p{3cm}|}
\hline
alghreaiog & bghsah \\
\hline
cagja\par bla & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \par xyz \\
\hline
\end{tabular}
\end{document}


With pict2e

Package pict2e allows arbitrary real numbers in the range [-16383, 16383] for the slope arguments of \line in parentheses. Therefore the example uses 1pt as \unitlength and recalculate the numbers of the \pdfsavepos feature that are given with unit sp to pt.

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage{colortbl}
\usepackage{zref-savepos}
\usepackage{pict2e}
%\usepackage{picture}

\newcounter{NoTableEntry}
\renewcommand*{\theNoTableEntry}{NTE-\the\value{NoTableEntry}}

\makeatletter
\newcommand*{\notableentry}{%
\multicolumn{1}{@{}c@{}|}{%
\stepcounter{NoTableEntry}%
\zsavepos{\theNoTableEntry l}% left
%
\raisebox{%
\dimexpr\zposy{\theNoTableEntry b}sp
-\zposy{\theNoTableEntry l}sp\relax
}[0pt][0pt]{%
\color{red}%
\setlength{\unitlength}{1pt}%
\edef\w{%
\strip@pt\dimexpr\zposx{\theNoTableEntry r}sp%
-\zposx{\theNoTableEntry l}sp\relax
}%
\edef\h{%
\strip@pt\dimexpr\zposy{\theNoTableEntry t}sp%
-\zposy{\theNoTableEntry b}sp\relax
}%
\ifdim\w pt=0pt % prevent error in first run for \line(0,0)
\else
\begin{picture}(0,0)%
% the arguments of \line needs to be expanded,
% because pict2e' needs to see the decimal dot
\edef\x{%
\noexpand\put(0,0){\noexpand\line(\w,\h){\w}}%
\noexpand\put(0,\h){\noexpand\line(\w,-\h){\w}}%
}\x
\end{picture}%
\fi
}%
\hspace{0pt plus 1filll}%
\zsavepos{\theNoTableEntry r}% right
}%
}

\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
cagja & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}

\begin{tabular}{|p{4cm}|p{3cm}|}
\hline
alghreaiog & bghsah \\
\hline
cagja\par bla & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \par xyz \\
\hline
\end{tabular}
\end{document}


Variant with \notableentry inside \multicolumn

In this variant, \notableentry is used inside \multicolumn with c as column specifier. That allows more flexibility regarding the vertical lines and the number of columns, which are covered by the cross.

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage{colortbl}
\usepackage{zref-savepos}
\usepackage{pict2e}
%\usepackage{picture}

\newcounter{NoTableEntry}
\renewcommand*{\theNoTableEntry}{NTE-\the\value{NoTableEntry}}

\makeatletter
\newcommand*{\notableentry}{%
\kern-\tabcolsep
\stepcounter{NoTableEntry}%
\zsavepos{\theNoTableEntry l}% left
%
\raisebox{%
\dimexpr\zposy{\theNoTableEntry b}sp
-\zposy{\theNoTableEntry l}sp\relax
}[0pt][0pt]{%
\color{red}%
\setlength{\unitlength}{1pt}%
\edef\w{%
\strip@pt\dimexpr\zposx{\theNoTableEntry r}sp%
-\zposx{\theNoTableEntry l}sp\relax
}%
\edef\h{%
\strip@pt\dimexpr\zposy{\theNoTableEntry t}sp%
-\zposy{\theNoTableEntry b}sp\relax
}%
\ifdim\w pt=0pt % prevent error in first run for \line(0,0)
\else
\begin{picture}(0,0)%
% the arguments of \line needs to be expanded,
% because pict2e' needs to see the decimal dot
\edef\x{%
\noexpand\put(0,0){\noexpand\line(\w,\h){\w}}%
\noexpand\put(0,\h){\noexpand\line(\w,-\h){\w}}%
}\x
\end{picture}%
\fi
}%
\hspace{0pt plus 1filll}%
\zsavepos{\theNoTableEntry r}% right
\kern-\tabcolsep
}

\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
\multicolumn{2}{|c|}{\notableentry} \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}

\begin{tabular}{|p{4cm}|p{3cm}|}
\hline
alghreaiog & bghsah \\
\hline
cagja\par bla & \multicolumn{1}{c|}{\notableentry} \\
\hline
\cellcolor{blue} & edkhaklgjaj \par xyz \\
\hline
\multicolumn{1}{|c|}{\notableentry} & asdf \\
\hline
\end{tabular}
\end{document}


-
+1 for pre I'd forgotten about that:-) – David Carlisle Jan 27 '14 at 12:29
Magnificent! You will get your bounty in 2 days. Would it be possible to draw the cross using only LaTeX's picture? I don't know if it can do overlay. – Henri Menke Jan 27 '14 at 18:26
@HenriMenke: LaTeX's picture environment only provides lines (\line) with a quite limited set of slopes. – Heiko Oberdiek Jan 27 '14 at 18:51
@HeikoOberdiek Your answer is definitely worth a bounty of 200! Many thanks again. – Henri Menke Jan 29 '14 at 8:24
@GonzaloMedina: I have added a variant of \notableentry, which is used inside \multicolumn. – Heiko Oberdiek Jan 31 '14 at 18:03

colortbl uses \leaders with \vrule to add the panel, normally the \vrule extends to the full height/depth of the containing box which is why it fills the cell, however if you specify a fixed height and depth then you get a horizontal line. note that you can't see at the TeX macro layer what the extent of the box is, that is resolved later in the alignment code in TeX's internals. So even though \vrule draws a line from top to bottom, you don't know where the "top" is so you can't draw a cross without using something like \pdfsavepos which is what the tikz remember stuff is doing. Then of course even if you know the coordinates you need some back end code to draw a line of a given slope. (You don't need the whole of tikz, but you need something)

As it happens, I developed color and colortbl on a monochrome screen and since black-on-black is a bit hard to read There is a built in option to restrict colortbl to a thin horizontal line. (It would be easy to not use this option all the time and just have a command that locally uses this debug version but:

\documentclass{article}
\pagestyle{empty}% for cropping
\usepackage[debugshow]{colortbl}
\makeatletter
\def\notableentry{\cellcolor{blue}}
\makeatother
\begin{document}
\LARGE
\begin{tabular}{|c|c|}
\hline
alghreaiog & bghsah \\
\hline
cagja & \notableentry \\
\hline
\cellcolor{blue} & edkhaklgjaj \\
\hline
\end{tabular}

\end{document}

-
But actually if you are doing this just doing \hrulefill` is more or less equivalent, and a lot simpler. – David Carlisle Jan 27 '14 at 10:50