How do I force multicols environment to use first column when called from within a minipage

I understand how to get multicol package to use the entirety of the first column before moving to the next:

\begin{multicols*}{3}
....
\end{multicols*}

which is mentioned in section 2.2 of the manual. But it also mentions in that section that the starred environment "only works on top-level." The manual explains that "inside a box one has to balance to determine a column height in absence of a fixed value."

What I would like to know is whether there's a way to get around this when the height of the containing box is known.

In other words, if I would like to write something like

\begin{minipage}[t][4in]{10in}
\begin{multicols*}{3}
....
\end{multicols*}
\end{minipage}

and get the multicol package to think that it's on a page of the specified height.

Does anyone know any work arounds?

I know I could use \newgeometry for a given page. But, my headers and footers get moved around and I'm not happy with that. Moreover, I generally don't want to dedicate entire pages to this multicolumned format.

Here's an example of what the page design should look like. While it might be hard to tell from the image. This is an 8.5x11 page in landscape.

Here's the MWE which created this image. This is a very odd page design, but it meets the needs for the finished document.

\documentclass{article}
%--------------------
%--------------------
\usepackage{fancyhdr}
\renewcommand{\footrulewidth}{0.4pt}
\pagestyle{fancy}
%--------------------
\usepackage{multicol}
\setlength{\columnseprule}{0.4pt}
\setlength{\columnsep}{0.25in}
%--------------------
\usepackage{lipsum}
\begin{document}

\lipsum[1]
\vspace{2ex}

\noindent
\hspace*{\dimexpr\textwidth/2}%
\hspace*{-5in}%
\begin{minipage}{0pt}
\begin{minipage}[t][2.85in]{10in}
\begin{multicols*}{4}
\lipsum[1-2]
\vspace{2in}

\vspace{2.85in}~
\hspace*{\fill}.
\end{multicols*}
\end{minipage}
\end{minipage}

\vspace{2ex}
\lipsum[2]

\end{document}

The document is deliberately designed to have extremely large margins---so the headers and footers should similarly not span the entire page to preserve the appearance of massive margins.

Obviously I can achieve the effect I want, but I don't want to have to go through each of these multi-column insets and manually place sufficient struts to properly fill up the height of the box.

Incidentally, the final \hspace*{\fill}. in the multicols environment is only inserted there so that, when I cropped the image, the cropping didn't knock off too much of the empty space.

Two ideas:

I have two ideas about how to accomplish this. But I don't have any idea of how to implement either.

Preliminaries

Though for the final version I would like to be able to choose how many columns I need, for the sake of explaining my ideas, I'll assume that I'm working with 4 columns of text.

Let's say that the total width of the environment is W and that the \columnsep is set to s. Then one column of text within the environment should have a width of C=(W-3s)/4.

Let's say that height of the environment is H. Since I'm formatting four columns of text, where each column has height H, the total effective height of each column, if stacked on top of each other combined, is close to 4H.

First Idea

The first formats a multi-column environment under a single run with pdflatex.

The idea is as follows:

(1) First format the text as though it were just one column of width C

I could do that something like:

\begin{lrbox}{\aebox}
\begin{minipage}{<width=C>}
....TEXT....
\end{minipage}
\end{lrbox}

(2) Measure the height of this column of text, call that h

\setlength{<height=h>}{\dimexpr\dp\aebox+\ht\aebox\relax}

(3) If h>4H, then I've got problems. I'm not interested in considering this case.

(4) If h<4H, then I look at the difference 4H-h and create as many struts of height H that will fit in 4H-h and one remainder strut of height 4H-h modulo H

Suppose the columns are lettered, from left to right, as A, B, C, and D. Then I will have lengths

\aestrutDheight
\aestrutBheight
\aestrutCheight
\aestrutRheight <remainder height>

<PSEUDO-CODE>
let L=4H-h

while L > H
{
<set a length for each iteration>
\setlength{\aestrut[DBC]height}{<height=H>}
L=L-H
}
\setlength{\aestrutRheight}{L}

(5) Reprocess the text but with the the remainder strut and other struts appended.

The pseudo-code here is for the case where I have enough text to span 3 columns, but not 4.

\begin{minipage}[t][<height=H>]{<width=C>}
\begin{multicols*}{4}
....TEXT....

\rule{0pt}{\aestrutRheight}

\rule{0pt}{\aestrutDheight}
\end{multicols*}
\end{minipage}

Generally, I think I can do this except for the very last step. Once I've used the text, I've lost it and don't know how to reprocess it.

