3

Below example will draw matrix from a array, but I wish to draw grid on it as well just like a table for any list text (longer or shorter)!

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,positioning,calc}
\usepackage{etoolbox}
\newcommand{\JLST}{%
{0,1,2},
{a,b,c},
{f,juice,white rice}%
}
\newcommand{\TBL}[3][M] {%[#1]{name}{list}
    \let\desc\empty
\foreach \col in #3 {%
    \foreach \row [count=\nc] in \col {
        \ifnum\nc > 1%
           \expandafter\gappto\expandafter\desc\expandafter{\&}
         \fi%
        \expandafter\gappto\expandafter\desc\expandafter{\row}%
    }%
    \xappto\desc{\\}%  
}%
\matrix [#1,
    nodes={minimum size=1em,outer sep=0pt,inner sep=1pt},
    append after command={
        \pgfextra{
            \draw ($(\tikzlastnode.north west)$) rectangle ($(\tikzlastnode.south east)$);
        }
    },
    nodes in empty cells,
    column sep=-0.5pt, row sep=-0.5pt,
    matrix of nodes,ampersand replacement=\&] (#2) {
    \desc
};
}
\begin{document}
    \tiny\begin{tikzpicture}
    \TBL[]{M}{\JLST}
    \end{tikzpicture}
\end{document} 

Output:

enter image description here

4

This can be achieved with eqparbox, which allows us to make sure that the nodes in each column have the same width, which is the maximal width of a given column. All this can be made a style, center align per column. (You could also have left or right align, which mimics the column types l and r, respectively.)

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,positioning,calc}
\usepackage{etoolbox}
\usepackage{eqparbox}
\newbox\matrixcellbox
\tikzset{center align per column/.style={nodes={execute at begin
 node={\setbox\matrixcellbox=\hbox\bgroup},
 execute at end
 node={\egroup\eqmakebox[\tikzmatrixname\the\pgfmatrixcurrentcolumn][c]{\copy\matrixcellbox}}}},
}
\newcommand{\JLST}{%
{0,1,2},
{a,b,c},
{f,juice,white rice}%
}
\newcommand{\TBL}[3][M] {%[#1]{name}{list}
    \let\desc\empty
\foreach \col in #3 {%
    \foreach \row [count=\nc] in \col {
        \ifnum\nc > 1%
           \expandafter\gappto\expandafter\desc\expandafter{\&}
         \fi%
        \expandafter\gappto\expandafter\desc\expandafter{\row}%
    }%
    \xappto\desc{\\}%  
}%
\matrix [#1,
    nodes={minimum size=1em,outer sep=0pt,inner sep=1pt},
    draw,thick,inner sep=0pt,
%     append after command={
% %         \pgfextra{
% %             \draw ($(\tikzlastnode.north west)$) rectangle ($(\tikzlastnode.south east)$);
% %         }
%     }, % replaced this by draw
    nodes in empty cells,
    nodes={draw,thin,anchor=center,inner sep=2pt,
    text depth={depth("g")},text height={height("H")}}, %<-added
    center align per column,% <-added
    column sep=-0.4pt, row sep=-0.4pt, % <-changed
    matrix of nodes,ampersand replacement=\&] (#2) {
    \desc
};
}
\begin{document}
    \tiny\begin{tikzpicture}
    \TBL[]{M}{\JLST}
    \end{tikzpicture}
\end{document} 

enter image description here

