自动从列表中选择表格

自动从列表中选择表格

可以从列表创建表格吗?我的意思是:

Ex1(每三个元素生成一个新列):

\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley}
\peopleB{A. Hause, J. Ring}
\peopletable

在此处输入图片描述

示例2:

\peopleA{P. Smith, A. Row, B. Streams}
\peopleB{A. Hause, J. Ring}
\peopletable

在此处输入图片描述

例3(若列表为空则生成一个空列):

\peopleA{}
\peopleB{}
\peopletable

在此处输入图片描述

答案1

使用的方法xinttools

\documentclass{article}
\usepackage[hscale=0.8]{geometry}
\usepackage{array}
\usepackage{xinttools}

\newcommand{\peopleA}[1]{%
   % first we trim leading and trailing spaces from each item
   % #1 maybe a macro, it will be expanded; this means first item
   % will be expanded. Prefix this item with a space is this is to
   % be avoided
   \oodef\peopleAlist{\xintCSVtoList{#1}}%
   % now build an array for easy access
   \xintAssignArray\peopleAlist\to\peopleAarray
}%

\newcommand{\peopleB}[1]{%
   \oodef\peopleBlist{\xintCSVtoList{#1}}%
   \xintAssignArray\peopleBlist\to\peopleBarray
}%

\newcommand{\peopletable}{%
   % say we have Na people of type A and Nb people of type B
   % I think from the OP, it is asked to always use three rows
   % from 0 to 3 people of given type, 1 column
   % from 4 to 6 people, 2 columns
   % from 7 to 9 people, 3 columns
   % We do the arithmetic in TeX, not using packages
   \begingroup
     \count0 \peopleAarray{0}
     \advance\count0 by 2
     \divide \count0 by 3
     \ifnum\count0=0 \advance\count0 by 1 \fi
   \edef\peopletableNbOfColsA{\the\count0}%
     \count2 \peopleBarray{0}
     \advance\count2 by 2
     \divide \count2 by 3
     \ifnum\count2=0 \advance\count2 by 1 \fi
   \edef\peopletableNbOfColsB{\the\count2}%
     \count4 = \count0
     \advance\count4 by \count2
   \edef\peopletableNbOfCols{\the\count4}%
   %\show\peopletableNbOfCols
   \edef\peopletableColIndices{\xintSeq{1}{\peopletableNbOfCols}}%
   %\show\peopletableColIndices
   \centering
   \begin{tabular}{|*{\peopletableNbOfCols}{l|}}%
     \hline
     \multicolumn{\peopletableNbOfCols}{|c|}{\textbf{Title}}\\
     \hline
     \multicolumn{\peopletableNbOfColsA}{|l|}{PeopleA}&
     \multicolumn{\peopletableNbOfColsB}{l|}{PeopleB}\\
     \hline
     % first row
     \xintFor* ##1 in {\peopletableColIndices}:
     {\xintifForFirst{}{&}%
      \ifnum##1>\peopletableNbOfColsA\space
         \unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-2>\peopleBarray{0}
         % unfortunately xinttools create arrays checking
         % "index-out-of-range" type of errors, instead
         % of silently expanding to nothing, hence the check above
           \peopleBarray{3*(##1-\peopletableNbOfColsA)-2}%
         \fi
      \else
         \unless\ifnum\numexpr3*##1-2>\peopleAarray{0}
           \peopleAarray{3*##1-2}%
         \fi
      \fi
     }\\
     \hline
     % second row
     \xintFor* ##1 in {\peopletableColIndices}:
     {\xintifForFirst{}{&}%
      \ifnum##1>\peopletableNbOfColsA\space
         \unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-1>\peopleBarray{0}
         % unfortunately xinttools create arrays checking
         % "index-out-of-range" type of errors, instead
         % of silently expanding to nothing, hence the check above
           \peopleBarray{3*(##1-\peopletableNbOfColsA)-1}%
         \fi
      \else
         \unless\ifnum\numexpr3*##1-1>\peopleAarray{0}
           \peopleAarray{3*##1-1}%
         \fi
      \fi
      }\\
      \hline
     % third row
     \xintFor* ##1 in {\peopletableColIndices}:
     {\xintifForFirst{}{&}%
      \ifnum##1>\peopletableNbOfColsA\space
         \unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)>\peopleBarray{0}
         % unfortunately xinttools create arrays checking
         % "index-out-of-range" type of errors, instead
         % of silently expanding to nothing, hence the check above
           \peopleBarray{3*(##1-\peopletableNbOfColsA)}%
         \fi
      \else
         \unless\ifnum\numexpr3*##1>\peopleAarray{0}
           \peopleAarray{3*##1}%
         \fi
      \fi
      }\\
      \hline
   \end{tabular}%
   \par
   \endgroup
}

\begin{document}

\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley}
\peopleB{A. Hause, J. Ring}
\peopletable

\bigskip
With only three rows we soon get wide tables, so let's use digits for
demonstration purposes:


\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley,
  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}

\peopleB{A. Hause, J. Ring, 3, 4, 5, 6, 7, 8, 9, 10}

\peopletable
\end{document}

在此处输入图片描述

(空列时可正常工作)


OP 要求表格占据整个文本宽度,可以用来实现tabularx

\documentclass{article}
\usepackage{geometry}
\usepackage{array}
\usepackage{tabularx}
\usepackage{xinttools}

\newcommand{\peopleA}[1]{%
   % first we trim leading and trailing spaces from each item
   % #1 maybe a macro, it will be expanded; this means first item
   % will be expanded. Prefix this item with a space is this is to
   % be avoided
   \oodef\peopleAlist{\xintCSVtoList{#1}}%
   % now build an array for easy access
   \xintAssignArray\peopleAlist\to\peopleAarray
}%

\newcommand{\peopleB}[1]{%
   \oodef\peopleBlist{\xintCSVtoList{#1}}%
   \xintAssignArray\peopleBlist\to\peopleBarray
}%

\newcommand{\peopletable}{%
   % say we have Na people of type A and Nb people of type B
   % I think from the OP, it is asked to always use three rows
   % from 0 to 3 people of given type, 1 column
   % from 4 to 6 people, 2 columns
   % from 7 to 9 people, 3 columns
   % We do the arithmetic in TeX, not using packages
   \begingroup
     \count0 \peopleAarray{0}
     \advance\count0 by 2
     \divide \count0 by 3
     \ifnum\count0=0 \advance\count0 by 1 \fi
   \edef\peopletableNbOfColsA{\the\count0}%
     \count2 \peopleBarray{0}
     \advance\count2 by 2
     \divide \count2 by 3
     \ifnum\count2=0 \advance\count2 by 1 \fi
   \edef\peopletableNbOfColsB{\the\count2}%
     \count4 = \count0
     \advance\count4 by \count2
   \edef\peopletableNbOfCols{\the\count4}%
   %\show\peopletableNbOfCols
   \edef\peopletableColIndices{\xintSeq{1}{\peopletableNbOfCols}}%
   %\show\peopletableColIndices
   \noindent
   \begin{tabularx}{\linewidth}{|*{\peopletableNbOfCols}{X|}}%
     \hline
     \multicolumn{\peopletableNbOfCols}{|c|}{\textbf{Title}}\\
     \hline
     \multicolumn{\peopletableNbOfColsA}{|l|}{PeopleA}&
     \multicolumn{\peopletableNbOfColsB}{l|}{PeopleB}\\
     \hline
     % first row
     \xintFor* ##1 in {\peopletableColIndices}:
     {\xintifForFirst{}{&}%
      \ifnum##1>\peopletableNbOfColsA\space
         \unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-2>\peopleBarray{0}
         % unfortunately xinttools create arrays checking
         % "index-out-of-range" type of errors, instead
         % of silently expanding to nothing, hence the check above
           \peopleBarray{3*(##1-\peopletableNbOfColsA)-2}%
         \fi
      \else
         \unless\ifnum\numexpr3*##1-2>\peopleAarray{0}
           \peopleAarray{3*##1-2}%
         \fi
      \fi
     }\\
     \hline
     % second row
     \xintFor* ##1 in {\peopletableColIndices}:
     {\xintifForFirst{}{&}%
      \ifnum##1>\peopletableNbOfColsA\space
         \unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-1>\peopleBarray{0}
         % unfortunately xinttools create arrays checking
         % "index-out-of-range" type of errors, instead
         % of silently expanding to nothing, hence the check above
           \peopleBarray{3*(##1-\peopletableNbOfColsA)-1}%
         \fi
      \else
         \unless\ifnum\numexpr3*##1-1>\peopleAarray{0}
           \peopleAarray{3*##1-1}%
         \fi
      \fi
      }\\
      \hline
     % third row
     \xintFor* ##1 in {\peopletableColIndices}:
     {\xintifForFirst{}{&}%
      \ifnum##1>\peopletableNbOfColsA\space
         \unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)>\peopleBarray{0}
         % unfortunately xinttools create arrays checking
         % "index-out-of-range" type of errors, instead
         % of silently expanding to nothing, hence the check above
           \peopleBarray{3*(##1-\peopletableNbOfColsA)}%
         \fi
      \else
         \unless\ifnum\numexpr3*##1>\peopleAarray{0}
           \peopleAarray{3*##1}%
         \fi
      \fi
      }\\
      \hline
   \end{tabularx}%
   \par
   \endgroup
}

\begin{document}

\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley}
\peopleB{A. Hause, J. Ring}
\peopletable

\bigskip
With only three rows we soon get wide tables, so let's use digits for
demonstration purposes:


\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley,
  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}

\peopleB{A. Hause, J. Ring, 3, 4, 5, 6, 7, 8, 9, 10}

\peopletable

\bigskip

\peopleA{}
\peopleB{}

\peopletable
\end{document}

在此处输入图片描述

相关内容