Leeres Enviroment

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


123DrivenHoliday
Forum-Newbie
Forum-Newbie
Beiträge: 4
Registriert: Di 10. Nov 2009, 10:39

Leeres Enviroment

Beitrag von 123DrivenHoliday »

Hallo,

der Code unten erzeugt den Feher "! Extra }, or forgotten \endgroup <template> \unskip \hfil } \hskip \tabcolsep \endtemplate " und ich versteh einfach nicht warum. Wahrscheinlich habe ich nur ne Kleinigkeit übersehen, wäre nett wenn mir jemand auf die Sprünge helfen könnte.

Code: Alles auswählen

\documentclass{article}

\begin{document}

\newenvironment{env}%
{%
}{%
}

\begin{tabular}{ccc}
	\begin{env}
		bla & bli & blubb \\
		bla & bli & blubb \\
		bla & bli & blubb \\
	\end{env}
\end{tabular}
	
\end{document}

Schweinebacke

Beitrag von Schweinebacke »

Wie bestimmt auch hier im Forum schon mehrfach zu lesen war, ist jede Zelle einer Tabelle eine eigene Gruppe. Du hast also im Endeffekt so etwas:

Code: Alles auswählen

{% Anfang der ersten Zelle der Tabelle
  \begin{env}
   bla
}% Ende der ersten Zelle der Tabelle
{bli}{blubb}
{bla}{bli}{blubb}% Zweite Tabellenzeile
{bla}{bli}{blubb}% Dritte Tabellenzeile
{% Anfang einer Zelle einer weiteren Tabellenzeile
  \end{env}
}
Wie Du sofort sehen solltest, stimmt also die Gruppenschachtelung nicht. Du musst also entweder jede einzelne Zelle in die Umgebung env-packen oder die gesamte Tabelle. Es geht hingegen nicht, dass Du mehrere Zellen einer Tabelle zusammen in eine Umgebung packst.

123DrivenHoliday
Forum-Newbie
Forum-Newbie
Beiträge: 4
Registriert: Di 10. Nov 2009, 10:39

Beitrag von 123DrivenHoliday »

Danke! Das ist gut zu wissen.

Jetzt ist die Frage wie ich mein Programm dann umsetzte. Ich würde gerne ein Script für eine Zeittabelle schreiben. Die Tabelle soll mehrere Phase beinhalten, die wiederum aus mehreren Vorgänge bestehen. In der Zeittabelle sollen dann die Gesamtstunden pro Phase ausgerechnet werden. Ich stelle mir die Benutzung etwa so vor:

Code: Alles auswählen

\begin{zeittabelle}
\begin{phase}{Vorbereitung}
\vorgang{Mehl holen}{2}
\vorgang{Eier kaufen}{1}
\end{phase}
\begin{phase}{Backen}
\vorgang{Mehl und Eier verrühren}{2}
\vorgang{Teig backen}{8}
\end{phase}
\begin{phase}{Servieren}
\vorgang{Kuchen glasieren}{2}
\vorgang{Kuchen schneiden}{1}
\end{phase}
\end{zeittabelle}
Es kann natürlich aus ganz anders aussehen, aber das war meine erste Idee. Wichtig ist, dass das Ergebnis wie das Dokument im Anhang aussieht.

Lässt sich sowas überhaupt umsetzten?
Dateianhänge
minevn.pdf
(18.76 KiB) 689-mal heruntergeladen

phi
Moderator
Moderator
Beiträge: 420
Registriert: Fr 6. Feb 2009, 21:28

Beitrag von phi »

Du musst die geöffnete Gruppe einfach gleich wieder schließen und umgekehrt sowie den Konsistenzcheck austricksen:

Code: Alles auswählen

\makeatletter
\newenvironment{env}{%
  \endgroup
  \ignorespaces
}{%
  \ignorespacesafterend
  \begingroup
  \def\@currenvir{env}%
}
\makeatother

Schweinebacke

Beitrag von Schweinebacke »

Ich finde, das ist ein ziemlicher Hack. Man kann das auch sauber machen:

Code: Alles auswählen

