表格单元格的光学垂直对齐

表格单元格的光学垂直对齐

如果有人能帮助我格式化 1 至 3 列中的条目,使它们出现在行的中心,我将非常高兴,因为“曲目”列已在顶部规则中居中

\documentclass{article}
\usepackage{booktabs,multirow}
\usepackage{textcomp}

\begin{document}
\begin{table}[h]\centering
    \begin{tabular}{lcccc}
        \toprule
        \multirow{2}[3]{*}{Track} & \multicolumn{2}{c}{Virtual Station} & \multicolumn{2}{c}{Search window} \\
        \cmidrule(lr){2-3} \cmidrule(lr){4-5}
        & Lat [\textdegree]& Long [\textdegree] & Lat [\textdegree] & Long [\textdegree]\\
        \midrule
        551 &   42.967165  &  -87.062729  & 43.99  & -87.46  \\
            &              &              & 42.03  & -86.74 \\
         \hline
        7   &   44.370063  &  -86.847797  & 44.87 & -87.01  \\
            &              &              & 43.77 & -86.62 \\
         \hline
        882 &   43.850509  &  -86.949138  & 42.31 & -87.46  \\
            &              &              & 43.85 & -86.94 \\
        \hline
        465 &   45.065718  &  -86.387580  & 45.48 & -86.53  \\
            &              &              & 44.76 & -86.27 \\
        \hline
        338 &   42.471183  &  -86.719330  & 43.08 & -86.49  \\
            &              &              & 41.84 & -86.92 \\
        \hline
        923 &   45.556212  &  -85.851539  & 45.86 & -85.95  \\
            &              &              & 45.20 & -85.73 \\
        \hline
        379 &   45.782886  &  -85.220795  & 45.96 & -85.29  \\
            &              &              & 45.64 & -85.16 \\

        \bottomrule
    \end{tabular}
\end{table}
\end{document}

例子

答案1

在这里,我习惯\stackanchors围绕基线构建搜索窗口数据。我还以数学模式表达了所有纬度和经度,以捕捉正确的-符号。

在 中\sa[2pt]是在 上方和下方添加的垂直缓冲区\stackanchor,而[5pt]是搜索窗口堆叠条目之间的垂直间隙。

