Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

enter image description here

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@
    \advance\@tempdima\@tempdimb
    \advance\@tempdima\@tempdimc
    \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.

enter image description here

share|improve this question
    
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 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 at 10:29
    
a cross is possible, but more likely to need tikz (or at least some back end support) –  David Carlisle Jan 27 at 10:51

2 Answers 2

up vote 22 down vote accepted
+300

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}%
    \vadjust pre{\zsavepos{\theNoTableEntry t}}% top
    \vadjust{\zsavepos{\theNoTableEntry b}}% bottom
    \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}

Result

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}%
    \vadjust pre{\zsavepos{\theNoTableEntry t}}% top
    \vadjust{\zsavepos{\theNoTableEntry b}}% bottom
    \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}%
    \vadjust pre{\zsavepos{\theNoTableEntry t}}% top
    \vadjust{\zsavepos{\theNoTableEntry b}}% bottom
    \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}%
    \vadjust pre{\zsavepos{\theNoTableEntry t}}% top
    \vadjust{\zsavepos{\theNoTableEntry b}}% bottom
    \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}%
  \vadjust pre{\zsavepos{\theNoTableEntry t}}% top
  \vadjust{\zsavepos{\theNoTableEntry b}}% bottom
  \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}

Result

share|improve this answer
2  
+1 for pre I'd forgotten about that:-) –  David Carlisle Jan 27 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 at 18:26
    
@HenriMenke: LaTeX's picture environment only provides lines (\line) with a quite limited set of slopes. –  Heiko Oberdiek Jan 27 at 18:51
1  
@HeikoOberdiek Your answer is definitely worth a bounty of 200! Many thanks again. –  Henri Menke Jan 29 at 8:24
1  
@GonzaloMedina: I have added a variant of \notableentry, which is used inside \multicolumn. –  Heiko Oberdiek Jan 31 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:

enter image description here

\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}
share|improve this answer
    
But actually if you are doing this just doing \hrulefill is more or less equivalent, and a lot simpler. –  David Carlisle Jan 27 at 10:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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