# How can I suppress a page break before all \midrule and \cmidrule horizontal lines in an xtabular environment?

I have a large number of tables (several dozen) which contain either amino acid or DNA nucleotide sequences, and are produced by a semi-automated bioinformatics workflow.

These tables are fairly long, often running to two or even three pages, therefore I need to use a table-making environment that supports a multi-page typesetting capability. I decided to use the xtab package, based upon advice I found in section 3.4.2 of this document at tug.org:

The xtab package has functions very similar to those of supertabular but it corrects some defects thus it is recommended.

One of the nice features that xtab offers is a capability to print a table header that will appear at the top of each subsequent page after the first one. However, when xtab creates a page break in the vicinity of a midline rule, it seems to prefer always placing the page break immediately before the midrule, so that the midrule appears at the top of the next page, instead of at the bottom of the previous one. While this may look good when the multi-page table header feature is disabled, it looks wrong when multi-page headers are operational.

Below, I've included a MWE, and a screenshot of the output that it produces when I compile with xelatex:

% Basic document setup
\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\geometry{letterpaper}
\usepackage{fontspec}
\setmainfont{Tinos}

% Table-specific setup
\usepackage{xtab}      % Needed for multi-page tables
\usepackage{multirow}  % Needed because some cells span 2 rows
\usepackage{booktabs}  % Improves appearance of horizontal lines and rules
\newcommand{\otoprule }{\midrule[\heavyrulewidth]}
\usepackage{seqsplit}  % Needed for line breaking amino acid sequences
\usepackage{siunitx}   % Needed for aligning numbers in columns
\sisetup{
table-format = 2.2
}

