2

I have been trying to solve this problem for days. I have scoured many questions asked on this website, but none seem to address what I am trying to do.

Basically, within a tabular, I want to "slash" some of my cells. This means creating a diagonal line across the cell I want to slash. The tricky part is that I need text to be centered in the cell. We can assume the width and height of cells will always be the same.

I have found a solution that is very close, but I can only get it exactly correct if I manually hard-code the values for each cell I need to slash. I was hoping for a more robust solution that will work no matter what the text is. See my MWE below:

\documentclass[letterpaper, 12pt]{article}
\usepackage{array}
\usepackage{tikz}

\begin{document}
\begin{table}[!ht] \centering

\renewcommand{\arraystretch}{1.6}

\begin{tabular}{|c|c|c|}
\hline
\tikz[overlay,line width=0.8pt]{\draw (\dimexpr0.1cm-2\tabcolsep-2.5\arrayrulewidth,-0.6em) -- (\dimexpr1.1cm-\tabcolsep-\arrayrulewidth,1em+4.5pt)}AAA & A & AA  \\ 
\hline
\tikz[overlay,line width=0.8pt]{\draw (\dimexpr0.1cm-2\tabcolsep-2.5\arrayrulewidth,-0.6em) -- (\dimexpr1.1cm-\tabcolsep-\arrayrulewidth,1em+4.5pt)}AA & AAA & A  \\ 
\hline
\tikz[overlay,line width=0.8pt]{\draw (\dimexpr0.1cm-2\tabcolsep-2.5\arrayrulewidth,-0.6em) -- (\dimexpr1.1cm-\tabcolsep-\arrayrulewidth,1em+4.5pt)}A & A & AAA\\ 
\hline
\end{tabular}
\end{table}

\end{document}

Edit: I edited the above MWE to include multiple columns.

2 Answers2

3

Complete revision: Disclaimer: This is not meant to be a competitor to Tarass' stellar answer. Rather, it is an alternative with lower performance, which however does not require lualatex, which is why I'm posting it. In fact, the only thing it requires in addition to what you've already loaded is the TikZ library calc. This code comes with a new column type which only inserts the TikZ nodes and macro \MeasureLastTable, which you need to place after the table and in which you need to specify the number of columns. This macro determines all relevant length except for one additional vertical shift: the cell contents are not centered vertically and empirically in your example this shift is 2pt. (This number seems to derive from \abovedisplayskip but I did not manage to extract it in a nice way.) After you've "measured" the table, you can cross out single cells with \CrossOut{x} where x specifies the index of the cell in a self-explanatory convention.

\documentclass[letterpaper, 12pt]{article}
\usepackage{array}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcounter{cellindex}

\newcolumntype{C}{>{\stepcounter{cellindex}%
\begin{tikzpicture}[remember picture,baseline=(Cell-\thecellindex-left.base),inner sep=0pt]
\node (Cell-\thecellindex-left){\strut};
\end{tikzpicture}
}c<{\begin{tikzpicture}[remember picture,baseline=(Cell-\thecellindex-right.base),inner sep=0pt]
\node (Cell-\thecellindex-right){\strut};
\end{tikzpicture}}} 

