我需要生成大量报告,并且已经用 R 编写了一个用于写入 LaTeX 文件的程序。大多数报告都运行正常,但有一个问题会影响迷你页面中多列结构中 3 个项目的放置。我精简了报告代码以显示这一点。
这是示例输出。在左上角,请注意多列在右侧放置了两个项目。我不希望发生这种情况,我希望左侧有 2 个项目。在几乎所有其他有 3 个项目的示例中,结果都是左侧有 2 个,右侧有 1 个。我修改了项目 2 中的字符串,以便在底部和右侧的框中产生所需的结果。
如何产生好的结果并不完全可预测。如果第二项的文本字符串稍长一点,或者短一点,那么列的位置就会符合我的要求。
由于我要生成数千份报告,因此筛选这些报告并找到这些意外的 3 项框并修复它们并不实际。因此,我希望你能帮助我了解导致这种情况的原因。
也许我的文档设计太复杂了。这是一个有 2 列的部分,每列都有小页面,每个小页面有 2 列。这些带有注释的程式化栏是报告中的必需元素。有时句子较长,有时较短。有时会有 15 或 20 个项目,句子长度各不相同。这里的设计似乎可以可靠地处理更大、更复杂的案例,但这个有 3 个项目的案例,嗯,令人沮丧。
这是 MRE。我剪掉了页眉、页脚和许多其他框。然后我复制了故障框以显示不同的情况。我留下了序言,因为如果我放错了导致这个问题的东西,我需要你发现它,告诉我该怎么修复。
\documentclass[letterpaper,landscape,english,11pt]{article}
\usepackage[scaled=.92]{helvet}
\renewcommand{\familydefault}{\sfdefault}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{array}
\usepackage{longtable}
\usepackage{multicol}
\usepackage{setspace}
\setlength{\parskip}{0bp}
\setlength{\parindent}{0bp}
\makeatletter
\setlength{\columnsep}{1.5cm}
\DeclareUnicodeCharacter{00A0}{}
\providecommand{\tabularnewline}{\\}
\makeatother
\usepackage{calc}
\usepackage{setspace}
%% compiler says not needed now: \usepackage{fixltx2e}
\usepackage{graphicx}
\usepackage{grffile}
\usepackage{multicol}
\usepackage{multirow}
\usepackage[normalem]{ulem}
\usepackage[english]{babel}
\usepackage{color}
\usepackage{colortbl}
\usepackage[landscape,letterpaper,includehead,includefoot]{geometry}
\geometry{verbose,tmargin=1.5cm,bmargin=0.75cm,lmargin=2cm,rmargin=2cm}
\usepackage{fancyhdr}
\headheight=5pt
\footskip=20pt
\marginparwidth=0pt
\marginparsep=0pt
\setlength{\parskip}{\smallskipamount}
\setlength{\parindent}{0pt}
\usepackage{adjustbox}
\pagestyle{fancy}
\usepackage{lastpage}
\usepackage[percent]{overpic}
\usepackage{moresize}
\usepackage{url}
\def\changemargin#1#2{\list{}{\rightmargin#2\leftmargin#1}\item[]}
\let\endchangemargin=\endlist
\begin{document}
\fancyhead{}
\fancyfoot{}
\fancypagestyle{empty}{
\fancyhf{}
\fancyfoot[R]{Page \thepage \hspace{1pt} of \pageref{LastPage}}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}
}
\thispagestyle{empty}
%% Space between big boxes specified next
\setlength\columnsep{20pt}
\begin{multicols}{2}
\fbox{\begin{minipage}{\columnwidth}
\raggedcolumns
%% Space between columns within box
\setlength\columnsep{10pt}
\begin{multicols}{2}
\begin{spacing}{0.7}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Construct understandings of text} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 13 of 45 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Integrate ideas and information from text} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 6 of 15 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Use writing to communicate} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 15 of 25 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\end{spacing}
\end{multicols}
\vspace{5pt}
\end{minipage}}
\vspace{10pt}
\fbox{\begin{minipage}{1\columnwidth}
\raggedcolumns
\setlength\columnsep{10pt}
\begin{multicols}{2}
\raggedcolumns
\begin{spacing}{0.7}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Construct understandings of text} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 13 of 45 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Integrate ideas and whatnot} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 6 of 15 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Use writing to communicate} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 15 of 25 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\end{spacing}
\end{multicols}
\vspace{5pt}
\end{minipage}}
\columnbreak
\vspace{10pt}
\fbox{\begin{minipage}{1\columnwidth}
\raggedcolumns
\setlength\columnsep{10pt}
\begin{multicols}{2}
\begin{spacing}{0.7}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Construct understandings of text} \\
\rule{0pt}{.45cm}\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 13 of 45 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Integrate ideas and information \\ from text}\\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 6 of 15 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\begin{minipage}{\columnwidth}
\vspace{1pt}
{\footnotesize{}Use writing to communicate} \\
\begin{overpic}[height=0.45cm]{pp-11}\put(5,-0.5){\textit{\ssmall{}Mastered 15 of 25 skills}}\end{overpic}
\rule[0.5ex]{.75\columnwidth}{1pt}
\end{minipage}
\end{spacing}
\end{multicols}
\vspace{5pt}
\end{minipage}}
\end{multicols}
\end{document}
我无法让论坛允许附加上图中使用的小型 pdf。我在我的网页上放了一份副本,但我知道你不想去钓鱼:http://pj.freefaculty.org/scraps/pp-11.pdf
提前感谢您的见解
答案1
以下是算法行为的解释。基本上,您要求多列平衡的不是单行文本,而是由多行组成的大块(小页面),这当然很难做到。在您的示例中,您只有 3 个块,因此将它们放在两列上基本上意味着一列获得其中 2 个,另一列获得另一个。
现在为了平衡,multicol 会猜测(故意太小)列的高度,然后尝试放置所有东西。因此第一次尝试时,第一个块会位于第 1 列,而其他 2 个块会位于第 2 列(并溢出该列)-> 失败。
然后 multicol 增加列高(增加 1pt)并重试。结果相同,因此列高缓慢增加。但唯一发生的事情是第一列确实不够满(因为里面仍然只有一个块)。
然而,在某个时刻,高度变得如此之大以至于第二列中的两个块最终适合第二列,这就是 multicol 作为平衡解决方案。
通过在加载包时使用该选项,您可以很好地观察到该行为balancingshow
。然后您将获得以下跟踪:
Package multicol: Balance columns on input line 98:
Column 1 badness: 10000
First column = 38.20001pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Retry: using natural height of first column!
Column 1 badness: 0
First column = 26.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 12
First column = 27.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 100
First column = 28.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 336
First column = 29.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 800
First column = 30.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 1558
First column = 31.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 2698
First column = 32.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 4279
First column = 33.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 6396
First column = 34.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 10000
First column = 35.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 10000
First column = 36.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
并且多次像这样尝试...最后...
Column 1 badness: 10000
First column = 58.57309pt (26.57309pt) <> last column = 59.4557pt
Rejected: last column too large!
Column 1 badness: 10000
First column = 59.57309pt (26.57309pt) <> last column = 59.4557pt
Final badness: 0
Package multicol: Column spec: 330.57948pt = indent + columns + sep =
(multicol) 0.0pt + 2 x 160.28973pt + 1 x 10.0pt on input line 98.
Package multicol: Ending environment (boxed mode) on input line 98.
这恰恰显示了上面解释的行为。
在第二个示例中,块的高度略有不同,因此在这种情况下 multicol 达到一个点,即前两个块适合第一列,而后两个块适合第二列。因此在这种情况下,可以得到所需的结果。
取得更好的结果
multicol 实际上有很多可以调整和改善结果的选项,但不幸的是,它们需要根据输入的类型进行调整。这里要调整的是columnbadness
控制允许获得多少不良列的计数器。默认值为 10000,这意味着在紧急情况下严重不足的列是可以的(只有过满的列是不允许的)。
有了这样的设置,更好的选择是
\setcounter{columnbadness}{9999}
这样,所有不良程度为 10000 的尝试都会被丢弃,这意味着 multicol 将继续增加高度,直到第一列不再不满。
(顺便说一句:不平衡计数器在这里只起到帮助作用,因为这样起点就会增加到足够的程度,以便两个块已经适合第一列(但这仅适用于该特定示例。在其他情况下,可能需要不同的不平衡设置,因此这只适用于手动调整))
答案2
我无法解释的行为multicolumns
,但您可以尝试将unbalance
参数设置为高于零的值。
\setcounter{unbalance}{2}
除此之外,您的代码还可以从多个方面进行改进。它会生成多个未满和过满的水平盒子,多个包会被加载两次,即使生成了代码,您也不应该重复该代码。要调整框架的空白,您可以将其设置\fboxsep
为更大的值。最后,您可以使用或轻松地生成图片而不是加载它们tikz
(pstricks
我还没有这样做,因为不知道加载图片背后的原理)。
\documentclass[letterpaper,landscape,english,11pt]{article}
\usepackage[scaled=.92]{helvet}
\renewcommand{\familydefault}{\sfdefault}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{multicol}
\usepackage{setspace}
\usepackage[landscape,letterpaper,includehead,includefoot]{geometry}
\geometry{verbose,tmargin=1.5cm,bmargin=0.75cm,lmargin=2cm,rmargin=2cm}
\headheight=5pt
\footskip=20pt
\marginparwidth=0pt
\marginparsep=0pt
\setlength{\parskip}{\smallskipamount}
\setlength{\parindent}{0pt}
\usepackage{moresize}
\usepackage{environ}
\usepackage{graphicx}
\NewEnviron{person}%
{\par
\vspace{10pt}%
\fbox
{\begin{minipage}{\dimexpr\columnwidth-2\fboxsep-2\fboxrule}%
\setlength\columnsep{10pt}%
\setcounter{unbalance}{2}%
\begin{multicols}{2}%
\raggedcolumns
\begin{spacing}{0.7}%
\BODY
\end{spacing}%
\end{multicols}
\end{minipage}%
}%
}
\newcommand\ability[4]%
{\begin{minipage}{\columnwidth}%
{\footnotesize#1\par}%
\makebox[4pt][l]{\includegraphics[height=0.45cm]{#2}}%
{\ssmall\itshape Mastered #3 of #4 skills}%
\par
\rule[1ex]{0.75\columnwidth}{1pt}%
\end{minipage}%
}
\begin{document}
\setlength\columnsep{20pt}
\begin{multicols}{2}
\begin{person}
\ability{Construct understandings of text}{pp-11}{13}{45}
\ability{Integrate ideas and information from text}{pp-11}{6}{15}
\ability{Use writing to communicate}{pp-11}{15}{25}
\end{person}
\begin{person}
\ability{Construct understandings of text}{pp-11}{13}{45}
\ability{Integrate ideas and whatnot}{pp-11}{6}{15}
\ability{Use writing to communicate}{pp-11}{15}{25}
\end{person}
\columnbreak
\begin{person}
\ability{Construct understandings of text}{pp-11}{13}{45}
\ability{Integrate ideas and information \\ from text}{pp-11}{6}{15}
\ability{Use writing to communicate}{pp-11}{15}{25}
\end{person}
\end{multicols}
\end{document}