\begin{document}
\begin{center}
% Print this header at the top of the first page.  Enclose 3rd column in
% brackets as a workaround to a weird bug that seems to arise from an
% interaction between xtab and siunitx packages.
Name & Type & {ID Number} & Amino Acid Sequences \\
\otoprule}
% Print this header at the top of all subsequent pages -- I made it identical
% to above, but in principle it could be different
Name & Type & {ID Number} & Amino Acid Sequences \\
\otoprule}
% Begin actual table body
\begin{xtabular}{lcS[table-number-alignment = right]p{0.6\textwidth}}
\multirow[t]{2}{*}{ABCD1001} & A & 1 & \seqsplit{CVPCYFWIIQMADNYCCYFMSRMCRPVFMTGHKWWANNQCVERSVTHKDFGRANAAFAKAYTGRNYHCNYKRYWYNNATQYPHMAEWHT} \\
\cmidrule(l){2-4}
& B & 2 & \seqsplit{AAWLYALGCQTDVYDISKYIQCGLEYRIGPCQRPGGWGYYFFHFFDVWTIDSAPDISVIKDRKKCMEQTADTISHVGLGTESTPKQIIAALLGDYGFLGCYNEL} \\
\midrule
\multirow[t]{2}{*}{ABCD1002} & A & 3 & \seqsplit{VMKCDPLWSDLFWTFNRMVKKKCDCARILFEVRVWISCQLMVSYLNWSIILEIRLIGEFSHGQQIWRLFNTKTDRWMVDEDGDNHFQRKVICFFNVRQDMPPNLFFTVWNDWMHTQTDH} \\
\cmidrule(l){2-4}
& B & 4 & \seqsplit{FRTWPHLAQESTRSITTLPRRISFMFCYDQYNEMRPACVICSDMVAYYILAPGKGAFTCEWVGRAVMNHHEHDMQMGEAIHRQEIYVHKDWDAI} \\
\midrule
\multirow[t]{2}{*}{ABCD1003} & A & 5 & \seqsplit{SIDYDEESNMPHDPQEEWWNTLPHQKYPLGCGQEDPWDYKNNIFRAYAWIYEWNHVKHDKTAIHTHVVKQAHCPNRHFFGFLCNLSQELMNSF} \\
\cmidrule(l){2-4}
& B & 6 & \seqsplit{EEDRYNFYVNWIADRFLVCKPEFWDAFLYKKLWCFATNSKAFGETDCYKDAWYYFIHPEEKMSDQATWEAGIMNWLQEQTMVQQQTDCISA} \\
\midrule
\multirow[t]{2}{*}{ABCD1004} & A & 7 & \seqsplit{AYRIGEDGRFRQGRDKINKYDRATHFLQYHGRTVWRWHQYEKVYTFIMAYVPGFQYCPDGVPYVNSRAKYHKGVWCCDIQWVQEACEWSGFCLNARTCACCRHRGSDVVQASK} \\
\cmidrule(l){2-4}
& B & 8 & \seqsplit{NGLGSNQQVVSVGMNMLCFFKPFFGHNAGGYDVQAVHVWSDLDIHTDGDWHNNSCMTSIVDAPQTPHLMWNAPKWNIAWPVPPVNGYTIFKPHSKTIMAKNVEGEQECVHFKNQA} \\
\midrule
\multirow[t]{2}{*}{ABCD1005} & A & 9 & \seqsplit{FNFHFPQDPYHGEGTGPDDVMWKEKSLPTPIWVLWKIEYNVVAHCLRGSPNYNNADRGDCCHAFQNHKEIWQDAITIFENGWCSCIDKCAQSVDIPIDHQEQCNKMQHCDAAME} \\
\cmidrule(l){2-4}
& B & 10 & \seqsplit{CCIYPFWIACCHCFELTAEQFSFCYGVQHVYHPEYSDKLCNNQFFSSILNRHYIPYAAGGWEQAMVVCKLFQPVMVKKWNTDFSHADCR} \\
\midrule
\multirow[t]{2}{*}{ABCD1006} & A & 11 & \seqsplit{KPIPQESQYAWLVNLVTMCCAGRAWSLAERMHFYCQMSSIGAHPGHVRGGRWEAEIIQNHGENLHRTDRVAFKMTYPTKFCRYVITQFMMQQWLQHNPYQGMIMHIIVGVRSNTILE} \\
% Uncommenting the line below results in a xelatex compilation error
% \nopagebreak
\cmidrule(l){2-4}
& B & 12 & \seqsplit{IWCTCISSPDKWWEDPKLYSYNWHKVAIMLGYFASVMFCIYQSCYIIAMLRMNPFRCWNSWVDVCIIQGYGCSKKQDVKDFEHLQYGNFIETVR} \\
\midrule
\multirow[t]{2}{*}{ABCD1007} & A & 13 & \seqsplit{NDAEWKGALINLVGMESQWKNRHGDYYGYAGRVYIPCNAQFVCWCNDLHEMVYNTMGPPCIPHMGISERSWFSCQNDVHRYGPAHVDRSVCVRFMEHVDHSVMKLVPHELTSSGI} \\
\cmidrule(l){2-4}
& B & 14 & \seqsplit{YHQQACAYPSYRFTSWNCEDAKYEKKIQWVAKTQFFGWPTPFMSDNPGEQDSKTLMFIRMPYPGEYFNQNRQNSGQLQRDQYGRWNCQKDYYMQNCFCT} \\
\bottomrule
\end{xtabular}
\end{center}
\end{document}


Ideally, I'd like to simply suppress page breaks systematically before all midline rules (thereby forcing the break to take place immediately after the next midline rule), however, when I actually tried this inside of xtab using the \nopagebreak command, it resulted in an error message.

My question: What other penalization techniques can I use inside of xtab, besides \nopagebreak, to force line breaks to always occur after a midline rule instead of before?

Also, before answering, please note that a highly specific inverse solution, in which I force a line break to take place at a very particular location, is not desirable. As I said at the beginning, I have dozens of tables to contend with, and I'd still like xelatex to do most of my thinking for me--I don't want to have to make fussy hand corrections to dozens of tables; rather I'd just like to influence the page break-related scoring system a bit, at a fairly high level. It occurs to me, for example, that a good solution might be to simply redefine the \midrule and \cmidrule commands from booktabs so that these commands themselves somehow tell xelatex that they prefer to be page-broken after they are printed rather than before. However, I have no idea how one would actually go about doing something like this.