\documentclass{article}
\usepackage{booktabs,multirow}
\usepackage{textcomp}
\usepackage{stackengine}
\strutshortanchors{T}
\newcommand\sa[2]{\addstackgap[2pt]{\ensurestackMath{\stackanchor[5pt]{#1}{#2}}}}
\begin{document}
\begin{table}[h]\centering
    \begin{tabular}{lcccc}
        \toprule
        \multirow{2}[3]{*}{Track} & \multicolumn{2}{c}{Virtual Station} & \multicolumn{2}{c}{Search window} \\
        \cmidrule(lr){2-3} \cmidrule(lr){4-5}
        & Lat [\textdegree]& Long [\textdegree] & Lat [\textdegree] & Long [\textdegree]\\
        \midrule
        551 &$   42.967165  $&$  -87.062729  $& \sa{43.99}{42.03}  & \sa{-87.46}{-86.74}\\
         \hline
        7   &$   44.370063  $&$  -86.847797  $& \sa{44.87}{43.77} & \sa{-87.01}{-86.62} \\
         \hline
        882 &$   43.850509  $&$  -86.949138  $& \sa{42.31}{43.85} & \sa{-87.46}{-86.94} \\
        \hline
        465 &$   45.065718  $&$  -86.387580  $& \sa{45.48}{44.76} & \sa{-86.53}{-86.27} \\
        \hline
        338 &$   42.471183  $&$  -86.719330  $& \sa{43.08}{41.84} & \sa{-86.49}{-86.92} \\
        \hline
        923 &$   45.556212  $&$  -85.851539  $& \sa{45.86}{45.20} & \sa{-85.95}{-85.73} \\
        \hline
        379 &$   45.782886  $&$  -85.220795  $& \sa{45.96}{45.64} & \sa{-85.29}{-85.16} \\
        \bottomrule
    \end{tabular}
\end{table}
\end{document}

在此处输入图片描述

答案2

原则上你需要类似的东西

\newcommand*\Osborncell[1]{%
  \if\relax\detokenize{#1}\relax\else\multirow{2}{*}{#1}\fi
}

用于格式化。它只是检查是否有空单元格条目:如果不是空的,它会将当前单元格重新格式化为多行,因此它在视觉上与两个垂直相邻单元格的中心对齐。棘手的部分是只将其应用于表格的相关部分。虽然这可以手动完成,例如

\begin{table}[h]\centering
  \begin{tabular}{lcccc}
    \toprule
    \multirow{2}[3]{*}{Track}&
    \multicolumn{2}{c}{Virtual Station}&
    \multicolumn{2}{c}{Search window}\\
    \cmidrule(lr){2-3} \cmidrule(lr){4-5}
    & Lat [\textdegree]& Long [\textdegree] & Lat [\textdegree] & Long [\textdegree]\\
    \midrule
    \Osborncell{551} & \Osborncell{42.967165} & \Osborncell{-87.062729}  & 43.99  & -87.46 \\
     & & & 42.03  & -86.74 \\
     ...

对于这种表格来说,如果能实现一点自动化就更好了。为此,数据输入是在格式化之前完成的,界面进行了以下更改:表格内容通过宏收集,如下\tabledata

 \tabledata{%
    551, 42.967165, -87.062729, 43.99, -87.46;
       ,          ,           , 42.03, -86.74;
  %  \hline
    7  , 44.370063, -86.847797, 44.87, -87.01;
       ,          ,           , 43.77, -86.62;
  %  \hline
    882, 43.850509, -86.949138, 42.31, -87.46;
       ,          ,           , 43.85, -86.94;
  %  \hline
    465, 45.065718, -86.387580, 45.48, -86.53;
       ,          ,           , 44.76, -86.27;
  %  \hline
    338, 42.471183, -86.719330, 43.08, -86.49;
       ,          ,           , 41.84, -86.92;
  %  \hline
    923, 45.556212, -85.851539, 45.86, -85.95;
       ,          ,           , 45.20, -85.73;
  %  \hline
    379, 45.782886, -85.220795, 45.96, -85.29;
       ,          ,           , 45.64, -85.16;
  }

然后,实际的表格是通过

\begin{tabular}{lcccc}
  \toprule
  \multirow{2}[3]{*}{Track}&
  \multicolumn{2}{c}{Virtual Station}&
  \multicolumn{2}{c}{Search window}\\
  \cmidrule(lr){2-3} \cmidrule(lr){4-5}
  & Lat [\textdegree] & Long [\textdegree] & Lat [\textdegree] & Long [\textdegree]\\
  \midrule
  \printtabledata
  \bottomrule
\end{tabular}

\printtabledata打印之前指定的表格数据。)

展示

这是通过循环数据数组并将信息适当地存储在令牌寄存器 ( \@toks@table) 中来实现的。

\newtoks\@toks@table
\newcounter{currentrow}
\newcounter{currentcolumn}
\def\tabledata#1{\@toks@table{}\@tabledata#1\@end}
\def\@tabledata#1;#2{%
  \stepcounter{currentrow}%
  \mod{\c@currentrow}{2}%
  \ifnum\value{currentrow}=1\else\ifnum\@mod=1
    \@toks@table\expandafter{\the\@toks@table\hline}\fi\fi
  \parserow{#1}%
  \ifx#2\@end\else\expandafter\@tabledata\expandafter#2\fi
}
\def\parserow#1{%
  \setcounter{currentcolumn}{0}%
  \@parserow#1,\@@end
  \@toks@table\expandafter{\the\@toks@table\\}
}
\def\@parserow#1,#2{%
  \stepcounter{currentcolumn}%
  \ifnum\value{currentcolumn}=1\@toks@table\expandafter{\the\@toks@table \Osborncell{#1}}\fi
  \ifnum\value{currentcolumn}=2\@toks@table\expandafter{\the\@toks@table&\Osborncell{#1}}\fi
  \ifnum\value{currentcolumn}=3\@toks@table\expandafter{\the\@toks@table&\Osborncell{#1}}\fi
  \ifnum\value{currentcolumn}>3\@toks@table\expandafter{\the\@toks@table&#1}\fi
  \ifx#2\@@end\else\expandafter\@parserow\expandafter#2\fi
}

计数器“currentrow”和“currentcolumn”只是在循环期间跟踪数据中的当前位置。每列的格式在 的定义中定义\@parserow。这里,\Osborncell(见上文)应用于前三列的单元格。

完整代码

\documentclass{article}
\usepackage{booktabs,multirow}
\usepackage{textcomp}

\makeatletter
\newcount\@mod
\newcommand*{\mod}[2]{%
  \@mod=#1
  \@tempcnta=#2
  \ifnum\@mod<\@tempcnta\else
    \loop
    \advance\@mod by -#2
    \unless\ifnum\@mod<#2
    \repeat
  \fi
}
\newtoks\@toks@table
\newcounter{currentrow}
\newcounter{currentcolumn}
\def\tabledata#1{\@toks@table{}\@tabledata#1\@end}
\def\@tabledata#1;#2{%
  \stepcounter{currentrow}%
  \mod{\c@currentrow}{2}%
  \ifnum\value{currentrow}=1\else\ifnum\@mod=1
    \@toks@table\expandafter{\the\@toks@table\hline}\fi\fi
  \parserow{#1}%
  \ifx#2\@end\else\expandafter\@tabledata\expandafter#2\fi
}
\def\parserow#1{%
  \setcounter{currentcolumn}{0}%
  \@parserow#1,\@@end
  \@toks@table\expandafter{\the\@toks@table\\}
}
\def\@parserow#1,#2{%
  \stepcounter{currentcolumn}%
  \ifnum\value{currentcolumn}=1\@toks@table\expandafter{\the\@toks@table \Osborncell{#1}}\fi
  \ifnum\value{currentcolumn}=2\@toks@table\expandafter{\the\@toks@table&\Osborncell{#1}}\fi
  \ifnum\value{currentcolumn}=3\@toks@table\expandafter{\the\@toks@table&\Osborncell{#1}}\fi
  \ifnum\value{currentcolumn}>3\@toks@table\expandafter{\the\@toks@table&#1}\fi
  \ifx#2\@@end\else\expandafter\@parserow\expandafter#2\fi
}
\def\printtabledata{\the\@toks@table}
\newcommand*\Osborncell[1]{%
  \if\relax\detokenize{#1}\relax\else\multirow{2}{*}{#1}\fi
}
\makeatother

\begin{document}
\begin{table}[h]\centering
  \tabledata{%
    551, 42.967165, -87.062729, 43.99, -87.46;
       ,          ,           , 42.03, -86.74;
    7  , 44.370063, -86.847797, 44.87, -87.01;
       ,          ,           , 43.77, -86.62;
    882, 43.850509, -86.949138, 42.31, -87.46;
       ,          ,           , 43.85, -86.94;
    465, 45.065718, -86.387580, 45.48, -86.53;
       ,          ,           , 44.76, -86.27;
    338, 42.471183, -86.719330, 43.08, -86.49;
       ,          ,           , 41.84, -86.92;
    923, 45.556212, -85.851539, 45.86, -85.95;
       ,          ,           , 45.20, -85.73;
    379, 45.782886, -85.220795, 45.96, -85.29;
       ,          ,           , 45.64, -85.16;
  }
  \begin{tabular}{lcccc}
    \toprule
    \multirow{2}[3]{*}{Track}&
    \multicolumn{2}{c}{Virtual Station}&
    \multicolumn{2}{c}{Search window}\\
    \cmidrule(lr){2-3} \cmidrule(lr){4-5}
    & Lat [\textdegree] & Long [\textdegree] & Lat [\textdegree] & Long [\textdegree]\\
    \midrule
    \printtabledata
    \bottomrule
  \end{tabular}
\end{table}
\end{document}

评论

顺便提一下,对于 @egreg 的评论,您可能想尝试使用它siunitx来格式化表格中的数字。除了加载包之外,您还需要进行两个小调整:

  1. \Osborncell

    \newcommand*\Osborncell[1]{%
      \if\relax\detokenize{#1}\relax\else\multirow{2}{*}{\num{#1}}\fi
    }
    
  2. \@parserow

    \def\@parserow#1,#2{%
      ...
      \ifnum\value{currentcolumn}>3
        \@toks@table\expandafter{\the\@toks@table&\num{#1}}\fi
      \ifx#2\@@end\else\expandafter\@parserow\expandafter#2\fi
    }
    

备注_示例

相关内容