3

I want to use a TikZ matrix to draw a table with empty cells. But no matter what I do I run into errors. In particular, LaTeX complains about

! Package pgf Error: No shape named ae-5-4 is known.

Here's the code (far from what I really want):

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{matrix}
\usetikzlibrary{decorations.pathreplacing}
\begin{document}

\begin{tikzpicture}[
    %%---------------------------------------
    dm/.style={decoration={brace,mirror},decorate},
    dd/.style={decoration={brace},decorate},
    %%---------------------------------------
    nlble/.style={inner sep=0pt,anchor=east},
    nlblw/.style={inner sep=0pt,anchor=west},
    %%---------------------------------------
  ]
  \matrix (ae) [matrix of nodes,
                column 1/.style={anchor=west},
                minimum width=2cm,
                column sep=2.5ex,
                row sep=2.5ex,
                matrix of nodes/.style={execute at empty cell=\node {AAA};}
                ]
  {
        & column A & column B & column C & g                 \\
  Row A &          &          &          & a \node (cc)  {}; \\
  Row B &          &          &          &   \node (ss)  {}; \\
  Row C &          &          &          &   \node (alt) {}; \\
  Row D &          &          &          &                   \\
  };
  \foreach \row in {1,2,3,4,5} {%
    \draw[blue,line width=0.4pt] ($(ae-\row-2.base west)-(0,2ex)$) -- ($(ae-\row-4.base east)-(0,2ex)$);
   }
%  \foreach \col in {1,2,3,4}{%
%    \draw[blue,line width=0.4pt] ($(ae-1-\col.base east)-(0,2ex)$) -- ($(ae-4-\col.base east)-(0,2ex)$);
%  }
  \draw[dm]  ($(ae-2-1.west)+(0,2.5ex)$) -- ($(ae-3-1.west)-(0,2.5ex)$) node [midway,anchor=east] (A) {};
  \draw[dm]  ($(ae-4-1.west)+(0,2.5ex)$) -- ($(ae-4-1.west)-(0,2.5ex)$) node [midway,anchor=east] (B) {};
  \draw[dd]  ($(cc.east)+(0,2.5ex)$)     -- ($(cc.east)+(0,-2.5ex)$)    node [midway,anchor=west] (C) {};
  \draw[dd]  ($(ss.east)+(0,2.5ex)$)     -- ($(alt.east)+(0,-2.5ex)$)   node [midway,anchor=west] (D) {};

  \node[nlble] at ($(A)+(-1ex,0)$) {\parbox{1.35in}{\footnotesize\centering Instructions for material to be put in Rows A and B.}};
  \node[nlble] at ($(B)+(-1ex,0)$) {\parbox{1.35in}{\footnotesize\centering Instructions for material to be put in Row C.}};
  \node[nlblw] at ($(C)+(1ex,0)$)  {\parbox{1.5in}{\footnotesize\centering Additional instructions for Row A.}};    
  \node[nlblw] at ($(D)+(1ex,0)$)  {\parbox{1.5in}{\footnotesize\centering Additional instructions for Rows B and C.}};    
\end{tikzpicture}

\end{document}

What I'm most interested in knowing is how to automate drawing horizontal and vertical lines. I'd prefer to do it using the node names that TikZ creates for the cells of a matrix.

Of secondary interest,

  • I would like to know why when I try to add text before the \node {cc}; in the last column of Row A, I get an undefined command error from LaTeX.
  • I would also like to know whether there's a way to define the style for a range of columns (such as columns 2, 3, and 4) without having to declare the style for each individual column or define a style universally for all columns. For example, I only want to set the minimum width for columns 1, 2, and 3.
  • For defining the style for a range of columns, take a look at this answer by Qrrbrbirlbel – Loop Space Sep 20 '13 at 7:10
6