Second Idea

This idea is very similar to the first. But requires two passes of pdflatex.

(1) Try formatting the text as 4 columns of balanced text

\begin{lrbox}{\aebox}
\begin{minipage}{<width=W>}
\begin{multicols}{4}
....TEXT....
\end{multicols}
\end{minipage}
\end{lrbox}

(2) Measure the height of this box.

(3) Calculate the different of betweeen this height and the target height.

(4) Calculate the lengths of the necessary struts, but write this out to a log file.

(5) On the second rerun of pdflatex, read in the log file and then format the text as

\begin{minipage}[<height=H>]{<width=W>}
\begin{multicols*}{4}
...TEXT...
<insert struts determine by log file>
\end{multicols*}
\end{minipage}

But I don't know how to write this information to a log file or how to read in from the log file to create the necessary struts.

UPDATE: The start of a workable solution, but not quite there.

I've created the following work around. But there are several things about it that I can't get right:

\begin{filecontents}{content.tex}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum
gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate
a, magna. Donec vehicula augue eu neque. Pellentesque habitant morbi
tristique senectus et netus et malesuada fames ac turpis egestas. Mauris
ut leo. Cras viverra metus rhoncus sem. Nulla et lectus vestibulum urna
fringilla ultrices. Phasellus eu tellus sit amet tortor gravida
placerat. Integer sapien est, iaculis in, pretium quis, viverra ac,
nunc. Praesent eget sem vel leo ultrices bibendum. Aenean faucibus. Morbi
dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur auctor
semper nulla. Donec varius orci eget risus. Duis nibh mi, congue eu,
accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci
dignissim rutrum.

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel,
wisi. Morbi auctor lorem non justo. Nam lacus libero, pretium at, lobortis
vitae, ultricies et, tellus. Donec aliquet, tortor sed accumsan bibendum,
erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et
nisl hendrerit mollis. Suspendisse ut massa. Cras nec ante. Pellentesque a
\end{filecontents}
\documentclass{article}
%--------------------
%--------------------
\usepackage{xcolor}
\usepackage{fancyhdr}
\renewcommand{\footrulewidth}{0.4pt}
\pagestyle{fancy}
%--------------------
\usepackage{multicol}
\setlength{\columnseprule}{0.4pt}
\setlength{\columnsep}{0.25in}
%--------------------
\usepackage{lipsum}

\usepackage{xparse}

\newlength\aetmpdima
\newlength\aetmpdimb
%% Loop to reduce the height to below max value
\def\whileloop#1#2%
{\aetmpdima#1%
\aetmpdimb#2%
\ifdim\aetmpdima>\aetmpdimb\relax
\aetmpdima\dimexpr\aetmpdima-\aetmpdimb\relax
\whileloop\aetmpdima\aetmpdimb
\fi
#1\aetmpdima
}

