TransWikia.com

environment to balance a table in a multicol

TeX - LaTeX Asked by Michael Teresi on August 14, 2020

environment to balance a table in a multicol

I’d like an environment that balances a table in a multicol environment.

By this I mean I’d like to have potentially long tabular-like data
that automatically breaks to another column of a roughly equal number of rows.

like so, automatically breaking after row 3, for a 2 column tabular, into a 2 column multicol
(artist’s rendition)

lipsum lipsum lipsum lipsum lipsum

    row1 col2        row4 col2
    row2 col2        row5 col2
    row3 col2

lipsum lipsum lipsum lipsum lipsum

Additionally, I was looking to use xparse and a multicol to do this,
in order to pass the number of columns to use through the custom environment down to multicols.

Additionally, I was looking to use the book class and showframe package.

I’ve tried two solutions:

solution A, long table

This answer produces the correct output but not when I wrap it in an environment:

Balancing long table inside multicol in LaTeX

I’ve tried two fixes:

solution A, fix 1: replace the vbox{ and } with bgroupand egroup

Attempt no. 1 results in misaligned columns, and these errors:

  • Undefined control sequence. begin{myenvironment}
  • Package longtable Error: longtable not in 1-column mode.
  • Undefined control sequence. end{myenvironment}
  • misaligned columns
  • @numberne appears in the columns

solution 1, attempt 1

documentclass[]{book}
usepackage{showframe}
usepackage[]{geometry}
usepackage{longtable}
usepackage{multicol}
usepackage{xparse}

newsaveboxltmcbox

defshortlipsum{par Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis.par}

newcounter{entryno}
setcounter{entryno}{1}
deftabline{Test & thevalue{entryno} & Descriptionaddtocounter{entryno}{1}}
deftablines{tablinetablinetablinetablinetabline}

NewDocumentEnvironment{myenvironment}{O{2}}
{
    begin{multicols}{#1}
    setboxltmcboxvboxbgroup
    makeatlettercol@number@ne
    begin{longtable}{|l|l|l|}
}
{
    makeatlettercol@number@ne
    end{longtable}
    unskip
    unpenalty
    unpenalty
    egroupunvboxltmcbox
    end{multicols}
}

begin{document}

This works great!
shortlipsum
begin{multicols}{2}
    shortlipsum
    medskip
    setboxltmcboxvbox{
        makeatlettercol@number@ne
        begin{longtable}{|l|l|l|}
            tablinestablinestablinestablinestablinestablines
        end{longtable}
        unskip
        unpenalty
        unpenalty
    }
    unvboxltmcbox
    medskip
    shortlipsum
end{multicols}

shortlipsum
par

This does not work!
begin{myenvironment}
tablinestablinestablinestablinestablinestablines
end{myenvironment}
shortlipsum

end{document}

solution A, fix 2: replace the vbox{ and } with begingroup and endgroup

Attempt no. 2 results in a loss of output past the first shortlipsum and:

  • Missing { inserted. begin{myenvironment}
  • Undefined control sequence. begin{myenvironment}
  • Package longtable Error: longtable not in 1-column mode.
  • Undefined control sequence. end{myenvironment}
  • Missing } inserted. end{myenvironment}

enter image description here

documentclass[]{book}
usepackage{showframe}
usepackage[]{geometry}
usepackage{longtable}
usepackage{multicol}
usepackage{xparse}

newsaveboxltmcbox

defshortlipsum{par Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis.par}

newcounter{entryno}
setcounter{entryno}{1}
deftabline{Test & thevalue{entryno} & Descriptionaddtocounter{entryno}{1}}
deftablines{tablinetablinetablinetablinetabline}

NewDocumentEnvironment{myenvironment}{O{2}}
{
    begin{multicols}{#1}
    setboxltmcboxvboxbegingroup
    makeatlettercol@number@ne
    begin{longtable}{|l|l|l|}
}
{
    makeatlettercol@number@ne
    end{longtable}
    unskip
    unpenalty
    unpenalty
    endgroupunvboxltmcbox
    end{multicols}
}

begin{document}

This works great!
shortlipsum
begin{multicols}{2}
    shortlipsum
    medskip
    setboxltmcboxvbox{
        makeatlettercol@number@ne
        begin{longtable}{|l|l|l|}
            tablinestablinestablinestablinestablinestablines
        end{longtable}
        unskip
        unpenalty
        unpenalty
    }
    unvboxltmcbox
    medskip
    shortlipsum
end{multicols}

shortlipsum
par

This does not work!
begin{myenvironment}
tablinestablinestablinestablinestablinestablines
end{myenvironment}
shortlipsum

end{document}

solution B, pseudo-nested longtable w/ savebox

This answer also produces what I want, but I couldn’t get it to align with the text.

balanced longtables, multicol and page breaks

I’ve tried:

solution B, fix 1: wrap the commands in an env and remove the table, and that works great!

enter image description here

However…

That works great until I add the showframe package and I get:

  • Missing } inserted. begin{myenvironment}3
  • Extra }, or forgotten endgroup{myenvironment}
  • added space under the longtable

