# How to use arguments passed to a custom environment in the end code of the environment? [duplicate]

This question already has an answer here:

I want to save some typing when I use a comon style for my tables.

But because \caption and \label have to be used inside the float, I want to pass the values for these macros via arguments into my envrionment.

I want to keep these inside the end code of my environment, to easily keep the caption at the bottom of the table.

Here is the MWE to my problem:

\documentclass[
fontsize=12pt,
a4paper
]{scrreprt}

\newenvironment{bordertab}[2]
{
\begin{table}
\centering
\begin{tabular}{| l c r |}
\hline
}
{
\hline
\end{tabular}
\caption{#1}
\label{tab:b:#2}
\end{table}
}

\begin{document}
\begin{bordertab}{A table with a border}{ex1}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{bordertab}
\end{document}


and the errors which LaTeX throws at me when using it:

! Illegal parameter number in definition of \reserved@a.
<to be read again>
1
l.28 ^^I\end{bordertab}

You meant to type ## instead of #, right?
Or maybe a } was forgotten somewhere earlier, and things
are all screwed up? I'm going to assume that you meant ##.

! You can't use macro parameter character #' in restricted horizontal mode.
<argument> \ignorespaces ##
1
l.28 ^^I\end{bordertab}

Sorry, but I'm not programmed to handle this case;
I'll just pretend that you didn't ask for it.
If you're in the wrong mode, you might be able to
return to the right one by typing I}' or I$' or I\par'. ! You can't use macro parameter character #' in restricted horizontal mode. <argument> \ignorespaces ## 1 l.28 ^^I\end{bordertab} Sorry, but I'm not programmed to handle this case; I'll just pretend that you didn't ask for it. If you're in the wrong mode, you might be able to return to the right one by typing I}' or I$' or I\par'.

! Illegal parameter number in definition of \reserved@a.
<to be read again>
2
l.28 ^^I\end{bordertab}

You meant to type ## instead of #, right?
Or maybe a } was forgotten somewhere earlier, and things
are all screwed up? I'm going to assume that you meant ##.


## marked as duplicate by Werner tables StackExchange.ready(function() { if (StackExchange.options.isMobile) return; $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() { var$hover = $(this).addClass('hover-bound'),$msg = $hover.siblings('.dupe-hammer-message');$hover.hover( function() { $hover.showInfoMessage('', { messageElement:$msg.clone().show(), transient: false, position: { my: 'bottom left', at: 'top center', offsetTop: -7 }, dismissable: false, relativeToBody: true }); }, function() { StackExchange.helpers.removeMessages(); } ); }); }); Dec 14 '16 at 15:34

• Doing this, you'll most likely lose the autocomplete labels functionality. I would recommend you pass the whole \label in the second argument (in order to keep this functionality, if you care about it, of course...). – Guilherme Zanotelli Dec 14 '16 at 14:38
• Thanks for the hint @GuilhermeZanotelli, I do care about this functionality. – Luca Dec 14 '16 at 14:57

Save the values in macros, which you then can use at the end of the environment.

\documentclass[
fontsize=12pt,
a4paper
]{scrreprt}

\newcommand\bordertabA{} % make sure \bordertabA is not in use.
\newcommand\bordertabB{} % make sure \bordertabB is not in use.
\newenvironment{bordertab}[2]
{\def\bordertabA{#1}%
\def\bordertabB{#2}%
\begin{table}
\centering
\begin{tabular}{| l c r |}
\hline
}
{
\hline
\end{tabular}
\caption{\bordertabA}
\label{tab:b:\bordertabB}
\end{table}
}

\begin{document}
\begin{bordertab}{A table with a border}{ex1}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{bordertab}
\end{document}


Passing the arguments via macros is necessary because a definition

\newenvironment{myenv}[n]{begin code}{end code}


is roughly equivalent to the definitions

\newcommand\myenv[n]{begin code}
\newcommand\endmyenv{end code}


So the arguments are only available to the begin code. Using #1 in the end code will lead to the error illegal parameter number as observed, since there are no parameters.

• Thank you very much, it works like a charm! Can you maybe also elaborate on why it needs to be done this way (i.e. why \caption doen't play along with #1)? – Luca Dec 14 '16 at 14:49
• @Luca I've added an explanation. – gernot Dec 14 '16 at 15:16
• Thank you very much, I have updated my question to better reflect the real cause/problem. – Luca Dec 14 '16 at 15:32

The problem is not with the \caption or the \label commands receiving # arguments. The Problem is that when you specify an Environment with arguments, the # have to be on the <begin> part of this Environment:

 \newenvironment{myenv}[1]{here goes #1}{no #1's here!!}


In light of this fact you can just put the caption on top:

\newenvironment{bordertab}[2]
{
\begin{table}
\centering
\caption{#1}
\label{tab:b:#2}
\begin{tabular}{| l c r |}
\hline
}
{
\hline
\end{tabular}
\end{table}
}


Of course this has the disadvantage of having the caption on top, when it's wished to be on the bottom. To overcome this, one can use the very useful package floatrow and set all table floats to be on the bottom, additionaly, we can set an optional Parameter for bordertab, to reset the position to the top part. Also, floatrow sets all floats to \centering out-of-the-box, so that's no longer needed.

\documentclass[
fontsize=12pt,
a4paper
]{scrreprt}

\usepackage{floatrow}

\newenvironment{bordertab}[3][top]
{\floatsetup[table]{capposition=#1}
\begin{table}
\caption{#2}
\label{tab:b:#3}
\begin{tabular}{| l c r |}
\hline
}
{
\hline
\end{tabular}
\end{table}
}

\begin{document}
\begin{bordertab}{A table with a border}{ex1}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{bordertab}

\begin{bordertab}[bottom]{A tabl}{ex2}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{bordertab}
\end{document}

• Thank you for your helpful explanation and additional solution. (Altough I somehow like @gernot's solution a bit more.) – Luca Dec 14 '16 at 15:28