Extender una tabla horizontalmente sobre páginas sin rotación ni uso horizontal

Extender una tabla horizontalmente sobre páginas sin rotación ni uso horizontal

Tengo una tabla muy amplia, que me gusta que se extienda horizontalmente a lo largo de las páginas.

  \documentclass[runnngheads]{book}
    \usepackage{longtable}
    \begin{document}
    \begin{longtable}{*{25}c} 
        \hline 
        $a_1$ & $a_2$ & $a_3$ & $b_1$ & $b_2$ & $c_1$ & $c_2$ & $c_3$ & $d_1$ & $d_2$ & $i_1$ & $i_2$ & $e_1$ & $e_2$ & $h_1$ & $h_2$ &test&test 2&test 3 &test 4 & test 5 & test 6 & test 7 & test 8 & test 9\\ 
        \hline 
    \end{longtable}
    \end{document}

¿Alguna idea de cómo hacerlo? Hay muchos ejemplos de expansión vertical pero no pude encontrar ninguno para mi caso. Y tampoco quiero usar el modo horizontal.

Respuesta1

Aquí hay una solución rápidamente pirateada. Como señaló @DavidCarlisle, el \widesplitcomando deesta respuestaProbablemente sea una mejor solución.

\documentclass[draft,runnngheads]{book}
\usepackage{mptab}
\begin{document}
\mptab{\the\columnsep}{\textwidth}{
  {$a_1$, $a_2$, $a_3$, $b_1$,                    $b_2$, $c_1$, $c_2$, $c_3$, $d_1$, $d_2$, $i_1$, $i_2$, $e_1$, $e_2$, $h_1$, $h_2$, test,  test22, test33, test 4, test 5, test 6, test 7, test 8, test 9},
  {$x_1$, $x_2$, $x_3$, $y_1$,                    $y_2$, $z_1$, $z_2$, $z_3$, $t_1$, $t_2$, $w_1$, $w_2$, $f_1$, $f_2$, $g_1$, $g_2$, hello, world,  bye,    bye,    lots,   of,     data,   beep,   boop},
  {$x_1$, $x_2$, $x_3$, $y_1$,                    $y_2$, $z_1$, $z_2$, $z_3$, $t_1$, $t_2$, $w_1$, $w_2$, $f_1$, $f_2$, $g_1$, $g_2$, hello, world,  bye,    bye,    lots,   of,     data,   beep,   boop},
  {1,     2,     3,    a rather very long cell,  5,     6,     7,     8,     9,     10,    11,    12,    13,    14,    15,    16,    17,    18,     19,     20,     21,     22,     23,     24,     25},
}
\end{document}

Lo que da el siguiente PDF de 3 páginas: Tres páginas, con las primeras columnas en la primera página, las siguientes columnas en la segunda página y las últimas columnas en la tercera página.

Y aquí está mptab.sty:

Probablemente contenga una cantidad nutritiva de errores y complejidad innecesaria, utiliza una coma en lugar de &y llaves en lugar de \\. No es compatible \hliney no lo he hecho para que puedas especificar el formato (por ejemplo, |no son posibles las líneas verticales). Todo esto debería ser bastante sencillo de agregar al código, y he incluido una cierta cantidad de comentarios. Lo único difícil para mí sería hacer que acepte la sintaxis &y \\, ya que no estoy familiarizado con la conexión a funciones de TeX basadas en códigos cat de bajo nivel. También consume una dimensión temporal existente \newlengthcuando probablemente podría salirse con la suya \bgroup…\egroup, y abusa de \global en muchos lugares.

Pero funciona, al menos en casos sencillos.

Cualquier mejora es bienvenida y este código sucio es de dominio público (CC0, WTFPL, usted elige). Intentaré agregar una alternativa a \hlinela especificación de formato y la posibilidad de mezclar fragmentos de la tabla y el texto, si encuentro tiempo (¡sin promesas!).

\usepackage{tikz}
\newlength{\mylen}
%
\newif\iffirstcolumn%
\newif\iffirstline%
\xdef\i{0}% Initialize column counter before first iteration.
\def\mptab#1#2#3{%
  \bgroup%
  \setlength\columnsep{#1}%
  % row counter:
  \xdef\j{0}%
  % Loop over lines:
  \global\firstlinetrue%
  \foreach \y in {#3}{%
    % Increment row counter
    \xdef\oldj{\j}%
    \pgfmathtruncatemacro{\j}{\j+1}%
    \xdef\j{\j}%
    % Column counter:
    \xdef\oldi{\i}%
    \xdef\i{0}%
    \foreach \x in \y{%
      % Increment column counter:
      \pgfmathtruncatemacro{\i}{\i+1}%
      \xdef\i{\i}%
      % Compute width of current column
      \settowidth{\mylen}{\x}%
      \iffirstline%
        \expandafter\xdef\csname column\i maxwidth\endcsname{\the\mylen}%
      \else%
        % Make an alias for the currently computed column max width, for convenient access:
        \expandafter\let\expandafter\currentcolumnmaxwidth\csname column\i maxwidth\endcsname%
        % Compare this cell's width:
        \ifdim\mylen>\currentcolumnmaxwidth\relax%
          % And update the column's max width when the current cell is wider:
          \expandafter\xdef\csname column\i maxwidth\endcsname{\the\mylen}%
        \fi%
      \fi%
      % Remember the contents of this cell:
      \global\expandafter\let\csname cell\i x\j\endcsname\x%
    }%
    \global\firstlinefalse%
  }
  % 
  % Remember last column number:
  % For some reason, the foreach loop from tikz gives the line with an extra
  % pair of braces (which breaks the inner loop, as it sees only one value)
  % when there's no trailing comma after the last line, but gives an empty
  % line when there is a trailing comma. We detect this idiosyncrasy here and
  % revert the last column number and last line:
  \ifnum\i=0\relax%
    \xdef\lastcolumn{\oldi}%
    \xdef\lastline{\oldj}%
  \else%
    % We still keep the "reasonnable" behaviour here, just in case.
    \xdef\lastcolumn{\i}%
    \xdef\lastline{\j}%
  \fi%
  % \message{Last line: \lastline, Last column: \lastcolumn}%
  % 
  %
  % Initialization for the loop which aggregates all cells per page:
  \expandafter\xdef\csname tablepage1\endcsname{}%
  \expandafter\xdef\csname tableformat1\endcsname{}%
  \global\firstlinetrue%
  % Counter for the last page:
  \xdef\maxtablepage{1}%
  %
  % Loop over lines, aggregating each cell in its page.
  \foreach \y in {1,...,\lastline}{%
    \global\setlength{\mylen}{0pt}%
    \xdef\curtablepage{1}
    \global\firstcolumntrue%
    % Loop over the columns, aggregating each cell in its page.
    \foreach \x in {1,...,\lastcolumn}{%
      \global\addtolength{\mylen}{\columnsep}%
      \global\addtolength{\mylen}{\csname column\x maxwidth\endcsname}%
      \global\addtolength{\mylen}{\columnsep}%
      \ifdim\mylen>#2\relax%
        % Push to next page
        % Reset loop variables:
        \global\setlength{\mylen}{0pt}%
        % Re-add current cell width:
        \global\addtolength{\mylen}{\columnsep}%
        \global\addtolength{\mylen}{\csname column\x maxwidth\endcsname}%
        \global\addtolength{\mylen}{\columnsep}%
        % Bump table page number:
        \pgfmathtruncatemacro{\curtablepage}{\curtablepage+1}%
        \xdef\curtablepage{\curtablepage}
        % Initialize new empty page and format:
        \iffirstline
          \expandafter\xdef\csname tablepage\curtablepage\endcsname{}%
          \expandafter\xdef\csname tableformat\curtablepage\endcsname{}%
          % Bump the counter for the last page
          \xdef\maxtablepage{\curtablepage}%
        \fi
        % We're back on the first column:
        \global\firstcolumntrue%
      \fi%
      % Still fits on this page (or we just created a brand new page):
      % Create convenient aliases for the current page, format and cell:
      \expandafter\let\expandafter\thiscell\csname cell\x x\y\endcsname%
      \expandafter\let\expandafter\thistablepage\csname tablepage\curtablepage\endcsname%
      \expandafter\let\expandafter\thistableformat\csname tableformat\curtablepage\endcsname%
      % If we're on the first line, add a new column to the format
      \g@addto@macro\thistableformat{@{\hspace{\the\columnsep}}l@{\hspace{\the\columnsep}}}% THE COLUMN FORMAT HERE
      % Write back to \csname tableformat\curtablepage\endcsname:
      \global\expandafter\let\csname tableformat\curtablepage\endcsname\thistableformat%
      % 
      % The \expandafter and \noexpand tricks
      % are from https://tex.stackexchange.com/a/60976/5699
      % and from https://tex.stackexchange.com/a/67368/5699
      \iffirstcolumn%
      \global\firstcolumnfalse%
      \edef\doit{%
        \noexpand\g@addto@macro\noexpand\thistablepage{%
          % \noexpand\hspace{\noexpand\columnsep}%
          \expandafter\noexpand\thiscell%
          % \noexpand\hspace{\noexpand\columnsep}%
        }%
      }%
      \else%
      \edef\doit{%
        \noexpand\g@addto@macro\noexpand\thistablepage{%
          % \noexpand\hspace{\noexpand\columnsep}%
          & \expandafter\noexpand\thiscell%
          % \noexpand\hspace{\noexpand\columnsep}%
        }%
      }%
      \fi%
      \doit%
      % Write back to \csname tablepage\curtablepage\endcsname:
      \global\expandafter\let\csname tablepage\curtablepage\endcsname\thistablepage%
    }%
    %Add a \\ at the end of the line on each page:
    \foreach \curtablepage in {1,...,\maxtablepage}{%
      % Make an alias
      \expandafter\let\expandafter\thistablepage\csname tablepage\curtablepage\endcsname%
      % Add the "\\"
      \edef\doit{%
        \noexpand\g@addto@macro\noexpand\thistablepage{%
          \noexpand\\%
        }%
      }%
      \doit%
      % Write back to \csname tablepage\curtablepage\endcsname:
      \global\expandafter\let\csname tablepage\curtablepage\endcsname\thistablepage%
    }
    %Finished handling the line:
    \global\firstlinefalse
  }%
  %
  % 
  \foreach \i in {1,...,\curtablepage}{%
    \noindent\begin{tabular}{\csname tableformat\i\endcsname|}%
      \csname tablepage\i\endcsname%
    \end{tabular}%
    \clearpage%
  }%
  %
  \egroup%
}%

información relacionada