\newlength{\myenvWIDTH}
\newlength{\myenvHEIGHT}
\newlength{\myenvREMAINDER}
\newlength{\myenvSTRUT}
\newcommand{\myenvCOLCNT}{4}
\setlength{\myenvWIDTH}{10in}
\setlength{\myenvHEIGHT}{2.25in}
\setlength{\myenvSTRUT}{0pt}
\newsavebox{\singlecolumnbox}
\NewDocumentCommand{\aecols}{ m }
{
%% create a box the width of one column
\begin{lrbox}{\singlecolumnbox}%
\begin{minipage}{\dimexpr(\myenvWIDTH-\number\numexpr\myenvCOLCNT-1\relax\columnsep)/\myenvCOLCNT}
\input{#1}%
\end{minipage}%
\end{lrbox}%
%% reduce lengths to get lengths of the struts
\setlength{\myenvREMAINDER}{\dimexpr\myenvCOLCNT\myenvHEIGHT-(\ht\singlecolumnbox+\dp\singlecolumnbox)\relax}%
\ifdim\myenvREMAINDER>\myenvHEIGHT\relax
\setlength{\myenvSTRUT}{\myenvHEIGHT}\fi
\whileloop{\myenvREMAINDER}{\myenvHEIGHT}%
%% format the multicolumn environment
\noindent
\begin{minipage}[t][\myenvHEIGHT]{\myenvWIDTH}%
\noindent
\begin{multicols}{\myenvCOLCNT}%
\raisebox{0pt}[0pt][0pt]{\textcolor{gray!60}{\rule[\dimexpr-\myenvHEIGHT+2ex]{4pt}{\myenvHEIGHT}}}
\input{#1}
\textcolor{blue}{\rule{4pt}{\dimexpr\myenvREMAINDER}}
\textcolor{red}{\rule{4pt}{\dimexpr\myenvSTRUT}}
\end{multicols}%
\par\xdef\tpd{\the\prevdepth}
\end{minipage}%
\par\prevdepth\tpd
}

\begin{document}

\lipsum[1]
\vspace{2ex}

\noindent\hspace*{\dimexpr\textwidth/2-\myenvWIDTH/2}%
\rule{\myenvWIDTH}{5pt}

\noindent\hspace*{\dimexpr\textwidth/2-\myenvWIDTH/2}%
\aecols{content}

\vspace{2ex}
\lipsum[2]

\end{document}

The first problem is I can't seem to get \vspace to work correctly. So, I have to use \rule. In this above example, I've given width different from 0pt only to help them be visible for development purposes. Similarly, the gray strut at the beginning is only there for development purposes.

The second problem, I sometimes get multiple overful vbox errors: apparently caused by my struts, but only for certain values of the parameters. (Can't seem to reproduce them right now, though.) When I do get the errors, there are far more than struts I've created. Sorry I can't reproduce them right now. :(

Third problem, I can't get the spacing after the environment to work out correctly. I tried the \prevdepth trick, but it's not working here.

Fourth, not so much a problem, I'm getting around the issue of having to reformatting the same text by reading the text in twice from an outside file. I can live with this, but it would be nice if I didn't have to go this route.

Any suggestions about how to fix any of this?

PS

If I can rediscover the parameter values which cause the vbox errors, I'll post them in the comments following this question.

-
Why would you like to put a three column text inside a minipage? – Keks Dose Jul 10 '13 at 19:54
@KeksDose I have text that needs to be formatted differently from the rest of the page: namely, in multiple columns. The formatting calls for it to span a width wider than the usual text width, but it should not sit on its own page. – A.Ellett Jul 10 '13 at 20:12
The parameter values, listed below, create 70 Overfull \vbox errors where the lengths vary from 48.23993pt too high to 76.23993pt too high and quite a few values inbetween. \myenvWidth=10in, \myenvHEIGHT=3.85in, \myenvCOLCNT=4. Not sure why I'm getting so many errors when I have at most 3 struts (I'm assuming it's the struts causing the problems). – A.Ellett Jul 11 '13 at 4:00
I got rid of the \noindent arguments from inside the \aecols command. I'd forgotten about these. This seems to fix the vertical alignment and my \vbox errors have disappeared for any of the current values I've been using. – A.Ellett Jul 11 '13 at 5:32
Post your solution as an answer and that's it. – Keks Dose Jul 12 '13 at 8:09

I'd use a low level method with \vsplit:

\documentclass{article}
\usepackage[latin]{babel} % to hyphenate lipsum
\usepackage{microtype}    % avoid overfull lines
%--------------------
\usepackage[
top=0.35in,
bottom=0.35in,
width=4in,
landscape,
includefoot,
]{geometry}

%--------------------

\usepackage{fancyhdr}
\pagestyle{fancy}
\renewcommand{\footrulewidth}{0.4pt}

%--------------------

\usepackage{lipsum}

\begin{document}

\lipsum[1]

\vspace{2ex}

\noindent
\hspace*{-3in}%
\makebox[0pt][l]{%
\setbox0=\vbox{\hsize=2.5in
\lipsum[1-2]
}%
\setbox2=\vsplit0 to 2.5in
\vtop{\hrule height0pt\unvbox2}\hspace{0.25in}\vrule\hspace{0.25in}%
\setbox2=\vsplit0 to 2.5in
\vtop{\hrule height0pt\unvbox2}\hspace{0.25in}\vrule\hspace{0.25in}%
\vtop{\hrule height0pt\unvbox0}
}

\vspace{3ex}

\lipsum[2]

\end{document}

-
This is an interesting solution. I'm going to play with it for a while to make sure I understand what it does and how I can create an environment that automates this. – A.Ellett Jan 11 '14 at 18:02

Well, here goes. I am more than a little reticent about this suggestion, and it is only a start -- you will want to tailor it to your needs if it suits. Still, I think this is what you want. I agree with egreg: \vsplit is your friend. The code first:

\documentclass{article}

%--------------------
%--------------------
\usepackage{fancyhdr}
\renewcommand{\footrulewidth}{0.4pt}
\pagestyle{fancy}

\usepackage{calc}
\usepackage{lipsum}

\newcommand{\breakit}{\vfill\eject\ \unskip}

\newlength{\unbalcolht}

\newenvironment{unbalminicols}[1][2in]{%
\setlength{\unbalcolht}{#1}
\parindent0pt
\vspace{2ex}
\hspace{-2.8in}
\begin{minipage}[1]{9.5in}
\setbox0=\vtop\bgroup\setlength{\hsize}{\linewidth/3-1em}%
}{%
\vfill
\egroup
\splittopskip0pt
\setbox1=\vtop{\vsplit0 to \unbalcolht}
\setbox2=\vtop{\vsplit0 to \unbalcolht}
\setbox3=\vtop{\vsplit0 to \unbalcolht}
\hbox to \linewidth{%
\vrule\hfil
\box1%
\hfil\vrule\hfil
\box2%
\hfil\vrule\hfil
\box3%
\hfil\vrule
}
\end{minipage}
\vspace{2ex}
}

\begin{document}

\lipsum[1]

\begin{unbalminicols}[1in]
This is the first column\breakit
This is the second column\breakit
This is the third column
\end{unbalminicols}

\lipsum[5]

\end{document}

and here is the output:

The environment unbalminicols does the work. It takes an optional argument to adjust the height of the columns, the default being 2in. \breakit does the work of breaking the columns when necessary. If you only have, say, two columns of text, you'll need a \breakit to fill out the minipage.

There is a lot of plain TeX here, and I feel sure that there are better ways to do this. Hopefully this helps.

In my haste, I assumed four columns. My bad. I have updated the code (and screenshot) for three columns. Also demonstrated the optional argument: \begin{unbalminicols}[1in]

-

If I understand right, this is the way:

\documentclass[pagesize, DIV=calc, parskip=half]{scrartcl}
\usepackage{multicol, microtype, blindtext, lmodern}
\begin{document}
Here is text in one column.

\blindtext

\begin{multicols}{3}
\blindtext
\end{multicols}

\blindtext

\end{document}

If you do not use KOMA-script (you'd better do that!), then you get the addmargin environment with the scrextend package.

-
This is a very nice, clean solution. I like it. But, I still need to use a minipage because the text to be set in multiple columns should set in an environment with a restricted height. In other words, I'm using the minipage environment to achieve two effects: (1) changing the width of the typeset text, (2) changing the height of the multi-columnar text. – A.Ellett Jul 11 '13 at 16:01
Also, I want to use unbalanced columns. – A.Ellett Jul 11 '13 at 16:09
This environment is meant to be used with text that will not fill all the columns fully. The empty columns will provide work space for students to write in. Later I can reprint selected students' work and on the hand-out the visual effect will be that I did not change any formatting, only that I added text. With balanced columns, the appearance (to my students) will be that I've reformatted the text. With unbalanced columns, it'll look like I took the original document and just continued the type-setting from where it had been left off on the worksheet. – A.Ellett Jul 11 '13 at 16:10
@A.Ellett I don't comprehend what you are trying to do. Make a step back and edit your question: Don't describe technical details before giving a full picture of the layout of the page and who should write what to which area. – Keks Dose Jul 11 '13 at 16:51
I've provided a full picture in the original question last night. I was just trying to explain why the need for all the empty columns. – A.Ellett Jul 11 '13 at 17:32

Inspired by @egreg's solution, here's a slight generalization of what he suggested. It requires the environ package:

\documentclass{article}
\usepackage[
top=0.35in,
bottom=0.35in,
width=4in,
landscape,
includefoot,
]{geometry}
\usepackage{fancyhdr}
\pagestyle{fancy}
\renewcommand{\footrulewidth}{0.4pt}
%--------------------

\usepackage{environ}
\usepackage{pgfkeys}
\makeatletter
\newlength{\ae@width}
\newlength{\ae@hoffset}
\newlength{\ae@topsep}
\newlength{\ae@botsep}
\newlength{\ae@colheight}
\newlength{\ae@colsep}
\newlength{\ae@colrulewidth}
\pgfkeys{/ae/multi/columns/.cd,
width/.code=\setlength\ae@width{#1},
hoffset/.code=\setlength\ae@hoffset{#1},
topsep/.code=\setlength\ae@topsep{#1},
botsep/.code=\setlength\ae@botsep{#1},
height/.code=\setlength\ae@colheight{#1},
colsep/.code=\setlength\ae@colsep{#1},
colrulewidth/.code=\setlength\ae@colrulewidth{#1},
}

\NewEnviron{aemulticol}[1][]
{\pgfkeys{/ae/multi/columns/.cd,
topsep=2ex,
botsep=2ex,
hoffset=-3in,
width=2in,
height=4in,
colsep=2em,
colrulewidth=0.4pt,
#1}%%
\vspace{\ae@topsep}\par
\noindent
\hspace*{\ae@hoffset}%%
\makebox[0pt][l]{\ae@set@multi@cols}%%
\vspace{\ae@botsep}\par
}

\def\ae@set@multi@cols{%%
\setbox0=\vbox{%%
\hsize=\ae@width
\BODY}%%
\splittopskip=0pt
\ae@build@column
}

\def\ae@build@column{%%
\setbox2=\vsplit0 to \ae@colheight
\vtop{%%
\hrule height0pt
\unvbox2
}%%
\ifvoid0\relax\else
\hspace{\dimexpr(\ae@colsep-\ae@colrulewidth)/2}%%
\vrule width \ae@colrulewidth
\hspace{\dimexpr(\ae@colsep-\ae@colrulewidth)/2}%%
\expandafter\ae@build@column
\fi}

\makeatother

\begin{document}

Alice was beginning to get very tired of sitting by her sister on
the bank, and of having nothing to do. Once or twice she had peeped
into the book her sister was reading, but it had no pictures or
conversations in it, and what is the use of a book,'' thought
Alice, without pictures or conversations?''
\begin{aemulticol}[width=2.75in,height=4.00in]
So she was considering in her own mind (as well as she could, for
the day made her feel very sleepy and stupid), whether the pleasure
of making a daisy-chain would be worth the trouble of getting up and
picking the daisies, when suddenly a White Rabbit with pink eyes ran
close by her.

There was nothing so very remarkable in that, nor did Alice think it
so very much out of the way to hear the Rabbit say to itself, Oh
dear! Oh dear! I shall be too late!'' But when the Rabbit actually
took a watch out of its waistcoat-pocket and looked at it and then
hurried on, Alice started to her feet, for it flashed across her
mind that she had never before seen a rabbit with either a
waistcoat-pocket, or a watch to take out of it, and, burning with
curiosity, she ran across the field after it and was just in time to
see it pop down a large rabbit-hole, under the hedge. In another
moment, down went Alice after it!

The rabbit-hole went straight on like a tunnel for some way and then
dipped suddenly down, so suddenly that Alice had not a moment to
think about stopping herself before she found herself falling down
what seemed to be a very deep well.

Either the well was very deep, or she fell very slowly, for she had
plenty of time, as she went down, to look about her. First, she
tried to make out what she was coming to, but it was too dark to see
anything; then she looked at the sides of the well and noticed that
they were filled with cupboards and book-shelves; here and there she
saw maps and pictures hung upon pegs. She took down a jar from one
of the shelves as she passed. It was labeled ORANGE MARMALADE,''
but, to her great disappointment, it was empty; she did not like to
drop the jar, so managed to put it into one of the cupboards as she
fell past it.

Down, down, down! Would the fall never come to an end? There was
nothing else to do, so Alice soon began talking to
herself. Dinah'll miss me very much to-night, I should think!''
(Dinah was the cat.) I hope they'll remember her saucer of milk at
tea-time. Dinah, my dear, I wish you were down here with me!'' Alice
felt that she was dozing off, when suddenly, thump! thump! down she
came upon a heap of sticks and dry leaves, and the fall was over.

Alice was not a bit hurt, and she jumped up in a moment. She looked
up, but it was all dark overhead; before her was another long
passage and the White Rabbit was still in sight, hurrying down
it. There was not a moment to be lost. Away went Alice like the wind
and was just in time to hear it say, as it turned a corner, Oh, my
ears and whiskers, how late it's getting!'' She was close behind it
when she turned the corner, but the Rabbit was no longer to be seen.
\end{aemulticol}
She found herself in a long, low hall, which was lit up by a row of
lamps hanging from the roof. There were doors all 'round the hall,
but they were all locked; and when Alice had been all the way down
one side and up the other, trying every door, she walked sadly down
the middle, wondering how she was ever to get out again.

Suddenly she came upon a little table, all made of solid
glass. There was nothing on it but a tiny golden key, and Alice's
first idea was that this might belong to one of the doors of the
hall; but, alas! either the locks were too large, or the key was too
small, but, at any rate, it would not open any of them. However, on
the second time 'round, she came upon a low curtain she had not
noticed before, and behind it was a little door about fifteen inches
high. She tried the little golden key in the lock, and to her great
delight, it fitted!

\end{document}

-