Alternatively, you can use the styles from here. Then you only need to add matrix dividers,matrix frame=thick,.

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,positioning,calc,fit}
\makeatletter
\long\def\ifnodedefined#1#2#3{% https://tex.stackexchange.com/a/85531
    \@ifundefined{pgf@sh@ns@#1}{#3}{#2}%
}
\tikzset{matrix vlines/.style={execute at end matrix={
\foreach \XX in {1,...,\the\pgf@matrix@numberofcolumns}
{\xdef\FitList{}
\foreach \YY in {1,...,\the\pgfmatrixcurrentrow}
{\ifnodedefined{\tikzmatrixname-\YY-\XX}{\xdef\FitList{\FitList (\tikzmatrixname-\YY-\XX)}}{}
}
\node[fit=\FitList,draw=none,fill=none,inner sep=0pt,draw=none] (\tikzmatrixname-col-\XX) {};
}
\foreach \XX in {2,...,\the\pgf@matrix@numberofcolumns}
{\draw[#1] ($(\tikzmatrixname-col-\XX.west)!0.5!(\tikzmatrixname-col-\the\numexpr\XX-1\relax.east)$)
coordinate (aux) (aux|-\tikzmatrixname.north)
 --  (aux|-\tikzmatrixname.south);
}
}},matrix hlines/.style={execute at end matrix={
\foreach \YY in {1,...,\the\pgfmatrixcurrentrow}
{\xdef\FitList{}
\foreach \XX in {1,...,\the\pgf@matrix@numberofcolumns}
{\ifnodedefined{\tikzmatrixname-\YY-\XX}{\xdef\FitList{\FitList (\tikzmatrixname-\YY-\XX)}}{}
}
\node[fit=\FitList,draw=none,fill=none,inner sep=0pt,draw=none] (\tikzmatrixname-row-\YY) {};
}
\foreach \XX in {2,...,\the\pgfmatrixcurrentrow}
{\draw[#1] ($(\tikzmatrixname-row-\XX)!0.5!(\tikzmatrixname-row-\the\numexpr\XX-1\relax)$)
coordinate (aux) (aux-|\tikzmatrixname.west)
 --  (aux-|\tikzmatrixname.east);
}
}},
matrix dividers/.style={matrix vlines=#1,matrix hlines=#1},
matrix frame/.style={execute at end matrix={
\draw[#1] (\tikz@fig@name.south west) rectangle (\tikz@fig@name.north east);
}}}
\makeatother

\usepackage{etoolbox}
\newcommand{\JLST}{%
{0,1,2},
{a,b,c},
{f,juice,white rice}%
}
\newcommand{\TBL}[3][M] {%[#1]{name}{list}
    \let\desc\empty
\foreach \col in #3 {%
    \foreach \row [count=\nc] in \col {
        \ifnum\nc > 1%
           \expandafter\gappto\expandafter\desc\expandafter{\&}
         \fi%
        \expandafter\gappto\expandafter\desc\expandafter{\row}%
    }%
    \xappto\desc{\\}%  
}%
\matrix [#1,
    nodes={minimum size=1em,outer sep=0pt,inner sep=1pt},
    matrix dividers,matrix frame=thick,
    nodes in empty cells,
    column sep=-0.5pt, row sep=-0.5pt,
    matrix of nodes,ampersand replacement=\&] (#2) {
    \desc
};
}
\begin{document}
    \tiny\begin{tikzpicture}
    \TBL[]{M}{\JLST}
    \end{tikzpicture}
\end{document} 

enter image description here

You may want to adjust the inner sep to 0pt to get

enter image description here

ADDENDUM (per request): this defines the additional styles left align per column and right align per column. (One only needs to change the alignment in \eqmakebox.)

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{matrix}
\usepackage{eqparbox}
\newbox\matrixcellbox
\tikzset{center align per column/.style={nodes={execute at begin
            node={\setbox\matrixcellbox=\hbox\bgroup},
            execute at end
            node={\egroup\eqmakebox[\tikzmatrixname\the\pgfmatrixcurrentcolumn][c]{\copy\matrixcellbox}}}},
left align per column/.style={nodes={execute at begin
            node={\setbox\matrixcellbox=\hbox\bgroup},
            execute at end
            node={\egroup\eqmakebox[\tikzmatrixname\the\pgfmatrixcurrentcolumn][l]{\copy\matrixcellbox}}}},
right align per column/.style={nodes={execute at begin
            node={\setbox\matrixcellbox=\hbox\bgroup},
            execute at end
            node={\egroup\eqmakebox[\tikzmatrixname\the\pgfmatrixcurrentcolumn][r]{\copy\matrixcellbox}}}},                     
}

\begin{document}
    \tiny\begin{tikzpicture}
        \matrix [draw,line width=1pt,inner sep=0pt,nodes in empty cells,
        nodes={
            draw,thin,anchor=center,inner sep=2pt,
            text depth={depth("g")},text height={height("H")},
        }, 
    column 1/.style={right align per column},
    column 2/.style={center align per column},
    column 3/.style={left align per column},
    column sep=-0.4pt, row sep=-0.4pt,
    matrix of nodes] (M) {
        1 & 2 & 3 \\
        aaaaa & bbbb & cccccc \\
    };
    \end{tikzpicture}
\end{document} 

enter image description here

or

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{matrix}
\usepackage{eqparbox}
\newbox\matrixcellbox
\tikzset{column align/.style args={#1/#2}{column #1/.style={nodes={execute at begin
            node={\setbox\matrixcellbox=\hbox\bgroup},
            execute at end node={%
            \egroup\eqmakebox[\tikzmatrixname\the\pgfmatrixcurrentcolumn][#2]{\copy\matrixcellbox}}}}
            }}

\begin{document}
    \tiny\begin{tikzpicture}
        \matrix [draw,line width=1pt,inner sep=0pt,nodes in empty cells,
        nodes={
            draw,thin,anchor=center,inner sep=2pt,
            text depth={depth("g")},text height={height("H")},
        }, 
    column align/.list={1/r,2/c,3/l},
    column sep=-0.4pt, row sep=-0.4pt,
    matrix of nodes] (M) {
        1 & 2 & 3 \\
        aaaaa & bbbb & cccccc \\
    };
    \end{tikzpicture}
\end{document} 

Note, however, that something like \multicolumn and/or \multirow is harder to implement (according to what I know).

| improve this answer | |
  • Awesome, for the l,c,r definition, is it possible to use a argument rather than define 3 different style? – beetlej Mar 5 at 20:38
  • @beetlej Sure, these are all simple modifications. With the /.list key it becomes even more convenient. (I have collected all sorts of tricks somewhere, but unfortunately you cannot easily add \multicolumn or \multirow. Here, "easily" means without making too many assumptions. Everyone could add some execute at end matrix hacks but there are too many special cases that limit the scope.) – user194703 Mar 5 at 21:55
2

I prefer plain matrix and remove unnecessary libraries, more simple to understand:

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usepackage{eqparbox}
\newbox\matrixcellbox
\tikzset{center align per column/.style={nodes={execute at begin
            node={\setbox\matrixcellbox=\hbox\bgroup},
            execute at end
            node={\egroup\eqmakebox[\tikzmatrixname\the\pgfmatrixcurrentcolumn][c]{\copy\matrixcellbox}}}},
}
\begin{document}
    \tiny\begin{tikzpicture}
        \matrix [draw,line width=1pt,inner sep=0pt,nodes in empty cells,
        nodes={
            draw,thin,anchor=center,inner sep=2pt,
            text depth={depth("g")},text height={height("H")},
        }, 
    center align per column,
    column sep=-0.4pt, row sep=-0.4pt,
    matrix of nodes] (M) {
        1 & 2 & 3 \\
        a & b & cccccc \\
    };
    \end{tikzpicture}
\end{document} 

enter image description here

| improve this answer | |
  • Well, the style center align per column is just copied from my answer, isn't it? – user194703 Mar 5 at 18:29
  • @Schrödinger'scat Correct, your answer is great. BTW, how to align text in left? – beetlej Mar 5 at 20:05
  • You only need to change the second optional argument [c] of \eqmakebox to either [l] or [r]. I added this to the answer above. – user194703 Mar 5 at 20:19

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.