4

What is a technique I might use to have TeX calculate the max height of a group of boxes and then typeset all boxes using that height?

I'd like to automatically have TeX detect the middle box and set its height to the maximum of its neighbors within a row (horizontally-aligned boxes). enter image description here

  • Each box has a static width specified under \makeform
  • Each box has a dynamic height specified under \makeform, because of the nature of \pars in \parbox i.e. boxes can grow vertically. A minimum height is specified for visual appearance when boxes are not vertically full.
  • Note that user could put anything in a box, even an itemized list.

Code

\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{tikz}

% I would have preferred to use plain tex boxes for speed, but I opted TikZ because of preexisting knowledge

\makeatletter % simulate start of package code
% Backend boxmaker
\long\def\ABC@box#1#2#3{\tikz\node
[draw, line width=.4pt, inner sep=2pt,outer sep=0pt,align=left,minimum width=#2,minimum height=#3]
{\parbox{\dimexpr#2-4pt}{\raggedright\scriptsize#1}};}

% User-level boxmaker
\long\def\nodebox#1#2#3{\ABC@box{#1}{#2}{#3}\kern-.4pt}% kern used to horizontally shift boxes back by stroke width of frame

\gdef\ABCMANUFACTURERCONTACTINFORMATION#1{\gdef\ABCMANUFACTURERCONTACTINFORMATION{#1}} % Sets backend macro value

% Common minimum height for nodes so that empty forms look visually appealing
\newdimen\nodeboxminHT
\nodeboxminHT=1cm\relax

% Create form
\gdef\makeform{%
\nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}%
\nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.7\textwidth}{\nodeboxminHT}% redundant for demo only
\nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}% redundant for demo only
}
\makeatother % simulate end of package code

\begin{document}
\ABCMANUFACTURERCONTACTINFORMATION{Highly-specialized Special Ops}
\makeform
\end{document}
  • tex at its most primitive level makes the height of an hbox the max height of its contents, can you omit the visible frames of the three inner boxes and just put an \fbox around the whole line? – David Carlisle Apr 25 '18 at 11:52
  • @DavidCarlisle The intent here is to use LaTeX to typeset cellular data from Excel, because it looks much better. I want to create a form similarly to how the U.S. Airforce does it tug.org/TUGboat/tb12-3-4/tb33roth.pdf . An \fbox surrounding the line would not yield the compartmentalized, cellular look of each field. (unless you have a better idea) – Jonathan Komar Apr 25 '18 at 11:55
  • the vertical lines are a detail \vline for example will draw a line as tall as the surrounding box. – David Carlisle Apr 25 '18 at 12:54
  • @DavidCarlisle I am considering that option. It is certainly efficient to utilize existing TeX boxes, however, sometimes I have vertically stacked boxes within a single row. I'd have to occassionally implement something like \hline. I realize that this is not in my minimal example. – Jonathan Komar Apr 25 '18 at 13:16
  • That looks like a table. Why don't you use one? – Martin Schröder Apr 26 '18 at 22:41
2

If you can switch from TikZ to tcolorbox, then here's a solution based on this answer.

tcolorbox has an option equal height group, which allows you to group a bundle of boxes an make them all have the same height. You just have to make sure that boxes that must have the same height have the same group.

I redefined your \ABC@box macro to use tcolorbox instead of TikZ, then I put a fourth argument to the box-making macro, the group to which the box belongs.

enter image description here

I guess that a "Plain" approach would require saving the boxes in temporary registers, measuring them up, then writing them.

\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{tikz}

\usepackage[xparse]{tcolorbox}

% I would have preferred to use plain tex boxes for speed, but I opted TikZ because of preexisting knowledge

