# Partially coloring cell background to fake histogram

Excel has a cool feature called "data bar" conditional formatting that allows the user to partially fill a cell background to create histograms based on cell contents. Here is a screen clip example from a workbook:

I'm looking for a TiKZ, minipage, or some other solution that will allow me to only partially color the background of a cell. I've played around with a few options without success.

Here is a minimum working example using \cellcolor from the xcolor package.

\documentclass{article}
\usepackage[table]{xcolor}% http://ctan.org/pkg/xcolor
\begin{document}
\begin{tabular}{l|c|r}
\hline
91.41 & \cellcolor{green!25}90.81 & 38.76 \\
\cellcolor{green!25}98.75 & 13.82 & 94.62 \\
57.11 & \cellcolor{green!25}51.21 & \cellcolor{green!25}42.84 \\
\hline
\end{tabular}
\end{document}


The code above produces:

In a perfect world, I'd have a macro like \partialcellcolor{green!25}{0.41\linewidth} or whatever to specify that the color extends across 41% of the cell. I use "R" to generate the table, so I'll let it do the math as it scripts the latex code.

Any suggestions?

-
I guess this question was asked before but right now I can only find gradient-color-in-one-cell-of-a-table –  Uwe Ziegenhagen Nov 8 '12 at 20:35

# Update with minimal and maximal values

Minimal values are only usable when negative values are disabled (\negativeValuesfalse).

## Code