\newcommand{\MeasureLastTable}[1]{
\pgfmathtruncatemacro{\LeftCellIndex}{\thecellindex-1}
\pgfmathtruncatemacro{\AboveCellIndex}{\thecellindex-#1}
\begin{tikzpicture}[overlay,remember picture]
    \path let \p0 = (Cell-\thecellindex-right.east), 
    \p1 = (Cell-\thecellindex-left.west),
    \p2 = (Cell-\LeftCellIndex-right.east),
    \p3 = (Cell-\LeftCellIndex-left.west) in 
    \pgfextra{\pgfmathsetmacro{\tmp}{(\x0+\x1-\x2-\x3)/4}
    \xdef\HorSep{\tmp pt} % horizontal distance between two cell centers
    };
    \path let \p0 = (Cell-\thecellindex-right.north west), 
    \p1 = (Cell-\thecellindex-left.south west),
    \p2 = (Cell-\AboveCellIndex-right.north west),
    \p3 = (Cell-\AboveCellIndex-left.south west) in 
    \pgfextra{\pgfmathsetmacro{\tmp}{(\y2+\y3-\y0-\y1)/4}
    \xdef\VertSep{\tmp pt} % vertical distance between two cell centers
    }; % I know that in principle two coordinates would be sufficient here
\end{tikzpicture}%
}

\newcommand{\CrossOut}[2][]{
\tikz[overlay,remember picture]{
\path let \p0 = (Cell-#2-left.west), 
    \p1 = (Cell-#2-right.east),
    \p2 = (Cell-#2-left.north west),
    \p3 = (Cell-#2-left.south west) in
    \pgfextra{\pgfmathsetmacro{\tmp}{\HorSep-(\x1-\x0)/2}
    \xdef\myxoffset{\tmp pt}
    \pgfmathsetmacro{\tmp}{\VertSep-(\y2-\y3)/2}
    \xdef\myyoffset{\tmp pt}
    };
\draw[thick,#1] ([xshift=-\myxoffset,yshift=-\myyoffset+2pt]Cell-#2-left.south west) -- 
([xshift=\myxoffset,yshift=\myyoffset+2pt]Cell-#2-right.north east);
}}


\begin{document}
\begin{table}[!ht] \centering

\renewcommand{\arraystretch}{1.6}

\begin{tabular}{|C|C|C|}
\hline
AAA & A & AA  \\ 
\hline
AA & AAA & A  \\ 
\hline
A & A & AAA\\ 
\hline
\end{tabular}
\end{table}
\MeasureLastTable{3} %<- the argument is the number of columns of the last table
\CrossOut{1}
\CrossOut{3}
\CrossOut{5}
\CrossOut{8}
\end{document}

enter image description here

Of course, it will be straightforward to replace the \CrossOut macro by some other fancy annotation.

Original answer: The problem with this is that you can always change the table dimensions, and at a given point your macro will break. In this simple case of a one-column table one can at least make sure that the horizontal positions of the end points of the diagonal lines do not have to adjusted by hand. The vertical positions are still hard coded.

\documentclass[letterpaper, 12pt]{article}
\usepackage{array}
\usepackage{tikz}
\newcommand{\tikznode}[2]{\tikz[remember picture,baseline=(#1.base),inner
     sep=0pt]{\node(#1)[inner sep=0pt]{#2};}}
\newcommand{\CrossOut}[2][]{
\tikz[overlay,remember picture]{
\draw[thick,#1] ([yshift=-7pt]#2.south west-|tl.south east) -- 
([yshift=7pt]#2.north east-|br.north west);
}}

\begin{document}
\begin{table}[!ht] \centering

\renewcommand{\arraystretch}{1.6}
\tikznode{tl}{\strut}%
\begin{tabular}{| c |}
\hline
\tikznode{AA1}{AA1}\\
\hline
\tikznode{A2}{A2}\\
\hline
\tikznode{A3}{A3*}\\
\hline
\end{tabular}\tikznode{br}{\strut}
\end{table}
\CrossOut{AA1}\CrossOut{A2}\CrossOut{A3}
\end{document}

enter image description here

  • Okay, that's fair... you accurately answered the question I asked. Do you have a solution that works if there are also columns on either side of the one being striked? I am okay with manually selecting vertical positions. – Michael J Apr 09 '18 at 17:03
  • @MichaelJ Well, you could manually set the width of the cells. Or you could draw the whole thing with TikZ, e.g. using the matrix library. In this case, I would be happy to add this to my answer. If you not, I really have no good idea that always works. See e.g. here how messy the guessing of table parameters can get. Needless to say that the proposal there will break if one does something slightly different than what was foreseen by the author of the answer. –  Apr 09 '18 at 18:15
  • Thank you for your input thus far, I really do appreciate it. Perhaps this helps... in reality, my columns will always have the same width and height, it's just that the text within the columns may change by a letter or two. Assume my table dimensions never change. I am even okay with a solution that manually sets the width and height of the diagonal line; I just need to make sure that it goes from corner to corner of a known sized cell, regardless of what text is in the cell. Given these parameters, do you know of a solution to my issue? Thanks again. – Michael J Apr 09 '18 at 19:12
  • @MichaelJ Sure there is a solution for this scenario, but how do you really make sure that the height is always the same? Just try an example with the first cell containing "a" and the second "b" to see what I mean. Or are you happy to put \struts everywhere? And could you just append such a table to your question? –  Apr 09 '18 at 19:41
  • I edited my original question as requested. If changing the letter makes a minuscule difference in height, then we can assume the same letter always appears, but in varying multiples. See the MWE. Basically, I am simply wondering how to include a fixed size slash for various cells in a tabular that includes text. – Michael J Apr 10 '18 at 13:46
  • @MichaelJ I have completely rewritten my answer. Now it determines almost everything on its own. –  Apr 10 '18 at 18:02
3

TikzTab environment puts tikzmark on each corner of a tabular cell named Xn where X is A,B,... counting from the top line et n is 0,1,2,... counting from the left line.

enter image description here

\documentclass[letterpaper, 12pt]{article}
\pagestyle{empty}

\usepackage{tikz,array,xparse,luacode,tabularx}

\usetikzlibrary{tikzmark}
\newcounter{TikzTabCount}

% insert a phantom line (no height) between two real lines
% containing the tikzmarks
\makeatletter
\NewDocumentCommand{\TikzTabEnd}{O{\NbCols}}{%
    \\[-\ht\@arstrutbox]%
    \Row{#1}\stepcounter{TikzTabCount}%
    \\[-\dp\@arstrutbox]}
\makeatother

\ExplSyntaxOn
\NewDocumentCommand{\CountColumns}{m}
 {% count the number of & tokens in \@preamble
  \regex_count:nvN { \cT\& } { @preamble } \l_tmpa_int
  % they're one less than the columns
  \cs_gset:Npx #1 { \int_eval:n { 1 + \l_tmpa_int } }
 }
\cs_generate_variant:Nn \regex_count:nnN { nv }
\ExplSyntaxOff

% #1 is the real environment : tabular, array, tabularx...
% #2 is optional length for tabularx - don't use otherwise
% #3 tabular optional vertical alignment
% #4 columns pattern 
\NewDocumentEnvironment{TikzTab}{md<>O{c}mO{\NbCols}}{%
    \IfNoValueTF{#2}{%
        \setcounter{TikzTabCount}{2}%
        \begin{#1}[#3]{#4}%
        }{%
        \tabularx{#2}[#3]{#4}%
    }%
    \noalign{\CountColumns{#5}\tikzmark[yshift=5pt]{TTtop}}%
}{%
    \IfNoValueTF{#2}{%
        \end{#1}%
        }{%
        \endtabularx%
        }%
    \foreach \i in {0,...,4} {%
        \tikz[overlay,remember picture]
        \tikzmark{A\i}{({pic cs:TTtop}-|{pic cs:B\i})};
    }
}

% Loop creating the tikzmarkz
\newcommand{\Row}[1]{\directlua{row(#1)}}

\begin{luacode}
function row (s)
    a = "\\multicolumn{1}{@{}c@{}}{\\tikzmark{\\Alph{TikzTabCount}0}"
    for i = 1,s-1
    do
    a=a.."\\strut\\hfill\\tikzmark{\\Alph{TikzTabCount}"..i.."}}&\\multicolumn{1}{@{}c@{}}{"
    end
    a=a.."\\strut\\hfill\\tikzmark{\\Alph{TikzTabCount}"..s.."}}"
    tex.print (a)
    --print (a)
end
\end{luacode}


\begin{document}
\begin{table}[!ht] \centering

\renewcommand{\arraystretch}{1.6}

\begin{TikzTab}{tabular}{|c|c|c|}
\hline
AAA & A & AA  \TikzTabEnd
\hline
\rule{0pt}{3em}AA & AAA & A  \TikzTabEnd 
\hline
\rule[-2em]{0pt}{5em}A & A & AAA\TikzTabEnd
\hline
\end{TikzTab}
\end{table}

\tikz[overlay,remember picture]
        \draw (pic cs:B0) -- (pic cs:A1)
        (pic cs:C0) -- (pic cs:B1)
        (pic cs:D0) -- (pic cs:C1) ;

\foreach \j in {A,B,C,D} {%
\foreach \i in {0,...,3} {%
    \tikz[overlay,remember picture]
        \node[red] at (pic cs:\j\i) {\tiny \j\i} ;
}}
\end{document}
Tarass
  • 16,912