删除嵌套表格导致的“Overfull \vbox”消息

删除嵌套表格导致的“Overfull \vbox”消息

我正在尝试排版嵌套表格,如下所示:

\documentclass{article}
\usepackage{bigstrut}
\usepackage{multirow}

\begin{document}

\begin{tabular}{|lll|}
  \hline
   A & \multirow{2}{*}{
      \begin{minipage}{3cm}
        \begin{tabular}{|l|l|}
          \hline
          A & \hfill 1\textsuperscript{st}\bigstrut[t] \\
          \hline
          A & A \\
          \hline
        \end{tabular}
      \end{minipage}
        } &  A \\
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}

\end{document}

这会导致坏盒:Overfull \vbox (3.19998pt too high) detected at line 19

我已经尝试了一段时间来检测这个坏框的确切来源(部分原因是\bigstrut),但我不知道如何删除此警告。我尝试了各种修复方法\\[3.5pt],但我不知道出了什么问题以及如何解决这个问题。可能以完全不同的方式排版表格是“最佳”方法,但目前我对坏框的来源以及如何摆脱它感兴趣。

注意:在这个最小化的例子中,底部中间的 A 与嵌套表重叠,但即使我\\[1cm]对倒数第二行做了类似的事情,坏的(过满)\vbox消息仍然存在(顺便说一下相同的点大小指示)。


编辑

这是一个替代的 MWE,它创建类似的溢出错误,而无需读取嵌套tabular环境:

