[Tex/LaTex] How to specify the multicolumn width in table header?

multicolumntableswidth

I want to read/input the body of a table from a separate file. I have mostly solved this problem using this question.

But when I try to read a table with multicolumn from a separate file, it failed.
The following is an example.

%main.tex
\documentclass{article}
\usepackage{filecontents,catchfile}
\begin{filecontents*}{table.tex}
%table.tex
    \hline
    A & B  & C & D  \\   \hline
    E & \multicolumn{3}{l|}{This is generated by excel2latex macro. I want to let it auto wrap according to the width of (B+C+D) }   \\      \hline

\end{filecontents*}

\begin{document}

Table test.

\section{Insert a full table}

    \begin{tabular}{|p{2cm}|p{2cm}|p{2cm}|p{2cm}|}
    \hline
    A & B  & C & D  \\   \hline
    E & \multicolumn{3}{p{6cm}|}{This is generated by excel2latex macro. I want to let it auto wrap according to the width of (B+C+D) }   \\      \hline
    \end{tabular}%

\section{ Input the body of table from a separate file}

\CatchFileDef{\mytable}{table.tex}{}% table.tex > \mytable
    \begin{tabular}{|p{2cm}|p{2cm}|p{2cm}|p{2cm}|}
  \mytable
    \end{tabular}%

\end{document}

I just don't want to manually define the width in the body of table because it is generated automatically.

Best Answer

Assume that columns B, C, and D are of the p type with usable widths given by the length parameters \colB, \colC, and \colD. In your example code, these lengths are equal to 2cm each. The total widths of columns B, C, and D are, however, not equal to 2cm. Instead, each column's total width equals 2cm+2\tabcolsep, where \tabcolsep is the parameter that governs the amount of whitespace inserted to the left and right of a column. (In the standard LaTeX document classes, the default value of this parameter is 6pt.)

The combined width of columns B, C, and D -- not counting the widths of the vertical bars to the left of B and to the right of D -- is

\colB + \colC + \colD + 6\tabcolsep + 2\arrayrulewidth 

(I'm assuming, implicitly, that the array package is being loaded. If that's not the case, then one should omit the 2\arrayrulewidth term.) You can probably guess that 2\arrayrulewidth represents the combined widths of the two interior vertical bars -- those separating B from C and C from D. The default value of this parameter is 0.4pt in the standard document classes.

The usable width of the three columns is a bit smaller, since we mustn't impose on \tabcolsep at the left-hand edge of B and at the right-hand edge of D. It is thus given by

\colB + \colC + \colD + 4\tabcolsep + 2\arrayrulewidth

One can create a length variable called, say, \combinedlength and set its value to the expression above. The contents of the external file table.tex would thus be given by

\hline
A & B  & C & D  \\   \hline
E & \multicolumn{3}{p{\combinedlength}|}{This is generated by excel2latex macro. I want to let it auto wrap according to the width of (B+C+D) }   \\      
\hline

The full MWE:

enter image description here

\documentclass{article}
\usepackage{array,filecontents,catchfile}
\begin{filecontents*}{table.tex}
\hline
A & B  & C & D  \\   \hline
E & \multicolumn{3}{p{\combinedlength}|}{This is generated by excel2latex macro. I 
want to let it auto wrap according to the width of (B+C+D) }   \\      
\hline
\end{filecontents*}

%% Define some length parameters and set their values
\newlength\colB \setlength\colB{2cm}
\newlength\colC \setlength\colC{2cm}
\newlength\colD \setlength\colD{2cm}
\newlength\combinedlength 
\setlength\combinedlength{%
    \dimexpr\colB+\colC+\colD+4\tabcolsep+%
    2\arrayrulewidth\relax}

\begin{document}
\section{ Input the body of table from a separate file}

\CatchFileDef{\mytable}{table.tex}{}% table.tex > \mytable
    \begin{tabular}{|p{2cm}|p{\colB}|p{\colC}|p{\colD}|}
    \mytable
    \end{tabular}%
\end{document}
Related Question