6

First: This question is similar to Generate rows in table using \multido (or something similar).

Consider the following code:

\documentclass{article}

\usepackage{siunitx}
\usepackage{multido}
\usepackage{booktabs}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
\newcommand*\nederst[1]{\calc{#1*(#1+1)/2}}
\newcommand*\iAlt[1]{\calc{#1*(#1+1)*(#1+2)/6}}

\begin{document}

\makeatletter
  \newcommand*\skyIDtable{}
  \multido{\i = 1+1}{6}{%
    \protected@xdef\skyIDtable{\skyIDtable \i & \i & \i & \nederst{\i} & \iAlt{\i}\\}
  }
\makeatother

\begin{table}
\centering
  \begin{tabular}{
    *{3}{S[table-format = 1]}
    *{2}{S[table-format = 2]}
  }
   \toprule
    {Long text~A} & {Long text~B} & {Long text~C} & {Long text~D} & {Long text~E} \\
   \midrule
    \skyIDtable
   \bottomrule
  \end{tabular}
\end{table}

\end{document}

output

I would like to switch the columns with the rows to get the following:

wanted

How do I do that?

4

More complicated code, but way simpler syntax:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[danish]{babel}

\usepackage{xparse,siunitx,booktabs}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\nederst}{m}
 {
  \fp_eval:n { #1 * (#1+1)/2 }
 }
\DeclareExpandableDocumentCommand{\iAlt}{m}
 {
  \fp_eval:n { #1 * ( #1 + 1 ) * ( #1 + 2 ) / 6 }
 }

\NewDocumentCommand{\printtable}{smmmm}
 {% * = transpose
  % #2 = number of iterations
  % #3 = column/row headers
  % #4 = table preamble
  % #5 = entry specs
  \svend_preparetable:nnn { #2 } { #3 } { #5 }
  \IfBooleanTF{#1}
   { \__svend_make_table_rows:nn { #3 } { #4 } }
   { \__svend_make_table_columns:nn { #3 } { #4 } }
 }

\tl_new:N \l_svend_tablebody_tl
\prop_new:N \l_svend_entries_prop
\int_new:N \l_svend_rows_int
\int_new:N \l_svend_columns_int

\cs_new:Npn \svend_prop_item:Nnn #1 #2 #3
 {
  \prop_item:Nn #1 { #2, #3 }
 }
\cs_generate_variant:Nn \svend_prop_item:Nnn { Nnf , Nfn }

\cs_new_protected:Npn \svend_preparetable:nnn #1 #2 #3
 {% #1=iterations; #2=column/row headers; #3=specs
  \int_set:Nn \l_svend_columns_int { \clist_count:n { #2 } }
  \int_set:Nn \l_svend_rows_int { #1 }
  \prop_clear:N \l_svend_entries_prop
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_rows_int }
   {
    \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
     {
      \prop_put:Nnf \l_svend_entries_prop { ##1,####1 }
       {
        \clist_item:nn { #3 } { ####1 }
       }
     }
   }
 }

\cs_generate_variant:Nn \prop_put:Nnn { Nnf }

\cs_new_protected:Npn \__svend_make_table_columns:nn #1 #2
 {
  % start making the table body
  \tl_set:Nn \l_svend_tablebody_tl
   {
    \begin{tabular}{ #2 }\toprule
   }

  % the header row
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
   {
    \tl_put_right:Nx \l_svend_tablebody_tl
     {
      \int_compare:nF { ##1 == 1 } { & }
      { \clist_item:nn { #1 } { ##1 } }
     }
   }
  \tl_put_right:Nn \l_svend_tablebody_tl { \\ \midrule } % finish the row

  % the table body proper
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_rows_int }
   {
    \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
     {
      \tl_put_right:Nx \l_svend_tablebody_tl
       {
        \int_compare:nF { ####1 == 1 } { & }
        \svend_prop_item:Nnn \l_svend_entries_prop { ##1 } { ####1 }
       }
     }
    \tl_put_right:Nn \l_svend_tablebody_tl { \\ }
   }

  % finish up the table body
  \tl_put_right:Nn \l_svend_tablebody_tl { \bottomrule \end{tabular} }

  % produce the table
  \tl_use:N \l_svend_tablebody_tl
 }

\cs_new_protected:Npn \__svend_make_table_rows:nn #1 #2
 {
  % start building the table body
  \tl_set:Nn \l_svend_tablebody_tl
   {
    \begin{tabular}{ #2 }\toprule
   }

  % the table body proper
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
   {
    \tl_put_right:Nx \l_svend_tablebody_tl
     {
      \clist_item:nn { #1 } { ##1 } &
     }
    \int_step_inline:nnnn { 1 } { 1 } { \l_svend_rows_int }
     {
      \tl_put_right:Nx \l_svend_tablebody_tl
       {
        \int_compare:nF { ####1 == 1 } { & }
        \svend_prop_item:Nnn \l_svend_entries_prop { ####1 } { ##1 }
       }
     }
    \tl_put_right:Nn \l_svend_tablebody_tl { \\ }
   }
  % finish up the table body
  \tl_put_right:Nn \l_svend_tablebody_tl { \bottomrule \end{tabular} }

  % produce the table
  \tl_use:N \l_svend_tablebody_tl
 }

\cs_generate_variant:Nn \prop_item:Nn { Nx }

\ExplSyntaxOff

\begin{document}

\printtable
 {6}
 { Long text A, Long text B, Long text C, Long text D, Long text E }
 { *{3}{S[table-format = 1]} *{2}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\bigskip

\printtable*
 {6}
 { Opstillingsnummer, Antal lag, Antal bægre i bundes side,
   Antal bægre i nederste lag, Antal bægre i optillingen }
 { l *{6}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\bigskip

\printtable
 {7}
 { Long text A, Long text B, Long text C, Long text D, Long text E }
 { *{3}{S[table-format = 1]} *{2}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\bigskip

\printtable*
 {7}
 { Opstillingsnummer, Antal lag, Antal bægre i bundes side,
   Antal bægre i nederste lag, Antal bægre i optillingen }
 { l *{7}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\end{document}

enter image description here

The table entries are computed and stored in a property list, indexed by row,column.

Then the table is printed columnwise (no *) or rowwise, gathering the appropriate index from the property list.

The first argument is the number of iteration, the second argument is the comma separated list of column or row headers (used for determining the number of columns/rows), the third argument is the table preamble; finally come the specifiers, where #1 is used for the current integer.

  • I've added another question for you at the bottom of my original question. – Svend Tveskæg Dec 22 '14 at 22:44
  • @SvendTveskæg Please, remove the addition, as it doesn't belong to the question. Why not using spaces, as they are ignored in the programming environment? Control sequence names can't have spaces in them, of course. – egreg Dec 22 '14 at 22:49
  • Okay. Removed. (I was just wondering, that's all.) – Svend Tveskæg Dec 22 '14 at 22:55
  • Hi again egreg. How do I get a comma (,) instead of a full stop (.) as decimal separator in the entries? (I can of course wrap the entries in the fifth argument to \printtable in a \num from siunitx but I would like to not have to do this every time (do to laziness).) – Svend Tveskæg Mar 14 '15 at 15:54
  • @SvendTveskæg Since the table uses siunitx features, you should try issuing \sisetup{output-decimal-marker={,}} in the document preamble. – egreg Mar 14 '15 at 15:57
5

I show the plain TeX-like solution but it works in LaTeX too because only eTeX primitives and \newcount macro are used. We needn't any LaTeX packages.

\def\nederst#1{\the\numexpr #1*(#1+1)/2 \relax}
\def\iAlt#1{\the\numexpr #1*(#1+1)*(#1+2)/6 \relax}

\newcount\i \i=1
\def\skyIDtable{
   \the\i & \the\i & \the\i & \hbox to1em{\hss\nederst\i} & \hbox to1em{\hss\iAlt\i}
   \global\advance\i by 1
   \ifnum\i<7 \global\let\next=\skyIDtable \else \global\let\next=\empty \global\i=1 \fi
   \cr \next
}
\def\trline#1{#11 & #12 & #13 & #14 & #15 & #16 \cr}
\def\skyIDtableT{
   Opstillingsnummer            & \trline\relax  
   Antal lag                    & \trline\relax  
   Antal bægre i bundes side    & \trline\relax  
   Antal bægre i nederste lag   & \trline\nederst
   Antal bægre i optillingen    & \trline\iAlt
}

\def\toprule{\noalign{\smallskip\hrule height1pt\smallskip}}\let\botrule=\toprule
\def\midrule{\noalign{\smallskip\hrule\smallskip}}

Normal table:

\hfil\vbox{\halign{&\enspace\hfil#\unskip\hfil\enspace \cr
   \toprule
   Long text A & Long text B & Long text C & Long text D & Long text E \cr
   \midrule   
   \skyIDtable
   \botrule
}}

Transposed table:

\hfil\vbox{\halign{\enspace #\unskip\enspace\hfil&&\enspace\hfil#\unskip\enspace\cr
   \toprule
   \skyIDtableT
   \botrule
}}

\bye
4

The transposition is not as straight-forward. You'll have to cycle through each row individually:

enter image description here

\documentclass{article}

\usepackage{siunitx,multido,booktabs}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
\newcommand*\nederst[1]{\calc{#1*(#1+1)/2}}
\newcommand*\iAlt[1]{\calc{#1*(#1+1)*(#1+2)/6}}

\begin{document}

\centering

\makeatletter
\newcommand\skyIDtable{}
\multido{\i=1+1}{6}{% Construct 6 rows
  \protected@xdef\skyIDtable{\skyIDtable \i & \i & \i & \nederst{\i} & \iAlt{\i}\protect\\}%
}
\makeatother

\begin{tabular}{
  *{3}{S[table-format = 1]}
  *{2}{S[table-format = 2]}
}
 \toprule
 {Long text~A} & {Long text~B} & {Long text~C} & {Long text~D} & {Long text~E} \\
 \midrule
 \skyIDtable
 \bottomrule
\end{tabular}

\bigskip

% Transposed table

\makeatletter
\newcommand\skyIDtableT{Long text A}% First column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \i}}% Add first row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text B}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \i}}% Add second row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text C}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \i}}% Add third row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text D}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \nederst{\i}}}% Add fourth row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text E}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \iAlt{\i}}}% Add fifth row entries
\makeatother

\begin{tabular}{
  l
  *{6}{S[table-format = 2]}
}
 \toprule
 \skyIDtableT \\% Insert constructed table
 \bottomrule
\end{tabular}

\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.