enter image description here

documentclass[]{book}
%usepackage{showframe}
usepackage{longtable}
usepackage{multicol}
usepackage{lipsum}
usepackage{capt-of}
usepackage{xparse}

defshortlipsum{par Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis.par}

newcounter{entryno}
setcounter{entryno}{1}
deftabline{Test & thevalue{entryno} & Descriptionaddtocounter{entryno}{1}}
deftablines{tablinetablinetablinetablinetabline}

makeatletter
newsaveboxltmcbox
newsaveboxxxbox
newenvironment{multicolslongtable}[1]{
    setboxltmcboxvboxbgroup
    col@number@ne
    begin{longtable}{#1}
}
{
    end{longtable}
    unskip
    unpenalty
    unpenaltyegroup
    unvboxltmcbox
}
makeatother

NewDocumentEnvironment{myenvironment}{O{2}}
{
    saveboxxxboxbgroup
    begin{minipage}{textwidth}
    begin{multicols}{#1}
    begin{multicolslongtable}{| l | l | l |}
}
{
    end{multicolslongtable}
    end{multicols}
    end{minipage}
    egroup
    begin{multicols}{#1}
        useboxxxbox
    end{multicols}
}


begin{document}

shortlipsum

begin{myenvironment}[2]
tablinestablinestablinestablinestablinestablines
end{myenvironment}

shortlipsum

end{document}

One Answer

The fix was to use the showframe option from geometry package instead of the showframe package.

Thank you AboAmmar!

The code below shows an environment that balances tabular data using a longtable in a multicol (with showframe), by combining the following answers, xparse, and minor refactoring:

enter image description here

% environment to balance a table in a multicol

documentclass[]{book}
usepackage[showframe]{geometry}
usepackage{longtable}
usepackage{multicol}
usepackage{lipsum}
usepackage{xparse}


% helpers for the test
defshortlipsum{par Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis.par}
newcounter{entryno}
setcounter{entryno}{1}
deftabline{Test & thevalue{entryno} & Descriptionaddtocounter{entryno}{1}}
deftablines{tablinetablinetablinetablinetablinetablinetablinetablinetabline}


% box for a multi column long table
% SEE https://tex.stackexchange.com/questions/161827/balanced-longtables-multicol-and-page-breaks
makeatletter
newsaveboxltmcbox
newsaveboxxxbox
newenvironment{multicolslongtable}[1]{
    setboxltmcboxvboxbgroup
    col@number@ne
    begin{longtable}{#1}
}
{
    end{longtable}
    unskip
    unpenalty
    unpenaltyegroup
    unvboxltmcbox
}
makeatother


% environment to accept table input and produce multicol
NewDocumentEnvironment{myenvironment}{O{2}}
{
    saveboxxxboxbgroup
    begin{minipage}{textwidth}
    begin{multicols}{#1}
    begin{multicolslongtable}{| l | l | l |}
}
{
    end{multicolslongtable}
    end{multicols}
    end{minipage}
    egroup
    begin{multicols}{#1}
        centering
        useboxxxbox
    end{multicols}
}


% patch multicols to allow for one column
% SEE https://tex.stackexchange.com/questions/233866/one-column-multicol-environment
letmulticolmulticolsmulticols
letendmulticolmulticolsendmulticols
RenewDocumentEnvironment{multicols}{mO{}}
{%
    ifnum#1=1
    #2%
    else % More than 1 column
    multicolmulticols{#1}[#2]
    fi
}
{%
    ifnum#1=1
    else % More than 1 column
    endmulticolmulticols
    fi
}


begin{document}

section{one column}
shortlipsum
begin{myenvironment}[1]
tablines
end{myenvironment}
shortlipsum

section{two column}
shortlipsum
begin{myenvironment}
    tablines
end{myenvironment}
shortlipsum

section{three column}
shortlipsum
begin{myenvironment}[3]
    tablines
end{myenvironment}
shortlipsum

end{document}

Answered by Michael Teresi on August 14, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP