2

I've recently asked a question about the possibility to align cells in a tabular on something other than left, right and center. S. Segletes proposed a solution where cells had to be split in two parts, what I don't want to do.

D. Carlisle suggested to extend the cell content to some fixed dimension in order to get the desired alignment by right aligning them.

I've tried to implement a solution quite similar to that but by optimizing the extra space used to get the perfect alignment. This requires a two-pass strategy where the dimension of every cell is stored on the first pass so that the correct additional spacing can be computed on the second pass.

The code below allowed me to get this result (bounding box of cell content is light blue) :

enter image description here

To achieve that, I had to find a way to identify preciseley the column a cell is in. I did that by defining a counter and two new column types that would allow for the counter to be reset and incremented.

\newcolumntype{Q}{>{\setcounter{@column}{0}}r}
\newcolumntype{R}{>{\stepcounter{@column}}r}

I am not satisfied with this solution.

Isn't there already a mechanism (provided by tabular) that would allow me to identify the column from inside a cell?

\documentclass[margin=2cm]{standalone}
\usepackage{array, tikz}

\makeatletter

% Tounters for tables (useless for the moment)
% and columns:
\newcounter{@table}
\newcounter{@column}

% The @columns counter needs to be incremented
% each time we switch to a new column and reset
% each time we switch to a new row.
%
% Defining a new column type for the first column
% (resetting the counter) and for ordinary columns
% (increasing the counter).
\newcolumntype{Q}{>{\setcounter{@column}{0}}r}
\newcolumntype{R}{>{\stepcounter{@column}}r}

% The following macro will only be executed form the
% .aux file. It gradually computes the padding 
% needed for a given column in a given table.
\newcommand{\@process@column@padding}[3]{%
% #1 : table number
% #2 : column number
% #3 : right extension of one cell
% --------------------------------
% If the padding register already exists...
\ifcsname column@padding@#1@#2\endcsname%
    % ... replace it's content if the new padding
    % length is bigger ...
    \ifdim\@nameuse{column@padding@#1@#2}<#3%
        \global\@namedef{column@padding@#1@#2}{#3}%
    \fi%
\else%
    % ... or define the padding register.
    \global\@namedef{column@padding@#1@#2}{#3}
\fi%
}

\newcommand{\mycell}[2][]{%
    \tikz[baseline=0, #1]{
        % execute the cells tikz-code
        #2
        
        % visualize the anchor (debug):
            \draw[densely dotted, thick, blue] (0,-1)--(0,1);
            
        % identify right side of bounding box:
        \path (current bounding box.east);
        
        % recover it's coordinates:
        \pgfgetlastxy{\@xcoord}{\@ycoord}
        
        % needed to avoid a "Undefined control
        % sequence" error on \@xcoord:
        \global\edef\@extension{\@xcoord}
        
        % write processing command to aux file
        \immediate\write\@auxout{\string\@process@column@padding{\the@table}{\the@column}{\@xcoord}}
        
        % visualize bounding box (debug):
            \fill[blue, opacity=.1] (current bounding box.south west) rectangle (current bounding box.north east);
    }%
    % check if suitable padding register was already
    % set:
    \ifcsname column@padding@\the@table @\the@column\endcsname%
        % register is set, compute missing length
        % for this cell...
        \pgfmathsetmacro{\@padding}{\@nameuse{column@padding@\the@table @\the@column}-\@extension}%
        % ... and add padding to the right
        \hspace{\@padding pt}%
    \fi%
}


\begin{document}
\begin{tabular}{|Q|R|}
\hline
center & \mycell{\draw[line width=5mm] circle (.6);} \\
\hline
right & \mycell{\draw[line width=2mm] (1,0) circle (.6);} \\
\hline
left & \mycell{\draw (-1,0) circle (.6);} \\
\hline
\end{tabular}
\end{document}
1
  • 1
    No, standard LaTeX's tabular and array's tabular don't have a mechanism to track the column.
    – Skillmon
    Feb 9 at 16:16
3

If you just want to align the cell to the right or left without using another column, you should try the nicematrix package.

Provides a \Block command that allows just that. In the example, the block is one column times one row wide, but it works the same way with multiple columns and multiple rows.

The package creates PGF/Tikz nodes below the cells to place the content. So it may take more than one compile.

x

Loading tikz allows the execution of code in the nodes i-j (the three circles) or using the intersections of the rules (the two red lines). Or from the middle of two nodes to the middle of two other nodes (vertical dotted blue line).

From the manual:

From the manual of nicematrix

\documentclass[margin=2cm]{standalone}
\usepackage{nicematrix,tikz}

\begin{document}

\setlength{\tabcolsep}{0pt}
\newcommand{\square}{\color{blue!10}\rule{2cm}{2cm}}

\newcommand{\squarei}{
    \begin{tikzpicture}
    \fill[red!10!white] (0,0) rectangle (2,2);
    \end{tikzpicture}
}   

\begin{NiceTabular}{m{1cm}m{4cm}}[hvlines]  
    \Block[c]{}{center}& \Block[c]{}{center \\ \square}   \\
    \Block[r]{}{right} & \Block[r]{}{right  \\ \squarei}  \\
    \Block[l]{}{left}  & \Block[l]{}{left   \\ \square}   \\    
    \CodeAfter
        \tikz{%         
            \draw (1-2)[ xshift=-0cm, yshift=-1ex] circle (1) ;
            \draw (2-2)[line width=1mm,  xshift=0.995cm, yshift=-1ex] circle (0.95) ;   
            \draw (3-2)[line width=2mm,  xshift=-0.99cm, yshift=-1ex ]  circle (0.9) ;
            \draw[color=red] (1-|3) -- (2-|2);
            \draw[color=red] (1-|2) -- (2-|3);  
            \draw [densely dotted, thick, blue] (1-|2.5) -- (last-|2.5) ; 
        }   
\end{NiceTabular}   

\end{document}

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.