如果部分内容较短,则在多列环境中自动分列

如果部分内容较短,则在多列环境中自动分列

在我的文章模板中,部分文本设置为双栏模式。我正在使用multicol带有星号环境的包(一列接一列地填充)。

双栏文章部分由不同的部分组成,其中有些部分可能很短。例如,\listoffigues应打印出作者姓名和地址。

由于大部分内容都是在序言或文章结构中预先定义的,无论是通过使用的图表数量还是作者人数在一篇文章中,我想使排版过程自动化。

因此,我需要以下行为:

  • 如果第一部分的内容(比如说图表列表)只有几行,最多到页面的中间,则下一节应该直接放在同一列之后。(下图第一页)
  • 但如果第一部分的内容延伸到页面的中间,则下一节应该从下一列开始。(下图第二页)

在此处输入图片描述

当然,如果我排版任何文章单独,我可以在\newcolumn每个短节后手动插入一个来得到这个结果。

但我希望自动执行此步骤。是否有可能创建一个 if 条件,例如,如下所示:

if "previous section" starts at topline and is shorter than \textheight; then
    insert \newcolumn

我希望有一个expl3解决方案,并且已经浏览过了接口3手册,但到目前为止,找不到合适的解决方案。这可能是因为我缺乏使用 Latex if 条件和的经验expl3。但我非常愿意学习。

这是我的 MWE:

\documentclass[%
twoside,a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{noto}

\usepackage{geometry}
\geometry{%
    inner=20mm,
    outer=60mm,
    top=15mm,
    bottom=20mm,
    marginparwidth=40.5mm,
    marginparsep=4.5mm,
    showframe % to show the margins
}

\usepackage{multicol}

% Put a line in the middle of text height for testing
\usepackage{atbegshi,picture}
\AtBeginShipout{%
    \AtBeginShipoutUpperLeft{%
        \put(0,\dimexpr-\topmargin-1in %
        -\headheight-\headsep
        -.5\textheight\relax){%
            \line(1,0){\paperwidth}%
        }%
    }%
}

\usepackage{blindtext}

\begin{document}
    \section{Section}
    \blindtext[5]
    \newpage
    \begin{multicols*}{2}
        \section{Section}       
        \blindtext[2]
        \section{Section}
        \blindtext[3]
        
        \newpage
        \section{Section}       
        \blindtext[1]
        \section{Section}
        \blindtext[2]
        
        \newpage
        \section{Section}       
        \blindtext[2]
        \newcolumn
        \section{Section}
        \blindtext[2]
    \end{multicols*}
\end{document}

谢谢

答案1

由于我休息了一天,所以在阅读了更多资料之后,我找到了一个解决方案。这个解决方案运行得很好。

它使用 来parbox测量所需文本区域的高度,并将其与文本高度的一半进行比较。如果测量的文本长度超过文本高度的一半,则会\newcolumn插入 以将以下文本推到下一列:

\documentclass[%
twoside,a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{noto}

\usepackage{geometry}
\geometry{%
    inner=20mm,
    outer=37.5mm,
    top=15mm,
    bottom=20mm,
    marginparwidth=18mm,
    marginparsep=4.5mm,
    showframe % to show the margins
}

\usepackage{multicol}

% Put a line in the middle of text height for testing
\usepackage{atbegshi,picture}
\AtBeginShipout{%
    \AtBeginShipoutUpperLeft{%
        \put(0,\dimexpr-\topmargin-1in %
        -\headheight-\headsep
        -.5\textheight\relax){%
            \line(1,0){\paperwidth}%
        }%
    }%
}

\usepackage{blindtext}

\newlength{\metaheight}

\newcommand{\testheight}[1]{%
    \settoheight{\metaheight}{%
    \parbox[b]{\linewidth}{\selectfont\noindent#1}}%
    #1\par \the\metaheight%
}
\ExplSyntaxOn
\NewDocumentCommand{\columntest}{}{%
    \int_compare:nNnTF {\int_to_arabic:n {\metaheight}} < {\int_to_arabic:n {\textheight/2}} {} {\newcolumn}
}
\NewDocumentCommand{\sectiontest}{m}{%
    \testheight{#1}\par
    \columntest
}
\ExplSyntaxOff

\setlength\parindent{0pt}
\begin{document}
\blindtext
\newpage
    \begin{multicols*}{2}
        
        \section{Section}       
        \sectiontest{\blindtext[1]}

        \section{Section}
        \blindtext[3]
        
        \newpage
        
        \section{Section}       
        \sectiontest{\blindtext[2]}
        
        \section{Section}
        \blindtext[2]
    
    \end{multicols*}
\end{document}

我用不同类型的文本对其进行了测试,到目前为止,效果非常好。

当然,如果一些老手有任何改进的想法,我会很高兴听到。

相关内容