3

I can use this to generate a simple table:

\documentclass{article}
\begin{document}
\begin{tabular}{|p{.25\textwidth}|p{.25\textwidth}|p{.5\textwidth}|}\hline
&&\\\hline
&&\\\hline
\end{tabular}
\end{document}

I need a \newcommand\quicktable{........}, and can use it like:

\quicktable{1:1:2}{
&&\\\hline
&&\\\hline
}
  • 1
    With the current column types, your table will be wider than the textwidth, since they do not take into account the \tabcolsep and the \arrayrulewidth. – leandriis Oct 17 '19 at 13:52
  • A precise definition is that I want further more – Zeno Shuai Oct 17 '19 at 14:00
  • @leandriis in the MWE array isn't loaded, so \arrayrulewidth won't contribute to the overall width. – Skillmon likes topanswers.xyz Oct 17 '19 at 14:22
  • Better to use \begin{tabularx}{\linewidth}{|*2{>{\hsize=.75\hsize\linewidth=\hsize}X|}>{\hsize=1.5\hsize\linewidth=\hsize}X|}. – Skillmon likes topanswers.xyz Oct 17 '19 at 14:26
  • 1
    Is the number of columns fixed at 3? What does the 1:1:2 represent? – Peter Grill Oct 17 '19 at 15:05
5

Here's an implementation with xparse and expl3.

The idea is to first sum the items in the “multiratio” so as to establish the modulus. Then a suitable preamble is built, multiplying each item by the modulus and subtracting twice the \tabcolsep.

I set up things so you don't need to type \hline.

The optional argument defaults to \columnwidth, but you can try

\quicktable[10cm]{1:2:1}{&&\\&&}