• I am pretty much a beginner, but did you tried the longtable package? Why did you ruled it out? Out of my experience, if you are opened to try different package, there is also tabu package. One of them might have different algorithm, that would not act like that. I am using mostly longtable (tabu is not maintained) and it has never done anything similar to what you are experiencing. Might be related: tex.stackexchange.com/questions/110548/… – Tomáš Kruliš Oct 23 '19 at 20:31
• I haven't ruled out the longtable package yet, nor other options such as supertabular. If someone with more experience than me were able to suggest a fix which substitutes one of these alternative options in place of the xtab package, I would gladly consider it. However, the xtab is already very close to producing the output that I want, so I was hoping someone who understands TeX's pagebreak scoring system might see this, and be able to suggest a trivial tweak. – stachyra Oct 24 '19 at 16:16
• @TomášKruliš: O.K., good call; thanks for your advice. The longtable package does seem to be a viable alternative that fixes the issue. Nevertheless, I still think it would be instructive to see how this could have been solved using xtabinstead, as I had initially anticipated when I posed the question. – stachyra Oct 24 '19 at 17:44
• Glad to help. Helping with xtab is way beyond my latex skills; I never even heard of this package. Just as final addition, xtab looks to be superseding supertabular, which was also superseded by longtable... Longtable is pretty much widely used (in my knowledge there is not much of a replacement exacept ltablex, which still loads longtable internally), so it is more likely to get help if something goes not as expected ... – Tomáš Kruliš Oct 24 '19 at 18:23

Based upon a comment by user Tomáš Kruliš, I tried substituting the longtable package in place of xtab, and that does indeed seem to have fixed the issue. A revised MWE and its resulting output are posted below:

% Basic document setup
\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\geometry{letterpaper}
\usepackage{fontspec}
\setmainfont{Tinos}

% Table-specific setup
\usepackage{longtable} % Needed for multi-page tables
\usepackage{multirow}  % Needed because some cells span 2 rows
\usepackage{booktabs}  % Improves appearance of horizontal lines and rules
\newcommand{\otoprule }{\midrule[\heavyrulewidth]}
\usepackage{seqsplit}  % Needed for line breaking amino acid sequences
\usepackage{siunitx}   % Needed for aligning numbers in columns
\sisetup{
table-format = 2.2
}