There are a few things going awry with your code.

  1. When you do matrix of nodes then each cell is surrounded by \node[options] (<name>) { ... };. It isn't allowed to nest nodes, so your \node ... in cell 5-2 is illegal. The ones in 5-3 and 5-4 are okay because TikZ takes a look to see if the cell starts with a TikZ command before enclosing it in a node. As the nodes are already there, if you want simply to give them new names then use the syntax for specifying extra options: |[options]| at the start of the cell.

  2. Although you want to give them new names, I think that you also want to refer to them via the ae-m-n syntax. So you actually want to give them aliases. Thus use the alias=<name> key.

  3. The line matrix of nodes/.style={execute at empty cell=\node {AAA};} is bizarre. It overwrites the matrix of nodes style, but you've already executed this. I presume that what you want is for AAA to appear in each blank cell. I don't know if there is a way to do this without hacking the code a little (ie without a \makeatletter) but a simple hack to adjust the code for empty cells solves this. I suspect that there are a couple of cells that you want to be genuinely empty. Putting {} as their contents makes them officially not empty (so doesn't invoke the empty cell code) whilst still being actually empty.

Here's a modification of your code taking the above into account:

\documentclass{article}
%\url{http://tex.stackexchange.com/q/134209/86}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{matrix}
\usetikzlibrary{decorations.pathreplacing}

\makeatletter
\newcommand\myemptycell[1]{%
  \iftikz@lib@matrix@empty\node[name=\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn] {#1};\fi}
\makeatother
\begin{document}

\begin{tikzpicture}[
    %%---------------------------------------
    dm/.style={decoration={brace,mirror},decorate},
    dd/.style={decoration={brace},decorate},
    %%---------------------------------------
    nlble/.style={inner sep=0pt,anchor=east},
    nlblw/.style={inner sep=0pt,anchor=west},
    %%---------------------------------------
  ]
  \matrix (ae) [matrix of nodes,
                column 1/.style={anchor=west},
                minimum width=2cm,
                column sep=2.5ex,
                row sep=2.5ex,
                nodes in empty cells,
                execute at empty cell=\myemptycell{AAA},
                ]
  {
   {}   & column A & column B & column C & g                 \\
  Row A &          &          &          &|[alias=cc]| a \\
  Row B &          &          &          &|[alias=ss]| \\
  Row C &          &          &          &|[alias=alt]| \\
  Row D &          &          &          &               {}    \\
  };
  \foreach \row in {1,2,3,4,5} {%
    \draw[blue,line width=0.4pt] ($(ae-\row-2.base west)-(0,2ex)$) -- ($(ae-\row-4.base east)-(0,2ex)$);
   }
%  \foreach \col in {1,2,3,4}{%
%    \draw[blue,line width=0.4pt] ($(ae-1-\col.base east)-(0,2ex)$) -- ($(ae-4-\col.base east)-(0,2ex)$);
%  }
  \draw[dm]  ($(ae-2-1.west)+(0,2.5ex)$) -- ($(ae-3-1.west)-(0,2.5ex)$) node [midway,anchor=east] (A) {};
  \draw[dm]  ($(ae-4-1.west)+(0,2.5ex)$) -- ($(ae-4-1.west)-(0,2.5ex)$) node [midway,anchor=east] (B) {};
  \draw[dd]  ($(cc.east)+(0,2.5ex)$)     -- ($(cc.east)+(0,-2.5ex)$)    node [midway,anchor=west] (C) {};
  \draw[dd]  ($(ss.east)+(0,2.5ex)$)     -- ($(alt.east)+(0,-2.5ex)$)   node [midway,anchor=west] (D) {};

  \node[nlble] at ($(A)+(-1ex,0)$) {\parbox{1.35in}{\footnotesize\centering Instructions for material to be put in Rows A and B.}};
  \node[nlble] at ($(B)+(-1ex,0)$) {\parbox{1.35in}{\footnotesize\centering Instructions for material to be put in Row C.}};
  \node[nlblw] at ($(C)+(1ex,0)$)  {\parbox{1.5in}{\footnotesize\centering Additional instructions for Row A.}};    
  \node[nlblw] at ($(D)+(1ex,0)$)  {\parbox{1.5in}{\footnotesize\centering Additional instructions for Rows B and C.}};    
\end{tikzpicture}

\end{document}

With result:

Matrix with lines

  • Actually, I didn't want to put AAA in every cell. I'd forgotten to take that out of my code when I posted here. Nevertheless, I was trying to use execute at empty cell as you appear to be using {} in cells 1,1 and 5,5. TikZ was complaining about non-existing objects. I thought I could use this command---following the example from the manual (pg 277-278 of the CVS version of the manual)---to force empty cells to some how be populated. I actually do want them to be empty: the purpose of the horizontal and vertical lines is to create clear borders for answers students will provide. – A.Ellett Sep 20 '13 at 13:13
  • Also, where is the |[...]| code documented? I saw it in the manual, didn't understand how it was working, but couldn't find its documentation (because I didn't know what to search on). – A.Ellett Sep 20 '13 at 13:15
  • @A.Ellett For the first, simply put nodes in empty cells in the options to the matrix. For the second, it's in the documentation for the matrix library. – Loop Space Sep 20 '13 at 15:35

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.