Multirow and Multirow Packages in LaTeX
Multirow and Multirow Packages in LaTeX
Contents
1 Introduction 2
2 Changes in version 2 2
3 Using multirow 3
3.1 Package Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.3 Fine-Tuning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.4 Multirow and colored cells . . . . . . . . . . . . . . . . . . . . . . . 8
3.5 Fine-tuning the hbigstrutsi parameter . . . . . . . . . . . . . . . . 9
3.6 Use with longtable . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.7 Use with supertabular . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.8 Dealing with tall entries . . . . . . . . . . . . . . . . . . . . . . . . 12
4 Using bigstrut 15
5 Using bigdelim 16
6 Implementation 17
6.1 The multirow package . . . . . . . . . . . . . . . . . . . . . . . . . 17
6.2 The bigstrut package . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.3 The bigdelim package . . . . . . . . . . . . . . . . . . . . . . . . . . 22
A Appendix 22
A.1 Case hnrowsi > 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
A.2 Case hnrowsi < 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
A.3 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
∗ catalogued “active author”
† Documentation originally put together by Robin Fairbairns
1
1 Introduction
These packages offer a series of extensions to the standard LATEX tabular envi-
ronment. Their respective functions are:
multirow which provides a construction for table cells that span more than one
row of the table;
bigstrut which creates struts which (slightly) stretch the table row in which they
sit.
bigdelim which creates an appropriately-sized delimiter (for example, brace,
parenthesis or bracket) to fit in a single multirow, to indicate a relation-
ship between other rows; and
2 Changes in version 2
version 2.3
• Replaced \textrm with \textnormal in text beside big braces in bigde-
[Link].
version 2.2
• Support for fractional values of hnrowsi.
version 2.0
• \multirow now has an first optional parameter [hvposi].
• The hwidthi parameter can be specified as = to use the defined width of the
column in which the \multirow appears.
• Optional prefix letters (t, b) for the hbigstrutsi parameter (see section 3.5).
• Package option debug.
• Package option longtable to work around a bug in longtable. See section 3.6.
• Package option supertabular to better support supertabular. See sec-
tion 3.7.
• Better positioning in some cases.
• Lots of documentation.
• The distribution is now based on a .dtx file.
• Backwards compatible with v1.6.
2
3 Using multirow
\multirow \multirow sets a piece of text in a tabular or similar environment, spanning
multiple rows. We will call the block of rows and columns that the text spans
the multirow block. Usually this covers one column, but by combining it with
\multicolumn more columns can be covered.
The basic syntax is:
\multirow[hvposi]{hnrowsi}[hbigstrutsi]{hwidthi}[hvmovei]{htexti}
where
hvposi defines the vertical positioning of the text in the multirow block. The
default is [c] which means the text will be vertically centered. Other options
are [t] for top alignment and [b] for bottom alignment.
hnrowsi is the number of rows to span. You should leave the other rows empty
at this column, otherwise the stuff created by \multirow will over-write
it. With a positive value of hnrowsi the spanned columns are this row and
(hnrowsi-1) rows below it. With a negative value of hnrowsi they are this
row and (1-hnrowsi) above it. Fractional values are permitted for hnrowsi;
this allows for some fine-tuning.
hbigstrutsi is mainly used if you’ve used the bigstrut package. In that case it
is the total number of uses of \bigstrut within the rows being spanned.
Count 2 uses for each \bigstrut, 1 for each \bigstrut[hx i] where hx i is
either t or b. The default is 0.
The hbigstrutsi parameter can optionally be preceded by a prefix letter t,
b or tb for finer control. See section 3.5 for details. The letter may be
separated from the number by a space character.
hwidthi is the width to which the text is to be set. Special values are * to indicate
that the text parameter’s natural width is to be used, and = to indicate that
the specified width of the column in which the \multirow entry is set should
be used.
hvmovei is a length used for fine-tuning: the text will be raised (or lowered, if
hvmovei is negative) by that length above (below) wherever it would other-
wise have gone.
htexti is the actual text of the construct. If the width was set explicitly, the text
will be set in a \parbox of that width; you can use \\ to force linebreaks
where you like.
If the width was given as * the text will be set in LR mode. If you want a
multiline entry in this case you could use a tabular or array environment
in the text parameter. See for example the minitab below.
The width can also be given as = when the \multirow entry is given in a
column that has a defined width, for example in a p{} column, an X column
in tabularx or a L, C, R or J column in a tabulary environment. The text
will be set in a \parbox of that width. If you give “=” in other situations,
you will get strange results (usually a too wide column).
3
N.B. \multirow can be used in the tabular environment and most deriva-
tives of it, for example tabularx, tabulary, supertabular, ltablex, xtab,
longtable, tabu, booktabs and ctable. For some of these you have to pay
special attention to certain cases, see below.
\multirowsetup Just before htexti is expanded, the \multirowsetup macro is expanded
to set up any special environment. Initially, \multirowsetup contains just
\raggedright. It may be redefined with \renewcommand.
If you want to use both \multirow and \multicolumn on the same entry, you
must put the \multirow inside the \multicolumn. The other way around will not
work. For example:
\multicolumn{2}{c}{\multirow{3}{*}{Multi-multi}}
3.2 Examples
An example with both multirow and bigstrut):
\newcommand{\minitab}[2][l]{\begin{tabular}{#1}#2\end{tabular}}
\begin{tabular}{|c|c|}
\hline
\multirow{4}{1in}{Common g text} & Column g2a\\
& Column g2b \\
& Column g2c \\
& Column g2d \\
\hline
\multirow{3}[6]*{Common g text} & Column g2a\bigstrut\\\cline{2-2}
& Column g2b \bigstrut\\\cline{2-2}
& Column g2c \bigstrut\\
\hline
\multirow{4}[8]{1in}{Common g text, but a bit longer.} &
Column g2a\bigstrut\\\cline{2-2}
& Column g2b \bigstrut\\\cline{2-2}
& Column g2c \bigstrut\\\cline{2-2}
& Column g2d \bigstrut\\
\hline
\multirow{4}*{\minitab[c]{Common \\ g text}} & Column g2a\\
& Column g2b \\
4
& Column g2c \\
& Column g2d \\
\hline
\end{tabular}
An example with the “=” hwidthi specifier in a tabulary (Note: The braces around
the = may be omitted):
\setlength{\extrarowheight}{2pt}
\begin{tabulary}{11cm}{|L|L|L|}
\hline
All human beings are born free and equal in dignity and rights. &
\multirow{2}{=}{Everyone is entitled to all the rights and
freedoms set forth in this Declaration, without distinction of
any kind, such as race, colour, sex, language, religion,
political or other opinion, national or social origin, property,
birth or other status.}
& Everyone has the right to life, liberty and security of person. \\
\cline{1-1}\cline{3-3}
No one shall be held in slavery or servitude; slavery and the
slave trade shall be prohibited in all their forms. &
& No one shall be subjected to torture or to cruel, inhuman or
degrading treatment or punishment. \\
\hline
\end{tabulary}
5
All human beings Everyone is entitled to all Everyone has
are born free and the rights and freedoms set the right to life,
equal in dignity forth in this Declaration, liberty and
and rights. without distinction of any security of
kind, such as race, colour, person.
No one shall be sex, language, religion, No one shall be
held in slavery or political or other opinion, subjected to
servitude; slavery national or social origin, torture or to
and the slave property, birth or other cruel, inhuman
trade shall be status. or degrading
prohibited in all treatment or
their forms. punishment.
\setlength{\extrarowheight}{2pt}
\begin{tabulary}{11cm}{|L|L|L|}
\hline
All human beings are born free and equal in dignity and rights. &
& Everyone has the right to life, liberty and security of person. \\
\cline{1-1}\cline{3-3}
No one shall be held in slavery or servitude; slavery and the
slave trade shall be prohibited in all their forms. &
\multirow{-2}{=}[12mm]{Everyone is entitled to all the rights and
freedoms set forth in this Declaration, without distinction of
any kind, such as race, colour, sex, language, religion,
political or other opinion, national or social origin, property,
birth or other status.}
& No one shall be subjected to torture or to cruel, inhuman or
degrading treatment or punishment. \\
\hline
\end{tabulary}
1 This is only available with the array package, which tabulary includes automatically.
6
All human beings Everyone has
are born free and Everyone is entitled to all the right to life,
equal in dignity the rights and freedoms set liberty and
and rights. forth in this Declaration, security of
without distinction of any person.
No one shall be kind, such as race, colour, No one shall be
held in slavery or sex, language, religion, subjected to
servitude; slavery political or other opinion, torture or to
and the slave national or social origin, cruel, inhuman
trade shall be property, birth or other or degrading
prohibited in all status. treatment or
their forms. punishment.
In this case the text would be centered somewhere in the bottom row, which
would make it stick out of the bottom. Therefore we applied a hvmovei of 12mm.
The hvmovei usually requires some experimentation.
3.3 Fine-Tuning
If any of the spanned rows are unusually large, or if you’re using the bigstrut
package and \bigstruts are used asymetrically about the centerline of the spanned
rows, the vertical centering may not come out right. Use the hvmovei parameter in
this case. Sometimes it may be more helpful to just use a larger value for hnrowsi,
including fractional values. See an example in section 3.8.
It’s just about impossible to deal correctly with descenders. The text will be
set up centered, but it may then have a baseline that doesn’t match the baseline
of the stuff beside it, in particular if the stuff beside it has descenders and htexti
does not. This may result in a small misalignment. About all that can be done
is to do a final touchup on htexti, using the hvmovei optional parameter. (Hint:
If you use a measure like .1ex, there’s a reasonable chance that the hvmovei will
still be correct if you change the point size.)
\multirow is mainly designed for use with tabular, as opposed to array,
environments. It might not work well in an array environment if there are big
formulas in some rows; in that case you can use the hvmovei parameter to refine
the result.
In some cases you might want to align the multirow entry with the top of the
other row cells, for example if you have a large capital in it. when you use hvposi
= [t], the baselines will be aligned, which is the wrong thing in this case. You
can then do the positioning with the hvmovei parameter and let LATEX calculate
the amount. For example:
\usepackage{calc}
\newlength{\shiftdown}
\setlength{\shiftdown}{\heightof{\Huge\bfseries B}-\heightof{f}}
. . .
\begin{tabular}{cll}
\toprule
\multirow[t]{5}{*}[-\shiftdown]{\Huge\bfseries B}
& foo & Lorem ipsum dolor sit \\
& bar & Maecenas sed purus \\
& baz & Nullam luctus id tellus \\
7
& qux & Aenean consequat commodo \\
\bottomrule
\end{tabular}
B foo
bar
Lorem ipsum dolor sit
Maecenas sed purus
baz Nullam luctus id tellus
qux Aenean consequat commodo
ColumnOne ColumnTwo
First data 932
239
More data 137
319
Last data 132
8
This can be solved by putting colored horizontal rules with the same color in
the colored multirow cell.
\begin{tabular}{|>{\columncolor{red}}c|c|}
\hline
\bfseries ColumnOne & \bfseries ColumnTwo\\ \hline
First data & 932\\ \hline
& 239\\ \hhline{|>{\arrayrulecolor{red}}->{\arrayrulecolor{black}}|-|}
& 137\\ \hhline{|>{\arrayrulecolor{red}}->{\arrayrulecolor{black}}|-|}
\multirow{-3}{*}{More data} & 319\\ \hline
Last data & 132\\ \hline
\end{tabular}
ColumnOne ColumnTwo
First data 932
239
More data 137
319
Last data 132
\begin{tabular}{|c|c|}
T \hline
\multirow{3}[1]{*}{Multirow} & T \bigstrut[t] \\
X
Multirow \cline{2-2}
B & X \\
\cline{2-2}
T & B \\
Multirow X \hline
\end{tabular}
B
In the top box in the above example the text “Multirow” should be centered, but
it is a bit below the center, because of the \bigstrut[t] in the top row. We can
correct this by giving the hbigstrutsi parameter as “t 1”, indicating a bigstrut in the
top. This is done in the bottom box, where \multirow{3}[t 1]{*}{Multirow}
is used.
A second example:
9
Multirow \begin{tabular}{|c|c|}
T
\hline
X & T \\
B \cline{2-2}
& X \\
Multirow T \cline{2-2}
\multirow[t]{-3}[1]{*}{Multirow} & B \bigstrut[b] \\
X
\hline
B
\end{tabular}
In the top box the \multirow[t] should be positioned on the same height as
the T, but it is too high, because there is a \bigstrut in the bottom. We
can correct that by specifying the hbigstrutsi parameter as “b 1”, i.e. using
\multirow[t]{-3}[b 1]{*}{Multirow}.
In this case if the “Sept. 23” entry comes close to the bottom of the page, you
want to prevent the pagebreak to occur in the middle of this entry. You can do
this by ending the intermediate rows with \\* instead of \\.
10
\multirow{3}*{Sept. 23} & 10:00 & event 3 \\*
& 12:00 & event 4 \\*
& 15:00 & event 5 \\
There is, however, a bug in longtable, that causes the \\* not to work if it is
followed by a \cline, like in the following example:
multirow has a package option longtable that redefines \cline so that the
\\* will also work when followed by \cline. The code comes from David Carlisle.
11
\ldots & \ldots & \ldots \\
You will have to experiment a bit with the value to see what works. Sometimes
it is better to exaggerate the required space a bit.
\begin{tabular}{| l | l | p{4cm} |}
\hline
\multirow{3}*{Week 38} & Monday & Rain most of the day\\
\cline{2-3}
& Tuesday & Sunny with some clouds\\
\cline{2-3}
& Wednesday & A clear day with a lot of sunshine.
However, the strong wind will bring down the
temperature. \\
\hline
\end{tabular}
12
must now enlarge the other rows, and that is something \multirow cannot
do.
An example: (Don’t take this as a medical advice. The names are fake
anyway.)
Both \multirow entries are too high; the first sticks out into the second
entry, and the second one sticks out of the table.
There are two ways we can correct this: The simplest would be to add extra
empty rows to cover the overlapping space. For the first entry that would
13
be 2 extra rows; for the second 4. So we add twice & & \\ before the third
\hline, and four of these before the last \hline. This gives us just the
correct table:
\newcommand{\mystrut}{\rule[-8pt]{0pt}{20pt}}
\setlength{\bigstrutjot}{7pt}
\begin{tabular}{ p{2mm} l p{5cm} }
\toprule
\multicolumn{2}{l}{\textbf{Medicine \& dose}}
& \textbf{Possible Side effects} \\
\cmidrule(r){1-2} \cmidrule(l){3-3}
\multicolumn{2}{l}{Spirino} \mystrut
& \multirow{3}={Confusion,
hallucinations, rapid breathing,
14
seizure (convulsions);
upset stomach, heartburn; severe nausea,
vomiting, or stomach pain or mild headache.} \\
\cmidrule(r){1-2}
& initial: 200 mg/day \mystrut & \\
\cmidrule(r){1-2}
& maintenance: 100-400 mg/day \mystrut & \\
\midrule
\multicolumn{2}{l}{Conzac} \bigstrut
& \multirow{3}[tb6]={Anxiety; nervousness;
insomnia; anorexia; mild bradycardia;
SA node slowing; weight loss;
solar photosensitivity; hyponatremia;
sexual dysfunction (both genders); may
alter glycemic control in diabetic patients.} \\
\cmidrule(r){1-2}
& initial: 10 mg/day \bigstrut & \\
\cmidrule(r){1-2}
& maintenance: 10-40 mg/day \bigstrut & \\
\bottomrule
\end{tabular}
4 Using bigstrut
\bigstrut \bigstrut[hx i] produces a strut (a rule with width 0) which is \bigstrutjot
\bigstrutjot (2pt by default) higher, lower, or both than the standard array/tabular strut. Use
it in table entries that are adjacent to \hlines to leave an extra bit of space —
according to the TeXbook (page 246), “This is a little touch that improves the
appearance of boxed tables; look for it as a mark of quality.”
Although you could use \bigstrut in an array, there isn’t normally much point
since arrays are ‘opened up’ by \jot anyway.
\bigstrut[t] adds height; \bigstrut[b] adds depth. Just \bigstrut adds
both. So: Use \bigstrut[t] in the row just after an \hline; \bigstrut[b] in
the row just before; and \bigstrut if there are \hlines both before and after.
15
Spaces after the \bigstrut are ignored, even if it has an optional parameter.
Spaces before the \bigstrut are generally ignored (by a single \unskip).
\bigstrutjot Note: The multirow package makes use of \bigstrutjot. If both packages
are used, they can be used in either order, as each checks to see if the other has
already defined \bigstrutjot. However, the default values they set are different:
if only multirow is used, \bigstrutjot will be set to 3pt. If bigstrut is used, with
or without multirow, \bigstrutjot will be 2pt.
5 Using bigdelim
The package is for working in a tabular or array environment, in which the
multirow package is also used.
\ldelim Syntax of use is
\rdelim
\ldelim ( {hni}{hwidthi}[htexti]
\rdelim ) {hni}{hwidthi}[htexti]
The commands are used in a column of a tabular or array; they create a big
parenthesis, brace or whatever delimiter that extends over the hni rows starting at
the one containing the command. Corresponding cells in the following rows must
be explicitly given as empty cells.
The first parameter is a delimiter to be used, e.g., \{ \} [ ] ( ) — in fact,
anything that can be used with \left or \right, as appropriate.
Here is an example:
\begin{equation}
\begin{array}{ccccccc}
\ldelim({4}{4mm} & x & x & x & x & \rdelim){4}{4mm} \\
& x & x & x & x & & i \\
& x & x & x & x & & j \\
& x & x & x & x & \\
& & u & v & &
\end{array}
\end{equation}
x x x x
x x x x
i
x x x x j (1)
x x x x
u v
When \ldelim is used, the optional htexti is set centred to the left of \ldelim.
If \rdelim is used it is set to the right of \rdelim. The hwidthi parameter is the
space that is reserved for the delimiter and its text; as with the multirow package,
the hwidthi may be given as *. Compare for example these:
\begin{tabular}{p{2em}l}
\ldelim\{{3}{*}[type] & dvi \\ dvi
& ps \\ type ps
& pdf \\ pdf
\end{tabular}
16
\begin{tabular}{l@{\,}l}
\ldelim\{{3}{*}[type] & dvi \\ dvi
& ps \\ type ps
& pdf \\ pdf
\end{tabular}
In the first example we cheated: by using a column width that is too small, we
swallowed up some of the intercolumn space, at the cost of an “Overfull \hbox”
message. In the second example we did it the proper way by inserting @{\,} to
replace the default intercolumn space with a narrow space.
Also the commands may be used in the last row of the extension with a negative
hni parameter. This is useful in combination with colortbl (see the discussion in
section 3 on multirow). If there are unusually tall rows you may have to enlarge
hni (you can use fractional values). If you have horizontal lines that interact with
the braces you are advised to use the hhline package to make the lines.
In case you want to have a paragraph type text as optional parameter you
could put it in a \parbox. Alternatively you could add an extra column with the
text in a \multirow, like in
\begin{tabular}{l@{}l@{}l}
dvi & \rdelim\}{3}{1em} & \multirow{3}{4cm}{These are the output types,
that are commonly used for \TeX.} \\
ps & & \\
pdf & & \\
\end{tabular}
dvi These are the output
ps types, that are commonly
pdf used for TEX.
Note that we used @{} to eliminate the intercolumn space to get the text tight to
the brace.
6 Implementation
6.1 The multirow package
\ifmultirowdebug This is a boolean to [de]activate debugging (showing the generated box contents).
\multirowdebugtrue It is activated by the debug package option. The \newif initializes it to false.
\multirowdebugfalse 1 \newif\ifmultirowdebug
2 \DeclareOption{debug}{\multirowdebugtrue}
\cline The package option longtable redefines the \cline macro to work around a bug
in longtable. See section 3.62 .
3 \DeclareOption{longtable}{%
4 \AtBeginDocument{%
5 \def\@cline#1-#2\@nil{%
2 Thanks to David Carlisle. See [Link]
longtable-multirow-problem-with-cline-and-nopagebreak#answer-52101
17
6 \omit
7 \@multicnt#1%
8 \advance\@multispan\m@ne
9 \ifnum\@multicnt=\@ne\@firstofone{&\omit}\fi
10 \@multicnt#2%
11 \advance\@multicnt-#1%
12 \advance\@multispan\@ne
13 \leaders\hrule\@height\arrayrulewidth\hfill
14 \cr
15 \noalign{\nobreak\vskip-\arrayrulewidth}}
16 }}
\ST@tabularcr This macro is the definition of \\ inside a supertabular. We check for a *, and
if it is present we call our own version, otherwise the supertabular version.
19 \def\ST@tabularcr{%
20 {\ifnum0=‘}\fi
21 \@ifstar{\MRST@xtabularcr}{\ST@xtabularcr}}
\MRST@xtabularc These are copies of the corresponding macros from supertabular, but instead of
\MRST@argtabularc \ST@cr they call \MRST@cr.
\MRST@xargtabularc 22 \def\MRST@xtabularcr{%
\MRST@yargtabularc 23 \@ifnextchar[%]
24 {\MRST@argtabularcr}%
25 {\ifnum0=‘{\fi}\cr\MRST@cr}}
26 \def\MRST@argtabularcr[#1]{%
27 \ifnum0=‘{\fi}%
28 \ifdim #1>\z@
29 \unskip\MRST@xargarraycr{#1}
30 \else
31 \MRST@yargarraycr{#1}%
32 \fi}
33 \def\MRST@xargarraycr#1{%
34 \@tempdima #1\advance\@tempdima \dp \@arstrutbox
35 \vrule \@height\z@ \@depth\@tempdima \@width\z@ \cr
36 \noalign{\global\ST@toadd=#1}\MRST@cr}
37 \def\MRST@yargarraycr#1{%
38 \cr\noalign{\vskip #1\global\MRST@toadd=#1}\MRST@cr}
\MRST@cr This is a truncated copy of \ST@cr. It does all the bookkeeping about the space
the longtable occupies, but it doesn’t do the pagebreaking part.
39 \def\MRST@cr{%
40 \noalign{%
41 \ifnum\ST@pboxht<\ST@lineht
42 \global\advance\ST@pageleft -\ST@lineht
43 \global\ST@prevht\ST@lineht
44 \else
45 \global\advance\ST@pageleft -\ST@pboxht
18
46 \global\advance\ST@pageleft -0.1\ST@pboxht
47 \global\advance\ST@pageleft -\ST@stretchht
48 \global\ST@prevht\ST@pboxht
49 \global\ST@pboxht\z@
50 \fi
51 \global\advance\ST@pageleft -\ST@toadd
52 \global\ST@toadd=\z@}}
53 }
\STneed This macro can be used in a supertabular to indicate how much space a multirow
entry needs. See section 3.7.
54 \def\STneed#1{\ifdim\ST@pageleft<#1\ST@newpage\ST@next\fi}
55 }
56 \ProcessOptions
\multirow@colwidth is a length that is used to implement the “=” variant of
hwidthi.
\multirow@cntb Define two counters and a length for internal use in \multirow.
\multirow@dima 58 \newcount\multirow@cntb
59 \newlength\multirow@dima
\multirow@setcolwidth This macro calculates \multirow@colwidth for an entry that has the hwidthi
given as “=”. We check if we are inside a tabulary environment, by checking if
\TY@final is defined. If not, then \multirow@colwidth = \hsize. The tabulary
environment will make two passes. On the first pass, we set \multirow@colwidth
to the size that the text would have in LR mode (with newlines replaced by spaces),
so that tabulary will gives us enough space. On the second pass (characterized
by \TY@box = \TY@box@v) we use the value that tabulary has given us in \hsize.
This algorithm is not perfect, but good enough in most cases.
60 \def\multirow@setcolwidth#1{%
61 \ifx\TY@final\multirow@undefined \multirow@colwidth=\hsize
62 \else
63 \ifx\TY@box\TY@box@v\multirow@colwidth=\hsize
64 \else \setbox0\hbox
65 {\let\\\space\let\newline\space #1}\multirow@colwidth=\wd0
66 \fi
67 \fi}
19
Depending on the hvposi parameter, it will be top-aligned, vertically centered, or
bottom-aligned. This is done by inserting \vfill in the proper places.
Note: the \relax is to protect against an empty hvposi parameter.
69 \long\def\multirow@vbox#1#2#3{\setbox0\vtop to \multirow@dima{#2%
70 \if #1t\relax\else\vfill\fi
71 \multirowsetup #3\if #1b\relax\else\vfill\fi}}
\multirow@piii This macro splits off a t, b, or tb prefix of the hbigstrutsi parameter, and
\ifmultirow@prefixt sets \multirow@cntb to the numerical value. The prefix is remembered in two
\multirow@prefixttrue booleans: \ifmultirow@prefixt and \ifmultirow@prefixb.
\multirow@prefixtfalse 77 \newif\ifmultirow@prefixt
\ifmultirow@prefixb 78 \newif\ifmultirow@prefixb
\multirow@prefixbtrue 79 \def\multirow@piii#1#2#3\end{\multirow@prefixtfalse\multirow@prefixbfalse
\multirow@prefixbfalse 80 \if t#1\multirow@prefixttrue
81 \if b#2\multirow@prefixbtrue \multirow@cntb=#3%
82 \else \multirow@cntb=#2#3%
83 \fi
84 \else
85 \if b#1\multirow@prefixbtrue \multirow@cntb=#2#3%
86 \else \multirow@cntb=#1#2#3%
87 \fi
88 \fi}
This is the real workhorse. It starts with splitting the hbigstrutsi parameter,
and then calculating the height of the multirow box. Because hnrowsi (#2) can
be fractional, we cannot use \ifnum to test for positive or negative. Therefore we
use \ifdim by putting a unit (pt) after the number.
89 \def\@xmultirow[#1]#2[#3]#4[#5]#6{%
90 \expandafter\multirow@piii#3\relax\end%
91 \multirow@dima=#2\ht\@arstrutbox
92 \advance\multirow@dima#2\dp\@arstrutbox
93 \ifdim#2pt<\z@\multirow@dima=-\multirow@dima\fi
94 \advance\multirow@dima \multirow@cntb\bigstrutjot
The text is set in a \vbox by calling \multirow@vbox.
If the hwidthi parameter is * set just the text in the \vbox.
95 \if*#4\multirow@vbox{#1}{}{\hbox{\strut#6\strut}}%
Otherwise set it in a \parbox inside a \vbox.
If the hwidthi parameter is given as “=”, we calculate \multirow@colwidth and
use that as width of the \parbox.
96 \else \if=#4\multirow@setcolwidth{#6}%
97 \multirow@vbox{#1}{\hsize\multirow@colwidth\@parboxrestore}{\strut#6\strut\par}%
20
Otherwise the given parameter is used as the width of the \parbox.
98 \else \multirow@vbox{#1}{\hsize#4\@parboxrestore}{\strut#6\strut\par}%
99 \fi \fi
Now position the \vbox properly. More details are given in the appendix. The
overview of the calculation of the shift amount can be found in section A.3.
If hnrowsi > 0:
If hvposi = [t], then the box is already positioned correctly (the baseline is on
the baseline of the row). However, later the top of the box will be taken as the
reference point (instead of the baseline), therefore we take the height of the box
(h) as the shift amount. See fig. 1.
If hvposi = [c] we shift it up h1 (see fig. 2), where h1 = \ht\@arstrutbox +
(\bigstrutjot \ifmultirow@prefixt).
If hvposi = [b] we shift it up h1 + h2 (see fig. 3), where h2 = \dp\@arstrutbox
+ (\bigstrutjot \ifmultirow@prefixb).
We calculate the required shift in \multirow@dima.
100 \ifdim#2pt>\z@
101 \if#1t\relax\multirow@dima=\ht0\else
102 \multirow@dima=\ht\@arstrutbox
103 \ifmultirow@prefixt \advance\multirow@dima\bigstrutjot\fi
104 \if#1b\relax \advance\multirow@dima\dp\@arstrutbox
105 \ifmultirow@prefixb \advance\multirow@dima\bigstrutjot\fi
106 \fi
107 \fi
If hnrowsi < 0:
If hvposi = [t], shift the box up H − h1 − h2 + h. See fig. 4.
If hvposi = [c], shift the box up H − h2. See fig. 5.
If hvposi = [b], shift the box up H. See fig. 6.
H is the current value of \multirow@dima.
108 \else
109 \if#1b\relax\else
110 \advance\multirow@dima-\dp\@arstrutbox
111 \ifmultirow@prefixb \advance\multirow@dima-\bigstrutjot\fi
112 \if#1t\relax\advance\multirow@dima-\ht\@arstrutbox
113 \ifmultirow@prefixt \advance\multirow@dima-\bigstrutjot\fi
114 \advance\multirow@dima\ht0
115 \fi
116 \fi
117 \fi
Finally, we add the hvmovei parameter (#5), and go into horizontal mode. Then
we shift the box up by putting a \vskip above it, and add it to the output.
Because of the \vskip the resulting box will have a height 0. We set the depth of
the \vbox to 0, so that it will not influence the depth of the current row.
If \multirowdebug is true, we show the box.
118 \advance\multirow@dima#5\relax
119 \leavevmode
120 \setbox0\vtop{\vskip-\multirow@dima\box0\vss}\dp0=\z@
121 \ifmultirowdebug{\showboxdepth=5 \showboxbreadth=10 \showbox0}\fi
122 \box0
123 }
21
\bigstrutjot Define \bigstrutjot if not already defined.
124 \@ifundefined{bigstrutjot}{\newdimen\bigstrutjot \bigstrutjot=\jot}{}
\bigstrut This macro inserts a strut. Depending on the optional parameter it extends above
and/or below the standard array/tabular strut.
126 \newcommand\bigstrut[1][x]{%
127 \unskip\@tempdima=\ht\@arstrutbox \@tempdimb=\dp\@arstrutbox
128 \ifx #1b\relax \else \advance\@tempdima by \bigstrutjot\fi
129 \ifx #1t\relax \else \advance\@tempdimb by \bigstrutjot\fi
130 \hbox{\vrule \@height\@tempdima \@depth\@tempdimb \@width\z@}\ignorespaces}
\rdelim This macro typesets a right delimiter. It calls \multirow with the proper param-
eters, similar to \ldelim.
138 \newcommand\rdelim[3]{\@ifnextchar[{\@rdelim{#1}{#2}{#3}}{\@rdelim{#1}{#2}{#3}[\null]}}
139 \def\@rdelim#1#2#3[#4]%
140 {\multirow{#2}{#3}{%
141 \ensuremath
142 {\left#1\vcenter{\hsize=0pt\vrule height \multirow@dima width 0pt}%
143 \textnormal{#4}\right.}}}
A Appendix
In this section we explain the \vbox positioning in \multirow. The positioning
depends on the hnrowsi, hvposi, hbigstrutsi and hvmovei parameters. The box is
constructed with \vtop. The algorithm of \vtop is described in The TEXbook,
p. 81.
Each case is described by a figure. In the figure the lefthand column indicates
the context of the tabular in which the multirow appears, i.e hnrowsi rows. The
righthand column is the multirow box that is to be inserted. The baseline is the
22
natural position where the material will be positioned in the first place. Later it
will be shifted up to the desired location.
H is the calculated height of the box: hnrowsi × the natural height of a row +
hbigstrutsi × \bigstrutjot.
topstrut = \bigstrutjot if there is a \bigstrut on the top of the first row
(as indicated by the t prefix in the hbigstrutsi parameter), otherwise 0.
botstrut = \bigstrutjot if there is a \bigstrut on bottom of the last row
(as indicated by the b prefix in the hbigstrutsi parameter), otherwise 0.
h1 = height of a tabular row + topstrut
h2 = depth of a tabular row + botstrut
Note: the following descriptions describe the vertical shift of the box without
taking the hvmovei into account. In all cases hvmovei has to be added if it is
given.
topstrut
h1
h
baseline
H text
H
\vfill
botstrut
hvposi = [c]
In this case the \vbox contains a \vfill, the text, and another \vfill. Such a
\vbox has a height 0, i.e. the top of the box is on the baseline. Because both
23
boxes have the same size (H), they can be aligned by shifting the \vbox up over
h1. See fig. 2.
topstrut
h1
baseline
\vfill
text H
botstrut
\vfill
hvposi = [b]
Now the \vbox contains a \vfill, followed by the text. Because it ends with the
text, it gets an additional depth equal to the depth of the last line of the text.
Such a \vbox has a height 0, i.e. the top of the box is on the baseline, but its
depth is H + that depth. In other words the baseline of the last text line is H
below the top.
Because hvposi = [b] we want the baseline of the last textline to shift to the
baseline of the last tabular row. The amount of the shift is h1 + h2. See fig. 3.
topstrut
h1
baseline
H \vfill
H
baseline
botstrut h2
text
24
A.2 Case hnrowsi < 0
hnrowsi < 0 when the multirow is positioned in the last row of the multirow block.
hvposi = [t]
In this case the \vbox contains the text followed by a \vfill. Such a \vbox has
a height that is the height of the top line of the text. The baseline is aligned with
the baseline of the last row. Because hvposi = [t], we want it to be aligned with
the baseline of the first row. Therefore it has to be shifted up H − h1 − h2. But
because later the height of the box will be set to 0, we must also add the current
height h. Therefore the total shift becomes H − h1 − h2 + h. See fig. 4.
topstrut
h1
baseline
h
baseline
botstrut h2
text
H
\vfill
hvposi = [c]
In this case the \vbox contains a \vfill, the text, and another \vfill. Such a
\vbox has a height 0, i.e. the top of the box is on the baseline. Because both
boxes have the same size (H), they can be aligned by shifting the \vbox up over
H − h2. See fig. 5.
hvposi = [b]
The \vbox contains a \vfill, followed by the text. Because it ends with the text,
it gets an additional depth equal to the depth of the last line of the text. Such a
\vbox has a height 0, i.e. the top of the box is on the baseline, but its depth is H
+ that depth. In other words the baseline of the last text line is H below the top.
25
topstrut
h1
baseline
baseline
botstrut h2
\vfill
text
\vfill
Because hvposi = [b] we want the baseline of the last textline to shift to the
baseline of the last tabular row. The amount of the shift is H. See fig. 6.
A.3 Overview
hvposi hnrowsi > 0 hnrowsi < 0
[t] h H − h1 − h2 + h
[c] h1 H − h2
[b] h1 + h2 H
x H − h1 − h2 + x
Change History
26
topstrut
h1
baseline
baseline
botstrut h2
vfill
H
text
27
Implement the “=” option for v2.0
\multirow’s hwidthi General: Release v2.0 . . . . . . . . . . 1
parameter. . . . . . . . . . . . . . . 19 v2.1
v1.9a \multirow: Set depth of final
\multirow: Add the optional prefix \vbox to 0, to prevent a tall
to the hbigstrutsi parameter. . 20 multirow line to push the
following rows downwards. . . . 21
Redo the \vbox calculation and
General: Rename hfixupi to
positioning. . . . . . . . . . . . . . 20
hvmovei in the documentation
General: Implement the debug
as in The LaTeX Companion. . 3
option. . . . . . . . . . . . . . . . . . 17
v2.2
v1.9b \multirow: Support fractional
General: Implement the longtable values for hnrowsi. . . . . . . . . 20
option. . . . . . . . . . . . . . . . . . 17 General: Eliminate
Implement the supertabular \multirow@cnta. . . . . . . . . . 19
option and the \STneed v2.3
command. . . . . . . . . . . . . . . 18 General: Small bugfix . . . . . . . . . 1
Index
Numbers written in italic refer to the page where the corresponding entry is de-
scribed; numbers underlined refer to the code line of the definition; numbers in
roman refer to the code lines where the entry is used.
B longtable . . . . . . . . 10 \multirow@setcolwidth
\bigstrut . . . . . 15, 126 longtabu . . . . . . . . . 10 . . . . . . . . . . . . 60
\bigstrutjot . . . . . . \multirow@vbox . . . . 69
. . 15, 16, 124, 125 M
\multirowdebugfalse
\MRST@argtabularc . 22
booktabs . . . . . . . . . 14 . . . . . . . . . . . 1, 4
\MRST@cr . . . . . . . . . 39
\multirowdebugtrue 1, 4
C \MRST@xargtabularc . 22
\multirowsetup . . . 4, 68
\cline . . . . . . . . . . . . 3 \MRST@xtabularc . . . 22
\mystrut . . . . . . . . . 14
colortbl . . . . . . . . . 8, 17 \MRST@yargtabularc . 22
\multicolumn . . . . . . . 4
\multirow . . . . . . . 3, 72 R
E \rdelim . . . . . . . 16, 138
\extrarowheight . . 5, 6 \multirow@cntb . . . . 58
\multirow@colwidth . 57
\multirow@dima . . . . 58 S
H
\multirow@piii . . . . 77 \ST@tabularcr . . . . . 19
hhline . . . . . . . . . . 8, 17
\multirow@prefixbfalse \STneed . . . . . . . . 11, 54
I . . . . . . . . . . . . 77 supertabular . . . . . . 11
\ifmultirow@prefixb 77 \multirow@prefixbtrue
\ifmultirow@prefixt 77 . . . . . . . . . . . . 77 V
\ifmultirowdebug . . . 1 \multirow@prefixtfalse \vbox . . . . . . . . . . . . 22
. . . . . . . . . . . . 77
L \multirow@prefixttrue X
\ldelim . . . . . . . 16, 132 . . . . . . . . . . . . 77 xtab . . . . . . . . . . . . . 11
28