and see the result.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\quicktable}{ O{\columnwidth} m m }
 {
  \zenoshuai_quicktable:nnn { #1 } { #2 } { #3 }
 }

\seq_new:N \l__zenoshuai_quicktable_header_seq
\seq_new:N \l__zenoshuai_quicktable_body_seq
\tl_new:N \l__zenoshuai_quicktable_header_tl
\dim_new:N \l__zenoshuai_quicktable_modulus_dim

\cs_generate_variant:Nn \seq_set_split:Nnn { NV }

\cs_new_protected:Nn \zenoshuai_quicktable:nnn
 {
  \seq_set_split:NVn \l__zenoshuai_quicktable_header_seq \c_colon_str { #2 }
  \dim_set:Nn \l__zenoshuai_quicktable_modulus_dim
   {
    #1/(\seq_use:Nn \l__zenoshuai_quicktable_header_seq { + })
   }
  \tl_set:Nx \l__zenoshuai_quicktable_header_tl
   {
    |\seq_map_function:NN \l__zenoshuai_quicktable_header_seq \__zenoshuai_quicktable_col:n
   }
  \__zenoshuai_quicktable_body:Vn \l__zenoshuai_quicktable_header_tl { #3 }
 }

\cs_new:Nn \__zenoshuai_quicktable_col:n
 {
  p { \dim_eval:n { #1\l__zenoshuai_quicktable_modulus_dim - 2\tabcolsep } }|
 }

\cs_new_protected:Nn \__zenoshuai_quicktable_body:nn
 {
  \seq_set_split:Nnn \l__zenoshuai_quicktable_body_seq { \\ } { #2 }
  \begin{tabular}{#1}
  \hline
  \seq_use:Nn \l__zenoshuai_quicktable_body_seq { \\ \hline } \\
  \hline
  \end{tabular}
 }
\cs_generate_variant:Nn \__zenoshuai_quicktable_body:nn { V }

\ExplSyntaxOff

\begin{document}

\noindent X\hrulefill X

\bigskip

\noindent
\quicktable{1:1:2}{
&&\\
&&
}

\bigskip

\noindent
\quicktable{2:2:6}{
&&\\
&&
}

\bigskip

\noindent
\quicktable{1:1:1:1}{
&&&\\
&&&
}

\end{document}

enter image description here

A slightly more complicated version that also works when array is loaded.

\documentclass{article}
\usepackage{xparse,array}

% important: code should go after \usepackage{array} or any package that loads it
\ExplSyntaxOn

\bool_new:N \g_zenoshuai_quicktable_array_bool
\use:c { @ifpackageloaded } { array }
 {
  \bool_gset_true:N \g_zenoshuai_quicktable_array_bool
 }
 {
  \bool_gset_false:N \g_zenoshuai_quicktable_array_bool
 }

\NewDocumentCommand{\quicktable}{ O{\columnwidth} m m }
 {
  \zenoshuai_quicktable:nnn { #1 } { #2 } { #3 }
 }

\seq_new:N \l__zenoshuai_quicktable_header_seq
\seq_new:N \l__zenoshuai_quicktable_body_seq
\tl_new:N \l__zenoshuai_quicktable_header_tl
\dim_new:N \l__zenoshuai_quicktable_modulus_dim

\cs_generate_variant:Nn \seq_set_split:Nnn { NV }

\cs_new_protected:Nn \zenoshuai_quicktable:nnn
 {
  \seq_set_split:NVn \l__zenoshuai_quicktable_header_seq \c_colon_str { #2 }
  \dim_set:Nn \l__zenoshuai_quicktable_modulus_dim
   {
    \bool_if:NTF \g_zenoshuai_quicktable_array_bool
     {(#1 - \int_eval:n { \seq_count:N \l__zenoshuai_quicktable_header_seq +1 }\arrayrulewidth) }
     { #1 }
    /(\seq_use:Nn \l__zenoshuai_quicktable_header_seq { + })
   }
  \tl_set:Nx \l__zenoshuai_quicktable_header_tl
   {
    |\seq_map_function:NN \l__zenoshuai_quicktable_header_seq \__zenoshuai_quicktable_col:n
   }
  \__zenoshuai_quicktable_body:Vn \l__zenoshuai_quicktable_header_tl { #3 }
 }

\cs_new:Nn \__zenoshuai_quicktable_col:n
 {
  p { \dim_eval:n { #1\l__zenoshuai_quicktable_modulus_dim - 2\tabcolsep } }|
 }

\cs_new_protected:Nn \__zenoshuai_quicktable_body:nn
 {
  \seq_set_split:Nnn \l__zenoshuai_quicktable_body_seq { \\ } { #2 }
  \begin{tabular}{#1}
  \hline
  \seq_use:Nn \l__zenoshuai_quicktable_body_seq { \\ \hline } \\
  \hline
  \end{tabular}
 }
\cs_generate_variant:Nn \__zenoshuai_quicktable_body:nn { V }

\ExplSyntaxOff

\begin{document}

\noindent X\hrulefill X

\bigskip

\noindent
\quicktable{1:1:2}{
&&\\
&&
}

\bigskip

\noindent
\quicktable{2:2:6}{
&&\\
&&
}

\bigskip

\noindent
\quicktable{1:1:1:1}{
&&&\\
&&&
}

\end{document}
3

The following uses tabularx and its X-type column (though this won't be necessary). It works in a similar manner as @Werner's answer in that it sums the ratios and then uses the entries of the sequence again to set the widths of each column. It adds a \hline before and after the contents of your table.

\documentclass[]{article}

\usepackage{xparse}
\usepackage{tabularx}

\ExplSyntaxOn
\seq_new:N \l__zeno_shuai_columnratios_seq
\int_new:N \l__zeno_shuai_column_count_int
\tl_new:N \l__zeno_shuai_columns_tl
\cs_new_protected:Npn \__zeno_shuai_set_columns:n #1
  {
    \tl_put_right:Nx \l__zeno_shuai_columns_tl
      {
        >{
        \exp_not:n { \hsize = }
        \fp_eval:n
          { #1 * \l__zeno_shuai_column_count_int / \l__zeno_shuai_ratio_sum_fp }
        \exp_not:n { \hsize \linewidth = \hsize }
        }X|
      }
  }
\cs_new_protected:Npn \__zeno_shuai_sum_ratios:n #1
  {
    \fp_add:Nn \l__zeno_shuai_ratio_sum_fp { #1 } 
  }
\cs_new_protected:Npx \__zeno_shuai_parse_widths:n #1
  {
    \exp_not:n
      {
        \tl_set:Nn \l__zeno_shuai_columns_tl { | }
        \seq_set_split:Nnn \l__zeno_shuai_columnratios_seq
      }
      { \c_colon_str } { #1 }
    \exp_not:n
      {
        \int_set:Nn \l__zeno_shuai_column_count_int
          { \seq_count:N \l__zeno_shuai_columnratios_seq }
        \fp_zero:N \l__zeno_shuai_ratio_sum_fp
        \seq_map_function:NN \l__zeno_shuai_columnratios_seq
          \__zeno_shuai_sum_ratios:n
        \seq_map_function:NN \l__zeno_shuai_columnratios_seq
          \__zeno_shuai_set_columns:n
      }
  }
\cs_new_protected:Npn \__zeno_shuai_start_tabularx:nn #1 #2
  {
  }
\cs_generate_variant:Nn \__zeno_shuai_start_tabularx:nn { nV }
\NewDocumentCommand \quicktable { O{\linewidth} m +m }
  {
    \__zeno_shuai_parse_widths:n { #2 }
    \exp_args:NnnV
    \begin { tabularx } { #1 } \l__zeno_shuai_columns_tl
      \hline
      #3
      \crcr
      \hline
    \end { tabularx }
  }
\ExplSyntaxOff

\begin{document}
\quicktable{1:1:2}{a&b&c\\}
\end{document}
2

The following version of \quicktable{<colspec ratio>}{<table>} processes the first argument - <colspec ratio> - twice. The first time it adds up the "ratios" into some total. During the second run it specifies the column width of each column as a ratio of \linewidth (minus the dual column padding provided by \tabcolsep). Finally, it sets the table with the newly-defined column specification, together with the second argument <table>.

enter image description here

\documentclass{article}

\usepackage{xfp}

\newcounter{colnums}
\newcommand{\sumcols}[1]{\setcounter{colnums}{\numexpr\value{colnums}+#1}}
\newcommand{\coldims}[1]{%
  \edef\colspec{\colspec p{\dimexpr\fpeval{#1/\value{colnums}}\linewidth-2\tabcolsep} |}%
}

% \quicktable{<colspec ratio>}{<table>}
\NewDocumentCommand{\quicktable}{>{\SplitList{:}}m m}{%
  \setcounter{colnums}{0}\ProcessList{#1}{\sumcols}% Identify total column ratio
  \def\colspec{|}% Initialize column specification
  \ProcessList{#1}{\coldims}% Update column specification with column widths/dimensions
  \noindent
  \begin{tabular}{\colspec}
    \hline
    #2
  \end{tabular}\par
}

\begin{document}

\quicktable{2:1:4:5}{%
  2 & 1 & 4 & 5 \\
  \hline
}

\quicktable{1:1:2}{
  1 & 1 & 2 \\
  \hline
}

\quicktable{1}{%
  1 \\
  \hline
}

\quicktable{1:2:3:4:5}{%
  1 & 2 & 3 & 4 & 5 \\
  \hline
}

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