\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage[table]{xcolor}
\usepackage{booktabs}
\makeatletter
\newcommand*{\zeittabellenzeilen}{}
\newcommand*{\phasenzeilen}{}
\newcounter{Dauer}
\newenvironment{zeittabelle}{%
  \global\let\zeittabellenzeilen\@empty
  \newenvironment{phase}[1]{%
    \setcounter{Dauer}{0}%
    \global\let\phasenzeilen\@empty
    \g@addto@macro\zeittabellenzeilen{%
      \rowcolor{gray!50}\textbf{##1} & \bfseries
    }%
    \newcommand*{\vorgang}[2]{%
      \addtocounter{Dauer}{####2}%
      \g@addto@macro\phasenzeilen{\quad ####1 & ####2\tabularnewline}%
    }%
  }{%
    \edef\@tempa{\theDauer}%
    \expandafter\g@addto@macro\expandafter\zeittabellenzeilen
    \expandafter{\@tempa\,Std.\tabularnewline}%
    \expandafter\g@addto@macro\expandafter\zeittabellenzeilen
    \expandafter{\phasenzeilen}%
  }%
}{%
  \begin{tabular}{lr}
    \toprule
    \textbf{Vorgang} & \textbf{Dauer}\tabularnewline
    \midrule
    \zeittabellenzeilen
    \bottomrule
  \end{tabular}
}
\makeatother
\begin{document}
\begin{zeittabelle}
\begin{phase}{Vorbereitung}
\vorgang{Mehl holen}{2}
\vorgang{Eier kaufen}{1}
\end{phase}
\begin{phase}{Backen}
\vorgang{Mehl und Eier verrühren}{2}
\vorgang{Teig backen}{8}
\end{phase}
\begin{phase}{Servieren}
\vorgang{Kuchen glasieren}{2}
\vorgang{Kuchen schneiden}{1}
\end{phase}
\end{zeittabelle}
\end{document}
Der Witz dabei ist, dass die Zeilen nach und nach aufgesammelt und erst ganz zum Schluss zu einer Tabelle montiert werden. Am Ende jeder Phase wird auch automatisch die Dauer ermittelt, etwas was innerhalb einer Tabelle auch nicht ganz trivial ist.

Nachteil dabei ist, dass man die Tabellen und Phasen nicht schachteln darf. Will man das noch, muss man mit \protected@edef statt mit \g@addto@macro arbeiten, wobei man sich genau überlegen muss, was mit \protect zu schützen ist. Das betrifft dann eventuell auch Material in der Tabelle, was bei obigem eher unproblematisch sein sollte.

Ich habe das übrigens nicht komplett alleine gebastelt. Insbesondere bei der richtigen Anzahl an # bei den innen definierten Anweisungen und auch bei der Grundidee mit dem Aufsammeln von Tabellenzeilen habe ich frühere Antworten von KOMA und das Wiki zu Rate gezogen. Deshalb hat mich die Antwort auch etwas Zeit gekostet.

123DrivenHoliday
Forum-Newbie
Forum-Newbie
Beiträge: 4
Registriert: Di 10. Nov 2009, 10:39

Beitrag von 123DrivenHoliday »

Hallo,

Vielen Dank Schweinebacke^^

Das ist fast schon das was ich brauche. Ich würde jetzt gerne noch eine Spalte einfügen, sodass man eine Soll- und eine Ist-Zeit hat. Ich habs gerade selber probiert, aber nicht hinbekommen. Wäre nett wenn du das noch mal eben machen könntest.

Wenn du ganz viel Lust hast, kannst du auch noch ne Funktion einbauen, die Vorgänge rot makiert, die zuviel Zeit benötigt haben und welche die weniger Zeit gebraucht haben grün. Aber das kriege ich vielleicht auch selber hin.

123DrivenHoliday
Forum-Newbie
Forum-Newbie
Beiträge: 4
Registriert: Di 10. Nov 2009, 10:39

Beitrag von 123DrivenHoliday »

Hallo,

ich hab es alleine hinbekommen. Hier der Code:

Code: Alles auswählen

\makeatletter
\definecolor{darkGreen}{rgb}{0.45,0.65,0.25}
\newcommand*{\zeittabellenzeilen}{}
\newcommand*{\phasenzeilen}{}
\newcounter{Soll}
\newcounter{Ist}
\newenvironment{zeittabelle}{%
  \global\let\zeittabellenzeilen\@empty
  \newenvironment{phase}[1]{%
    \setcounter{Soll}{0}%
    \setcounter{Ist}{0}%
    \global\let\phasenzeilen\@empty
    \g@addto@macro\zeittabellenzeilen{%
      \rowcolor{gray!50}\textbf{##1} & \bfseries
    }%
    \newcommand*{\vorgang}[3]{%
      \addtocounter{Soll}{####2}%
      \addtocounter{Ist}{####3}%
      \ifnum####2<####3%
      	\g@addto@macro\phasenzeilen{\quad ####1 & ####2 Std. & \textcolor{red}{####3 Std.}\tabularnewline}%
      \else%
      	\ifnum####2>####3
      		\g@addto@macro\phasenzeilen{\quad ####1 & ####2 Std. & \textcolor{darkGreen}{####3 Std.}\tabularnewline}%
      	\else%
      		\g@addto@macro\phasenzeilen{\quad ####1 & ####2 Std. & ####3 Std. \tabularnewline}%
      	\fi%
      \fi%
    }%
  }{%
    \edef\@tempa{\theSoll}%
    \edef\@tempb{\theIst}%
    \ifnum\theIst<\theSoll%
    	\def\@farb{\color{darkGreen}}%´
    \else%
    	\ifnum\theIst>\theSoll%
    		\def\@farb{\color{red}}%´
    	\else%
    		\def\@farb{\color{black}}%´
    	\fi%
    \fi%
    \expandafter\g@addto@macro\expandafter\zeittabellenzeilen
    \expandafter{\@tempa\,Std. & \bfseries}%
    \expandafter\g@addto@macro\expandafter\zeittabellenzeilen
    \expandafter{\@farb}%
    \expandafter\g@addto@macro\expandafter\zeittabellenzeilen
    \expandafter{\@tempb\,Std. \tabularnewline}%
    \expandafter\g@addto@macro\expandafter\zeittabellenzeilen
    \expandafter{\phasenzeilen}%
  }%
}{%
  \begin{tabular}{lrr}
    \toprule
    \textbf{Vorgang} & \textbf{geplante Dauer} & \textbf{tatsächliche Dauer} \tabularnewline
    \midrule
    \zeittabellenzeilen
    \bottomrule
  \end{tabular}
}
\makeatother 
Ist bestimmt nicht die eleganteste Lösung, aber es funktioniert.

Schweinebacke

Beitrag von Schweinebacke »

Man sollte nicht \theZähler miteinander vergleichen, weil das ja bereits die formatierte Ausgabe eines Zählers ist, sondern eher \value{Zähler}.

Antworten