\documentclass{article}
\usepackage[table]{xcolor}% http://ctan.org/pkg/xcolor
\usepackage{tikz,array,collcell}
\usetikzlibrary{calc}
\pgfdeclarelayer{background}
\pgfdeclarelayer{main}
\pgfsetlayers{background,main}
\newif\ifnegativeValues
\newcommand{\tikzMe}[1]{%
\tikz[baseline]{
\node[anchor=base,text width=\minWidth,align=\alignment,inner sep=0pt,inner xsep=\tabcolsep,outer sep=0pt] (n) {\strut$#1$};
\begin{pgfonlayer}{background}
\ifnegativeValues
\pgfmathparse{#1<0?"red!50":"green!25"}
\edef\color{\pgfmathresult}
\else
\def\color{green!25}
\fi
\pgfmathparse{abs((#1-\minValue)/(\maxValue-\minValue))}
\fill[color=\color] (n.north west) rectangle ($(n.south west)!\pgfmathresult!(n.south east)$);
\end{pgfonlayer}
}
}
%\negativeValuestrue % inserts a minus sign for the minWidth and use red for negative values
\negativeValuesfalse % doesn't insert a minus sign, uses only green

\newcolumntype{H}[3]{%
@{}
>{%
\ifx\\#1\\\def\alignment{right}\else\def\alignment{#1}\fi%
\ifnegativeValues\def\minValue{0.}\else\def\minValue{#2}\fi%
\def\maxValue{#3}%
\def\minWidth{\widthof{$\ifnegativeValues-\fi#3$}}%
\collectcell\tikzMe%
}c<{\endcollectcell}
@{}}
\begin{document}
\begin{tabular}{|H{}{10.}{100.00}|H{}{2.}{105.00}|H{}{0.}{150.00}|}
\hline
10.0   & 2.00   & 0.00   \\
15.49  & 13.82  & 100.00 \\
100.00 & 105.00 & 150.00 \\ \hline
\end{tabular}
\end{document}


## Code

\documentclass{article}
\usepackage[table]{xcolor}% http://ctan.org/pkg/xcolor
\usepackage{tikz,array,collcell}
\usetikzlibrary{calc}
\pgfdeclarelayer{background}
\pgfdeclarelayer{main}
\pgfsetlayers{background,main}
\newcommand*{\minWidth}{\widthof{$-100.00$}}
\newcommand*{\maxValue}{100}
\newcommand{\tikzMeL}[1]{\tikzMe{#1}{left}}
\newcommand{\tikzMeC}[1]{\tikzMe{#1}{center}}
\newcommand{\tikzMeR}[1]{\tikzMe{#1}{right}}
\newcommand{\tikzMe}[2]{%
\tikz[baseline]{
\node[anchor=base,text width=\minWidth,align=#2,inner sep=0pt,inner xsep=\tabcolsep,outer sep=0pt] (n) {\strut$#1$};
\begin{pgfonlayer}{background}
\pgfmathparse{#1<0?"red!50":"green!25"}
\edef\color{\pgfmathresult}
\pgfmathparse{abs(#1/\maxValue)}
\fill[color=\color] (n.north west) rectangle ($(n.south west)!\pgfmathresult!(n.south east)$);
\end{pgfonlayer}
}
}
\newcolumntype{L}{@{}>{\collectcell\tikzMeL}c<{\endcollectcell}@{}}
\newcolumntype{C}{@{}>{\collectcell\tikzMeC}c<{\endcollectcell}@{}}
\newcolumntype{R}{@{}>{\collectcell\tikzMeR}c<{\endcollectcell}@{}}
\begin{document}
\begin{tabular}{|L|C|R|}        \hline
91.41  & 100.00 & 38.76   \\
-15.49 & -13.82 & -100.00 \\
57.11  & 51.21  & -42.84  \\ \hline
\end{tabular}
\end{document}


## Output

-
This is a great example of how to keep the data section of the table clean by using the array package embed all the logic in the column types. Thanks! –  John Leonard Nov 8 '12 at 22:44
I've been thinking about how to encode \maxValue on a column-by-column basis. For example, \begin{tabular}{|L|C|R|} might look like: \begin{tabular}{|L{0}{100}|C{-20}{120}|R{0}{100}|} where 2 arguments (min and max column range) are included on a column-by-column basis. –  John Leonard Nov 9 '12 at 12:16
@JohnLeonard I've updated my answer. The column H takes three arguments: #1 → alignment (default right), #2 → minimal value, #3 → maximal value. –  Qrrbrbirlbel Nov 9 '12 at 12:38
I switched my "answered" to your solution. THANKS! This is really, really cool! –  John Leonard Nov 9 '12 at 12:42
@Qrrbrbirlbel How can column header row be used with text in it...? –  Nicholas Hamilton Jun 18 '13 at 10:27

Another sans-TikZ alterantive:

\documentclass{article}
\usepackage[table]{xcolor}% http://ctan.org/pkg/xcolor
\usepackage[nomessages]{fp}% http://ctan.org/pkg/fp
\newcommand{\maxnum}{100.00}
\newlength{\maxlen}
\newcommand{\databar}[2][green!25]{%
\settowidth{\maxlen}{\maxnum}%
\FPeval\result{round(#2/\maxnum:4)}%
\rlap{\color{green!25}\hspace*{-.5\tabcolsep}\rule[-.05\ht\strutbox]{\result\maxlen}{.95\ht\strutbox}}%
\makebox[\dimexpr\maxlen-\tabcolsep][r]{#2}%
}
\begin{document}

\begin{tabular}{*{3}{|l}|}
\hline
\databar{91.41} & \databar {90.81} & \databar{38.76} \\
\databar{98.75} & \databar {13.82} & \databar{94.62} \\
\databar{57.11} & \databar {51.21} & \databar{42.84} \\
\databar{20.00} & \databar{100.00} & \databar{80.00} \\
\hline
\end{tabular}
\end{document}


You provide the maximum number (as a macro \maxnum) that is used to calculate the percentage fill. Calculations are performed using fp.

Using this variation of \databar provides a fill that leaves a (barely visible) .5\arrayrulewidth on either side of the table cell. This is just to avoid any kind of artefacts caused by the viewer. The TikZ solution doesn't show this since it draws the coloured boxes in the background (almost as an underlay) of the entire table, so the rules overdraw any overlap:

%...
\newcommand{\databar}[2][green!25]{%
\settowidth{\maxlen}{\maxnum}%

@Sparr: I've added that to my answer. I've still kept a small (.5\arrayrulewidth) gap between the box and the tabular rules, since a reader may show an "overlap", although this is actually not the case. If you really don't want that, you can remove any reference to \arrayrulewidth in the updated version of \databar. –  Werner Nov 8 '12 at 21:19
@Werner: It was hard to pick, but I have to go with your non-Tikz option. Thanks!!!! I'm going to play with this base code so that the maximum value in each column is used to scale the histograms. This version hard codes \maxnum to 100, but in my working code I'll need to use \maxnum over all the values in a given column. –  John Leonard Nov 8 '12 at 21:20
@JohnLeonard: That can be achieved using the array` package and specifying a new column type that takes the "maximum value" as an argument. –  Werner Nov 8 '12 at 21:22