\makeatletter % simulate start of package code
% Backend boxmaker
\NewTotalTColorBox{\ABC@box}{+mmmm}{%
  size=fbox,
  sharp corners,
  colframe=black,
  colback=white,
  width=#2,
  height=#3,
  height plus=0pt plus 1fil,
  nobeforeafter,
  valign=center,
  equal height group=#4%
  }{#1}

% User-level boxmaker
\long\def\nodebox#1#2#3#4{\ABC@box{#1}{#2}{#3}{#4}\kern-.4pt}% kern used to horizontally shift boxes back by stroke width of frame

\gdef\ABCMANUFACTURERCONTACTINFORMATION#1{\gdef\ABCMANUFACTURERCONTACTINFORMATION{#1}} % Sets backend macro value

% Common minimum height for nodes so that empty forms look visually appealing
\newdimen\nodeboxminHT
\nodeboxminHT=1cm\relax

% Create form
\gdef\makeform#1{%
\nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.25\textwidth}{\nodeboxminHT}{#1}%
\nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{ .5\textwidth}{\nodeboxminHT}{#1}% redundant for demo only
\nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.25\textwidth}{\nodeboxminHT}{#1}% redundant for demo only
}
\makeatother % simulate end of package code

\begin{document}
\ABCMANUFACTURERCONTACTINFORMATION{Highly-specialized Special Ops}
\noindent\makeform{group1}

\bigskip

\gdef\ABCMANUFACTURERCONTACTINFORMATION{Less content}
\noindent\makeform{group2}

\bigskip

\gdef\ABCMANUFACTURERCONTACTINFORMATION{Lorem ipsum dolor sit amet, consectetuer
  adipiscing elit. I don't remember the rest but didn't want to load a package.}
\noindent\makeform{group3}
\end{document}
  • 2
    I really did not want to use tcolorbox :D But cool answer nonetheless! Unexpected... Just for info, my intent would be to call \makeform once in a document and have ALL of the rows of boxes typeset. – Jonathan Komar Apr 25 '18 at 12:51
0

Here is a technique that first typesets everything in a TeX register box (that never gets printed) by way of a LaTeX temporary box \@tempboxa. The maximum height is calculated and finally actually typeset.

I could have used a TeX token register, but I used \BODY from the environ package for convenience.

Code

I added a few lines of code to try different situations. I also overlap the rows of boxes by kerning the line skip by one frame stroke width (5pt).

\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{tikz}
\usepackage{environ}

% I would have preferred to use plain tex boxes for speed, but I opted TikZ because of preexisting knowledge

\makeatletter % simulate start of package code
% Backend boxmaker
\long\def\ABC@box#1#2#3{\tikz\node
[draw, line width=.4pt, inner sep=2pt,outer sep=0pt,align=left,minimum width=#2,minimum height=#3]
{\parbox{\dimexpr#2-4pt}{\raggedright\scriptsize#1}};}

% User-level boxmaker
\long\def\nodebox#1#2#3{\ABC@box{#1}{#2}{#3}\kern-.4pt}% kern used to horizontally shift boxes back by stroke width of frame

\gdef\ABCMANUFACTURERCONTACTINFORMATION#1{\gdef\ABCMANUFACTURERCONTACTINFORMATION{#1}} % Sets backend macro value

% Common minimum height for nodes so that empty forms look visually appealing
\newdimen\nodeboxminHT
\nodeboxminHT=1cm\relax

\NewEnviron{formrow}{\leavevmode\unskip\par\sbox\@tempboxa{\BODY}\nodeboxminHT=\the\ht\@tempboxa\BODY\ignorespaces}

% Create form
\gdef\makeform{%
  \parskip=0pt\relax
  \baselineskip=0ex\relax
  \lineskip=-.5pt\relax

  \begin{formrow}%
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}%
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.7\textwidth}{\nodeboxminHT}% redundant for demo only
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}% redundant for demo only
  \end{formrow}

  \begin{formrow}
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}%
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.7\textwidth}{\nodeboxminHT}% redundant for demo only
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}% redundant for demo only
  \end{formrow}
  \begin{formrow}
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}%
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.7\textwidth}{\nodeboxminHT}% redundant for demo only
    \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}% redundant for demo only
  \end{formrow}

  \begin{formrow}
  \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}%
  \hbox{\vbox{
    \hbox{\nodebox{Company Name}{.7\textwidth}{.5\nodeboxminHT}}%
    \hbox{\nodebox{Representative Name/Position}{.7\textwidth}{.5\nodeboxminHT}}%
  }}%
  \nodebox{Manufacturer Information\\\ABCMANUFACTURERCONTACTINFORMATION{}}{.2\textwidth}{\nodeboxminHT}% redundant for demo only
  \end{formrow}
  \begin{formrow}
    \nodebox{}{.2\textwidth}{\nodeboxminHT}% test empy node appearance
    \nodebox{}{.7\textwidth}{\nodeboxminHT}% test empy node appearance
    \nodebox{}{.2\textwidth}{\nodeboxminHT}% test empy node appearance
  \end{formrow}
}
\makeatother % simulate end of package code

\ABCMANUFACTURERCONTACTINFORMATION{Highly-specialized Special Ops}

\begin{document}
\makeform
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.