4

I need to generate a table of large size (25x10) where only some particular cells are nonempty (and colored). Creating it by hands is rather difficult. Of course I can use some latex table generators but still I get to a problem if I want to modify the contents of a given cell afterwards (I have to search through dozens of & characters).

Is there a way to create a table where I can modify contents of cell in a way similar to the addressing of 2-D arrays in programming languages, i.e. something like "set cell with coordinates 12, 4 to contain the following text and have the following (background) color"?

demitau
  • 195
  • Review the options in this posting (which I did not do) and there may be something useful there. http://tex.stackexchange.com/questions/49414/comprehensive-list-of-tools-that-simplify-the-generation-of-latex-tables – R. Schumacher Aug 20 '15 at 15:36

1 Answers1

4

Here is an idea. The \sparsetable command has three arguments: the number of rows, the number of columns and the list of entries.

Each item in the list has four arguments: the row index, the column index, the entry and the color. The order is arbitrary.

The macro parses the list, storing the items in a property list that is then used for populating the table body; we exploit the fact that \prop_item:Nn returns nothing if there is no corresponding property.

\documentclass{article}

\usepackage{xcolor}
\usepackage{colortbl}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\sparsetable}{mmm}
 {% #1 = number of rows, #2 = number of columns, #3 = list of entries
  \prop_clear:N \l_demitau_sparse_table_prop
  \clist_map_inline:nn { #3 } { \demitau_sparse_table_cell:nnnn ##1 }
  \demitau_sparse_table:nn { #1 } { #2 }
 }

\prop_new:N \l_demitau_sparse_table_prop
\tl_new:N \l_demitau_sparse_table_body_tl

\cs_new_protected:Nn \demitau_sparse_table_cell:nnnn
 {
  \prop_put:Nnn \l_demitau_sparse_table_prop { #1,#2 } { \cellcolor{#4}#3 }
 }

\cs_new_protected:Nn \demitau_sparse_table:nn
 {
  \tl_clear:N \l_demitau_sparse_table_body_tl
  \int_step_inline:nnnn { 1 } { 1 } { #1 }
   {
    \int_step_inline:nnnn { 1 } { 1 } { #2 - 1 }
     {
      \tl_put_right:Nx \l_demitau_sparse_table_body_tl
       {
        \prop_item:Nn \l_demitau_sparse_table_prop { ##1,####1 } &
       }
     }
    % no trailing & in the last column
    \tl_put_right:Nx \l_demitau_sparse_table_body_tl
     {
      \prop_item:Nn \l_demitau_sparse_table_prop { ##1,#2 }
     }
    \tl_put_right:Nn \l_demitau_sparse_table_body_tl { \\ }
   }
  \begin{tabular}{*{#2}{c}}
  \tl_use:N \l_demitau_sparse_table_body_tl
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\sparsetable{10}{5}{
  {1}{1}{a}{red},
  {1}{4}{b}{blue!50},
  {3}{2}{c}{blue!70},
  {4}{5}{d}{green},
  {10}{1}{e}{gray!70},
  {10}{5}{f}{green},
  {5}{1}{0}{white},
  {6}{1}{0}{white},
  {7}{1}{0}{white},
  {8}{1}{0}{white},
  {9}{1}{0}{white},
}

\end{document}

enter image description here

A couple of changes in the \demitau_sparse_table:nn function gives rules in the table:

\cs_new_protected:Nn \demitau_sparse_table:nn
 {
  \tl_clear:N \l_demitau_sparse_table_body_tl
  \int_step_inline:nnnn { 1 } { 1 } { #1 }
   {
    \int_step_inline:nnnn { 1 } { 1 } { #2 - 1 }
     {
      \tl_put_right:Nx \l_demitau_sparse_table_body_tl
       {
        \prop_item:Nn \l_demitau_sparse_table_prop { ##1,####1 } &
       }
     }
    % no trailing & in the last column
    \tl_put_right:Nx \l_demitau_sparse_table_body_tl
     {
      \prop_item:Nn \l_demitau_sparse_table_prop { ##1,#2 }
     }
    \tl_put_right:Nn \l_demitau_sparse_table_body_tl { \\ \hline }
   }
  \begin{tabular}{|*{#2}{c|}}
  \hline
  \tl_use:N \l_demitau_sparse_table_body_tl
  \end{tabular}
 }

enter image description here

egreg
  • 1,121,712