\begin{document}
\begin{center}
% Begin actual table body
\begin{longtable}{lcS[table-number-alignment = right]p{0.6\textwidth}}
\toprule Name & Type & {ID Number} & Amino Acid Sequences \\ \otoprule \endhead
\multirow[t]{2}{*}{ABCD1001} & A & 1 & \seqsplit{CVPCYFWIIQMADNYCCYFMSRMCRPVFMTGHKWWANNQCVERSVTHKDFGRANAAFAKAYTGRNYHCNYKRYWYNNATQYPHMAEWHT} \\
\cmidrule(l){2-4}
& B & 2 & \seqsplit{AAWLYALGCQTDVYDISKYIQCGLEYRIGPCQRPGGWGYYFFHFFDVWTIDSAPDISVIKDRKKCMEQTADTISHVGLGTESTPKQIIAALLGDYGFLGCYNEL} \\
\midrule
\multirow[t]{2}{*}{ABCD1002} & A & 3 & \seqsplit{VMKCDPLWSDLFWTFNRMVKKKCDCARILFEVRVWISCQLMVSYLNWSIILEIRLIGEFSHGQQIWRLFNTKTDRWMVDEDGDNHFQRKVICFFNVRQDMPPNLFFTVWNDWMHTQTDH} \\
\cmidrule(l){2-4}
& B & 4 & \seqsplit{FRTWPHLAQESTRSITTLPRRISFMFCYDQYNEMRPACVICSDMVAYYILAPGKGAFTCEWVGRAVMNHHEHDMQMGEAIHRQEIYVHKDWDAI} \\
\midrule
\multirow[t]{2}{*}{ABCD1003} & A & 5 & \seqsplit{SIDYDEESNMPHDPQEEWWNTLPHQKYPLGCGQEDPWDYKNNIFRAYAWIYEWNHVKHDKTAIHTHVVKQAHCPNRHFFGFLCNLSQELMNSF} \\
\cmidrule(l){2-4}
& B & 6 & \seqsplit{EEDRYNFYVNWIADRFLVCKPEFWDAFLYKKLWCFATNSKAFGETDCYKDAWYYFIHPEEKMSDQATWEAGIMNWLQEQTMVQQQTDCISA} \\
\midrule
\multirow[t]{2}{*}{ABCD1004} & A & 7 & \seqsplit{AYRIGEDGRFRQGRDKINKYDRATHFLQYHGRTVWRWHQYEKVYTFIMAYVPGFQYCPDGVPYVNSRAKYHKGVWCCDIQWVQEACEWSGFCLNARTCACCRHRGSDVVQASK} \\
\cmidrule(l){2-4}
& B & 8 & \seqsplit{NGLGSNQQVVSVGMNMLCFFKPFFGHNAGGYDVQAVHVWSDLDIHTDGDWHNNSCMTSIVDAPQTPHLMWNAPKWNIAWPVPPVNGYTIFKPHSKTIMAKNVEGEQECVHFKNQA} \\
\midrule
\multirow[t]{2}{*}{ABCD1005} & A & 9 & \seqsplit{FNFHFPQDPYHGEGTGPDDVMWKEKSLPTPIWVLWKIEYNVVAHCLRGSPNYNNADRGDCCHAFQNHKEIWQDAITIFENGWCSCIDKCAQSVDIPIDHQEQCNKMQHCDAAME} \\
\cmidrule(l){2-4}
& B & 10 & \seqsplit{CCIYPFWIACCHCFELTAEQFSFCYGVQHVYHPEYSDKLCNNQFFSSILNRHYIPYAAGGWEQAMVVCKLFQPVMVKKWNTDFSHADCR} \\
\midrule
\multirow[t]{2}{*}{ABCD1006} & A & 11 & \seqsplit{KPIPQESQYAWLVNLVTMCCAGRAWSLAERMHFYCQMSSIGAHPGHVRGGRWEAEIIQNHGENLHRTDRVAFKMTYPTKFCRYVITQFMMQQWLQHNPYQGMIMHIIVGVRSNTILE} \\
% Uncommenting the line below results in a xelatex compilation error
% \nopagebreak
\cmidrule(l){2-4}
& B & 12 & \seqsplit{IWCTCISSPDKWWEDPKLYSYNWHKVAIMLGYFASVMFCIYQSCYIIAMLRMNPFRCWNSWVDVCIIQGYGCSKKQDVKDFEHLQYGNFIETVR} \\
\midrule
\multirow[t]{2}{*}{ABCD1007} & A & 13 & \seqsplit{NDAEWKGALINLVGMESQWKNRHGDYYGYAGRVYIPCNAQFVCWCNDLHEMVYNTMGPPCIPHMGISERSWFSCQNDVHRYGPAHVDRSVCVRFMEHVDHSVMKLVPHELTSSGI} \\
\cmidrule(l){2-4}
& B & 14 & \seqsplit{YHQQACAYPSYRFTSWNCEDAKYEKKIQWVAKTQFFGWPTPFMSDNPGEQDSKTLMFIRMPYPGEYFNQNRQNSGQLQRDQYGRWNCQKDYYMQNCFCT} \\
\bottomrule
\end{longtable}
\end{center}
\end{document}


Nevertheless, in spite of this, I would still be very interested to see (and would gladly upvote, and potentially award "preferred answer" status) a response that is able to solve this by using xtab, and modifying its pagebreak scoring system.