4

I would like to save data to a savebox (or any other storage element) in iterations. At the end I would like to put each datapoint in a framebox and then in a frambox container with a given width. Here is my implementation:

\documentclass{article}

\newsavebox{\foo}
\newcommand{\savedata}[1]{\savebox{\foo}{\usebox{\foo} \fbox{#1}}}
\newcommand{\printdata}{\framebox{\parbox{4cm}{\usebox{\foo}}}}
\begin{document}
The desired usage:
\savedata{This is a box}
\savedata{This is another box}
\savedata{This is third box}
\printdata
\\
The desired output:
\framebox{\parbox{4cm}{
  \fbox{This is a box} 
  \fbox{This is another box} 
  \fbox{This is third box}}}
\end{document}

Output:
Output As seen does the container not wrap the inner framebox when using the programmatic implementation. What is wrong?

1
  • you are adding stuff outside a parbox when you are saving. Then everything is locked in place. Add the \parbox to the save instead
    – daleif
    Sep 24, 2014 at 11:49

3 Answers 3

5

You want raggedright to allow the lines to be short and need to unbox the saved data to allow linebreaking:

\documentclass{article}

\newsavebox{\foo}
\newcommand{\savedata}[1]{\savebox{\foo}{\ifvoid\foo\else\unhbox\foo{} \fi\fbox{#1}}}
\newcommand{\printdata}{\framebox{\parbox{4cm}{\raggedright\unhbox\foo}}}
\begin{document}
The desired usage:
\savedata{This is a box}
\savedata{This is another box}
\printdata

The desired output:
\framebox{\parbox{4cm}{\raggedright\fbox{This is a box} \fbox{This is another box}}}
\end{document}
2
  • If the \savedata are short words then more boxes occurs at the same line (like words in a paragraph). Is it desired?
    – wipet
    Sep 29, 2014 at 11:38
  • @wipet My guess was that was the intention, and I got the tick so I assume my guess was right:-) Sep 29, 2014 at 11:41
3

I'm not sure you want to use boxes:

\documentclass{article}

\usepackage{etoolbox}
\newcommand{\cleardata}{\renewcommand*{\saveddata}{}}
\newcommand*\saveddata{} % initialize

\newcommand{\savedata}[1]{%
  \unskip
  \ifx\saveddata\empty
  \else
    \appto{\saveddata}{\\}
  \fi
  \appto{\saveddata}{\fbox{#1}}\ignorespaces
}
\newcommand{\printdata}[1][4cm]{\fbox{\parbox{#1}{\raggedright\saveddata}}}

\begin{document}
The desired usage:
\savedata{This is a box}
\savedata{This is another box}
\savedata{This is third box}
\printdata

The desired output:
\framebox{\parbox{4cm}{
  \fbox{This is a box} \\
  \fbox{This is another box} \\
  \fbox{This is third box}}}

With optional argument: \printdata[6cm]
\end{document}

The command \cleardata resets the mechanism for adding new boxes.

enter image description here

Here I used etoolbox for convenience. You can avoid it by defining \appto yourself:

\makeatletter
\providecommand\appto[2]{%
  \ifx#1\@undefined
    \def#1{#2}%
  \else
    \expandafter\def\expandafter#1\expandafter{#1#2}%
  \fi
}
\makeatother
2
  • Thanks for the answer. I would like to not include any packages. Therefore I prefer boxes. Sep 29, 2014 at 9:47
  • @TorsteinI.Bø etoolbox is just for convenience. You can dispense with it. I'll add a note.
    – egreg
    Sep 29, 2014 at 10:01
1

Are you sure that you need 4cm width of the completed box? Isn't better to set this width as the width of the most wide box inside? If so, then you can use:

\newbox\foo
\def\savedata#1{\setbox\foo=\vbox{\unvbox\foo \hbox{\fbox{#1}}\kern1pt}\ignorespaces}
\def\printdata{\framebox{$\vcenter{\box\foo\kern-1pt}$}}
3
  • For my case, the width is fixed to the linewidth. Sep 29, 2014 at 9:48
  • @TorsteinI.Bø This is impossible. You have the text before box "The desired output:" The width of the box plus the width of this text have to be less than linewidth. And there is ugly white space at the right side in the box.
    – wipet
    Sep 29, 2014 at 9:59
  • I know, but this is a minimal example. So I have done some simplifications. Sep 29, 2014 at 12:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .