Many years ago, Barbara Beeton gave me the most valuable piece of advice
I have ever had about TeX: when possible, let paragraph-mode do it for you.
Repeated blocks in this format over many pages are sometimes best done
as boxes.
///Peter
\documentclass{article}
\usepackage{multicol,array,calc}
\newlength{\shoulder}
\newlength{\rulesize}
\newlength{\qty}
\newlength{\price}
\newlength{\desc}
\newenvironment{pricelist}[1][99.00]{%
\begin{multicols*}{2}%
\setlength{\shoulder}{\fboxsep}%
\setlength{\rulesize}{\fboxrule}%
\settowidth{\qty}{Qty}\addtolength{\qty}{2\shoulder}%
\settowidth{\price}{#1}\addtolength{\price}{2\shoulder}%
\setlength{\desc}{\columnwidth - \qty - \price - 4\rulesize}%
\parindent0pt
\offinterlineskip
\raggedright
}{%
\par\hrule height\rulesize\end{multicols*}%
}
\def\strut{\vrule height1.1em depth.666ex width0pt}
\makeatletter
\newcommand{\entry}[3][\relax]{%
\vbox{%
\hrule height\rulesize
\hbox to\columnwidth{%
\vrule width\rulesize
\hbox to\qty{\hfil#1\hfil}%
\vrule width\rulesize
\hbox to\desc{\hspace{\shoulder}%
\vbox{\hsize\desc\advance\hsize by-2\shoulder
\fontsize{\f@size}{\f@size}\selectfont
\raggedright\strut#2\strut\par}%
\hfil}%
\vrule width\rulesize
\hbox to\price{\hfil#3\hspace{\shoulder}}%
\vrule width\rulesize
}%
}\ignorespaces
}
\makeatother
\newcommand{\heading}[3]{%
\entry[\textbf{#1}]{\textbf{#2}}{\textbf{#3}}%
}
\begin{document}
\section*{Price List}
\fboxsep6pt
\fboxrule1pt
\raggedcolumns
\begin{pricelist}[\textbf{Price}]
\heading{Qty}{Description}{Price}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\hrule height\rulesize\columnbreak
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\entry{Banana (bruised)}{0.23}
\entry{Cheese (stinky 200g)}{3.34}
\entry{Blue suede shoes}{27.00}
\end{pricelist}
\end{document}