\documentclass{article}
\usepackage{xcolor}
\usepackage{multirow}
\setlength{\parindent}{0pt}
\newcommand{\vstrut}[3][blue]{{\color{#1}\rule[-#2]{0.4pt}{#3}}}
\newcommand{\hstrut}[2][blue]{{\color{#1}\makebox[0pt][l]{\rule[-0.4pt]{#2}{0.4pt}}}}
\begin{document}

\begin{tabular}{|lll|}
  \hline
   A\vstrut{0ex}{5ex} & \multirow{2}{3cm}{%
      \begin{minipage}[t]{3cm}
            Trial \vstrut[red]{18pt}{18pt}  text
      \end{minipage}} 
                                          & A \\
   A\vstrut{3ex}{3ex}\hstrut{1.65in} & {} & A \\
   A                                 & A  & A \\
  \hline
\end{tabular}

\end{document}

答案1

TeX 是正确的:应该有溢出框(高出 3.2pt):您试图放入两个外部表格行高度的嵌入表格太高了。是什么让它太高了?首先,您\bigstrut[t]嵌入表。这使其高出 2pt。其次,您使用了三个\hlines,每个都\arrayrulewidth=0.4pt很高:这占剩余的 1.2pt。

测试:如果删除bigstrut[t]和,内表将完全适合:\hline

没有 bigstrut 或 hline

\documentclass{article}
\usepackage{bigstrut}
\usepackage{multirow}
\begin{document}
\begin{tabular}{|lll|}
  \hline
   A & \multirow{2}{*}{
        \begin{tabular}{|l|l|}%|
          %\hline
          A & \hfill 1\textsuperscript{st}%
          %\bigstrut[t]
          \\
          %\hline
          A & A \\
          %\hline
        \end{tabular}
        } &  A\\
   A & {} & A\\
   A & A  & A \\
  \hline
\end{tabular}
\end{document}

解决这个问题的方法只有一种:在外表中留出更多空间。考虑到您可能希望内表和外表的行对齐,我建议使用并行。每当您\bigstrut在内表中使用时,也要在外表的同一行中使用它。

但是有一个问题。每当您将外部表格的一行设置为高于正常值时,您都需要告知multirow它,以免出现溢出框。为此,multirow 提供了可选参数bigstruts,用于增加多行单元格的高度bigstruts * \bigstrutjot。因此(我稍微清理了一下 MWE),\bigstrut内部表格中有一个(仅)的示例,因此\bigstrut外部表格中有一个加上可选参数[1]

bigstrut,没有 hlines

\documentclass{article}
\usepackage{bigstrut}
\usepackage{multirow}
\usepackage{xcolor}
\begin{document}
\begin{tabular}{|lll|}
  \hline
   A & \multirow{2}[1]{*}{\color{red}%
        \begin{tabular}{|l|l|}%|
          A & A\bigstrut[t] \\
          A & A\\
        \end{tabular}} &  A\bigstrut[t]  \\
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}
\end{document}

接下来,\hline在嵌入式表中。首先,平行性:我们还必须在外部表中留出额外的垂直空间。我建议使用适当深度的支柱。

\def\hlinestrut{\rule[\dimexpr-\dp\strutbox-\arrayrulewidth]{\dimexpr\dp\strutbox+\arrayrulewidth}{0pt}}

但是,这还不够:同样,我们还必须告诉 multirow 行比正常行高。但是,我们面临一个问题。增加多行单元格高度的唯一方法是使用可选参数bigstruts,该参数仅接受整数值,但 a 的高度\hline不是 的整数倍\bigstrutjot。默认情况下,\arrayrulewidth是 的五分之一\bigstrutjot。除了修补 multirow 以接受浮点数作为参数外,我看不出还有其他方法bigstruts。幸运的是,这很容易,我们要做的就是更改这一点:

%\ifnum#2>0 \advance\@tempdima\bigstrutjot \fi
\ifdim#2pt>0pt \advance\@tempdima\bigstrutjot \fi

现在完整的例子:

bigstrut 和一个 hline

\documentclass{article}
\usepackage{bigstrut}
\usepackage{multirow}
\usepackage{xcolor}
\def\hlinestrut{\rule[\dimexpr-\dp\strutbox-\arrayrulewidth]{\dimexpr\dp\strutbox+\arrayrulewidth}{0pt}}
\makeatletter
\def\@xmultirow#1[#2]#3[#4]#5{\@tempcnta=#1%
  \@tempdima\@tempcnta\ht\@arstrutbox
  \advance\@tempdima\@tempcnta\dp\@arstrutbox
  \ifnum\@tempcnta<0\@tempdima=-\@tempdima\fi
  \advance\@tempdima#2\bigstrutjot
  \if*#3\setbox0\vtop to \@tempdima{\vfill\multirowsetup
    \hbox{\strut#5\strut}\vfill}%
  \else
      \setbox0\vtop to \@tempdima{\hsize#3\@parboxrestore
                \vfill \multirowsetup \strut#5\strut\par\vfill}%
  \fi
  \ht0\z@\dp0\z@
  \ifnum\@tempcnta<0\advance\@tempdima-\dp\@arstrutbox
  \else\@tempdima\ht\@arstrutbox
     %\ifnum#2>0 \advance\@tempdima\bigstrutjot \fi
     \ifdim#2pt>0pt \advance\@tempdima\bigstrutjot \fi
  \fi
  \advance\@tempdima#4\relax\leavevmode\vtop{\vskip-\@tempdima\box0\vss}}
\@ifundefined{bigstrutjot}{\newdimen\bigstrutjot \bigstrutjot\jot}{}
\makeatother
\begin{document}
\begin{tabular}{|lll|}
  \hline
   A & \multirow{2}[1.2]{*}{\color{red}%
        \begin{tabular}{|l|l|}%|
          A & A\bigstrut[t] \\
          \hline
          A & A\\
        \end{tabular}} &  A\bigstrut[t]\hlinestrut  \\
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}
\end{document}

回到原始示例(包含三个\hlines),最后一个复杂因素:\hline两个表格的顶部应该重叠。首先,我们将其增加到bigstruts1.6一个\bigstrut和三个\hline)。其次:内部\hline是外部单元格的一部分!因此,如果我们什么都不做,内部表格将被推0.4pt下。(这将太靠近第三行的单元格。)解决方案是使用 的\multirow可选fixup参数,它会移动单元格。(省略此可选参数[\arrayrulewidth]意味着内部表格是不是移动以使它们的顶线重叠。)

bigstrut 和三条 hlines

\documentclass{article}
\usepackage{bigstrut}
\usepackage{multirow}
\usepackage{xcolor}
\def\hlinestrut{\rule[\dimexpr-\dp\strutbox-\arrayrulewidth]{\dimexpr\dp\strutbox+\arrayrulewidth}{0pt}}
\makeatletter
\def\@xmultirow#1[#2]#3[#4]#5{\@tempcnta=#1%
  \@tempdima\@tempcnta\ht\@arstrutbox
  \advance\@tempdima\@tempcnta\dp\@arstrutbox
  \ifnum\@tempcnta<0\@tempdima=-\@tempdima\fi
  \advance\@tempdima#2\bigstrutjot
  \if*#3\setbox0\vtop to \@tempdima{\vfill\multirowsetup
    \hbox{\strut#5\strut}\vfill}%
  \else
      \setbox0\vtop to \@tempdima{\hsize#3\@parboxrestore
                \vfill \multirowsetup \strut#5\strut\par\vfill}%
  \fi
  \ht0\z@\dp0\z@
  \ifnum\@tempcnta<0\advance\@tempdima-\dp\@arstrutbox
  \else\@tempdima\ht\@arstrutbox
     %\ifnum#2>0 \advance\@tempdima\bigstrutjot \fi
     \ifdim#2pt>0pt \advance\@tempdima\bigstrutjot \fi
  \fi
  \advance\@tempdima#4\relax\leavevmode\vtop{\vskip-\@tempdima\box0\vss}}
\@ifundefined{bigstrutjot}{\newdimen\bigstrutjot \bigstrutjot\jot}{}
\makeatother
\begin{document}
\begin{tabular}{|lll|}
  \hline
   A & \multirow{2}[1.6]{*}[\arrayrulewidth]{\color{red}%
        \begin{tabular}{|l|l|}%|
          \hline
          A & A\bigstrut[t] \\
          \hline
          A & A\\
          \hline
        \end{tabular}} &  A\bigstrut[t]\hlinestrut  \\
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}
\end{document}

当你使用(并行)\bigstruts 时,会出现另一个复杂情况,但不是在第一行。问题是,只要参数为正数,\multirow就会自动移动表格。但是,这只有在第一行出现时才有意义(我相信这是由于多行使用top 构建单元格内容)。因此,在上述情况下,必须使用“取消移动”表格,如下所示:\bigstrutjotbigstruts\bigstrut\vtopfixup

\begin{tabular}{|lll|}
  \hline
   A & \multirow{2}[1.6]{*}[\dimexpr\arrayrulewidth-\bigstrutjot]{\color{red}%
        \begin{tabular}{|l|l|}%|
          \hline
          A & A \\
          \hline
          A & A\bigstrut[t]\\
          \hline
        \end{tabular}} &  A\hlinestrut  \\
   A & {} & A\bigstrut[t] \\
   A & A  & A \\
  \hline
\end{tabular}

答案2

请注意,使用以下文本会重现相同的错误:

\documentclass{article}
\usepackage{xcolor}
\usepackage{multirow}
\setlength{\parindent}{0pt}
\newcommand{\vstrut}[3][blue]{{\color{#1}\rule[-#2]{0.4pt}{#3}}}
\newcommand{\hstrut}[2][blue]{{\color{#1}\makebox[0pt][l]{\rule[-0.4pt]{#2}{0.4pt}}}}
\begin{document}

\begin{tabular}{|lll|}
  \hline
   A\vstrut{0ex}{5ex} & \multirow{2}{3cm}{%
      \begin{minipage}[t]{3cm}
            Trial \vstrut[red]{18pt}{18pt}  text
      \end{minipage}} 
                                          & A \\
   A\vstrut{3ex}{3ex}\hstrut{1.65in} & {} & A \\
   A                                 & A  & A \\
  \hline
\end{tabular}

\end{document}

\multirow创建一个\vtop框,其高度和深度根据的规则设置,\vtop以及的高度和深度\@arstrutbox。现在,\@arstrutbox是创建表格环境时设置的框。它被设置为一个框,其高度和深度是\arraystretch正常支柱的高度和深度的倍数。

通过上面示例中的可见支柱,您可以看到如何\multirow为其内容创建框的效果。例如,即使您可以放置​​一个支柱来扩展第二行的大小,但这并不能防止支柱里面\multirow命令强制将创建的框的内容\multirow设置为大的。

因此,一种解决方案是重置 的值\arraystretch。但这似乎有点过头了:你可能不想\arraystretch改变所有的表仅修复一个盒子。

记住如何\multirow创建它的框意味着几件事。考虑下一个例子,我告诉\multirow你我只需要一行。

\begin{tabular}{|lll|}
  \hline
   A\vstrut{0ex}{5ex} & \multirow{1}{3cm}{%
      \begin{minipage}[t][0pt]{3cm}
            Trial \vstrut[red]{18pt}{18pt}  text
      \end{minipage}} 
                                          & A \\
   A\vstrut{3ex}{3ex}\hstrut{1.65in} & {} & A \\
   A                                 & A  & A \\
  \hline
\end{tabular}

通过创建零高度的\multirow顶部对齐,您可以完全放弃使用。minipage

\begin{tabular}{|lll|}
  \hline
   A\vstrut{0ex}{5ex} &% 
      {\begin{minipage}[t][0pt]{3cm}
            Trial \vstrut[red]{18pt}{18pt}  text
      \end{minipage}} 
                                          & A \\
   A\vstrut{3ex}{3ex}\hstrut{1.65in} & {} & A \\
   A                                 & A  & A \\
  \hline
\end{tabular}

避免\multirow,你仍然可以实现更像你的原始示例的东西,你可以写:

\begin{tabular}{|lll|}
  \hline
   A &% 
      {\begin{minipage}[t][0pt]{3cm}
          \begin{tabular}{|l|l|}
            \hline
            A & \hfill 1\textsuperscript{st} \\
            \hline
            A & A \\
            \hline
          \end{tabular}
      \end{minipage}} 
          & A \\
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}

似乎使用的好处\multirow是能够将其内容相对于它应该跨越的其他行居中(请参阅此答案末尾的编辑)。所以,这里有一个更接近你想要的例子。(我添加了一个\hrule以更好地显示错误水平线的对齐。

\begin{tabular}{|lll|}
  \hline
   A &% 
      \multirow{2}{*}%
      {\begin{minipage}[c][0pt]{3cm}%
          \begin{tabular}[c]{|l|l|}
            \hline
            A & \hfill 1\textsuperscript{st} \\
            \hline
            A & A \\
            \hline
          \end{tabular}%
      \end{minipage}} 
          & A \\\hline
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}

请记住,tabular环境与 s 非常相似minipage,可以相对于它们所在的线居中。

为了使水平线正确对齐,请在里面添加一个垂直支柱,minipage如下所示(在此示例中,我使用它\raisebox来创建一个总高度+深度为零的框):

\begin{tabular}{|lll|}
  \hline
   A &% 
      \multirow{2}{*}%
      {\raisebox{0pt}[0pt][0pt]{\begin{minipage}{3cm}\vspace{0.5pt}%
          \begin{tabular}[c]{|l|l|}
            %\hline % commented-out from original code b/c it slightly struts out at the top
            A & \hfill 1\textsuperscript{st} \\
            \hline
            A & A \\
            \hline
          \end{tabular}%
      \end{minipage}}} 
          & A \\\hline
   A & {} & A \\
   A & A  & A \\
  \hline
\end{tabular}

在此处输入图片描述

另外一点,您的文档中行尾处有一些空白。这导致宽度与您定义的宽度不完全一致。我已经消除了一些更令人震惊的情况。

编辑

正如 @SašoŽivanović 指出的那样\multirow中心内容。但我谈论的是中心化\multirow本质上将总高度和深度为零的框的内容居中。这是因为\vtop的定义中使用的的内容\multirow被括在\vfills 之间,从而导致内容相对于要跨越的行生成的预期高度居中。

空格

在您最初的帖子中您调用

A & \multirow{2}{*}{
  \begin{minipage}{3cm}
    \begin{tabular}{|l|l|}
      \hline
      A & \hfill 1\textsuperscript{st}\bigstrut[t] \\
      \hline
      A & A \\
      \hline
    \end{tabular}
  \end{minipage}
    }

这会在行首添加额外的空格\multirow...,当您编写时,也会在行尾添加额外的空格\end{minipage}。请查看我的示例,我通过%比您更早地放置或关闭参数来避免这种情况。

有关这方面的更多详细信息,我建议阅读@egreg的回答在 \newcommand 或类似命令中,在行尾添加百分号什么时候有害

相关内容