Inhalt von eigener Umgebung für Tabelle wird 3mal ausgeführt

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


godi
Forum-Fortgeschrittener
Forum-Fortgeschrittener
Beiträge: 75
Registriert: Mi 11. Feb 2015, 13:49

Inhalt von eigener Umgebung für Tabelle wird 3mal ausgeführt

Beitrag von godi »

Hallo,

ich habe eine eigene Umgebung für Tabellen erstellt.
Nun möchte ich die Tabellenelemente mit \xappto aus der etoolbox zwischenspeichern. Jedoch werden meine Tabellenelemente 3mal zwischengespeichert und ich weiß nicht warum.

Hier mein Beispiel:
\documentclass{scrreprt}
\usepackage{tabu}
\usepackage{etoolbox}

%neue Umgebung für Tabelle
\newenvironment{tab}{%
\begin{table}%
\center% 
\begin{tabu}{|X[m]|}	
	\hline%		
 		TestTabelle\\% 	
 	\hline% 		
}
{
\end{tabu}%  
\end{table}%
}

% Alle Tabellenelemente 
\newcommand\tabItems{}
% Erstellen eines Tabellenelementes mit Speicherung in allen Tabellenelementen
\newcommand\tabItem[1]{
	\xappto\tabItems{#1;}%
	#1\\%
	\hline%
}



\begin{document}
\begin{tab}
\tabItem{TabItem1} 
\tabItem{TabItem2}
\end{tab}

PROBLEM: Ausgabe aller Tabellenelemente enthaelt 3mal die Tabellenelemente?\\
\tabItems
\end{document}
Meine Ausgabe für \tabItems:
TabItem1;TabItem2;TabItem1;TabItem2;TabItem1;TabItem2;
Hat jemand eine Idee warum die Elemente 3mal gespeichert werden und wie ich dies umgehen kann?

esdd
Forum-Meister
Forum-Meister
Beiträge: 2561
Registriert: So 7. Feb 2010, 16:36

Beitrag von esdd »

tabu setzt wie auch tabularx die Tabelle intern mehrfach, u.a. um die Breite der X Spalte berechnen zu können. Und jedesmal werden Deine Tabellenelemente dem Befehl hinzugefügt.

godi
Forum-Fortgeschrittener
Forum-Fortgeschrittener
Beiträge: 75
Registriert: Mi 11. Feb 2015, 13:49

Beitrag von godi »

Ok,

danke für deine Antwort.

Ich habe es jetzt schon mit Zähler bzw. bool-flags versucht, das die Elemente nur beim ersten Aufruf gespeichert werden, jedoch war das auch nicht mit Erfolg gekrönt.

Leider stehe ich da ein wenig an, ist es möglich dies irgenwie umzusetzen?

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Sind die zu speichernden Einträge denn auch im echten Dokument nur Text und Zahlen und sind die Einträge alle eindeutig oder gibt es welche, die bewusst mehrfach vorkommen?

Andere Frage: Wozu brauchst du das denn? Möglicherweise gibt es ja noch einen anderen Weg zu deinem Ziel …
Ich biete Hilfe, Beratung und Schulung für alle Fragen rund um TeX, Buchgestaltung und Textsatz, sowie Grafik- und Kommunikationsdesign.
Mehr Infos und Kontakt unter tobiw.de.

Hier schreibe ich über TeX: Mein Blog „TeX-Beispiel des Monats“ (Deutsch) und TeX.tips (Englisch).

godi
Forum-Fortgeschrittener
Forum-Fortgeschrittener
Beiträge: 75
Registriert: Mi 11. Feb 2015, 13:49

Beitrag von godi »

Hallo,

wozu brauche ich das:
Der zwischengespeicherte String soll in ein Textfile mit spezieller Formatierung gespeichert werden. Dabei Handelt es sich um Zeichen und Zahlen. An was hättest du noch gedacht?

Die Tabelle hat im "echten" Dokument mehrere Spalten, davon benötige ich nur ein paar Spalten, die in das Textfile geschrieben werden sollen.

Die Einträge können, müssen aber nicht eindeutig sein. Also die kommen nicht bewusst mehrfach vor, wenn dann durch Zufall, was auch nicht stört.

godi
Forum-Fortgeschrittener
Forum-Fortgeschrittener
Beiträge: 75
Registriert: Mi 11. Feb 2015, 13:49

Beitrag von godi »

Hallo,

ich habe mir Gestern noch die Implementierung von tabu angesehen und alles möglich mit internen Countern und "iftabu" Befehlen getestet, jedoch nichts hat wirklich funktioniert.

Jetzt habe ich zwar eine Lösung die kurz und knapp ist, jedoch weiß ich nicht ob diese Performant ist, da ich jetzt auch die Tabellenzeilen vorab in einen Befehl zusammenfasse und diesen dann in der Tabu Umgebung aufrufe.

Hier mein Bsp:
\documentclass{scrreprt}
\usepackage{tabu}
\usepackage{etoolbox}

% Tabellenelemente
\newcommand\tabItems{}

% Erstellen eines Tabellenelementes mit Speicherung in allen Tabellenelementen
\newcommand\tabItem[1]{%
	\xappto\tabItems{#1;}
	\appto\tabRows{%
		#1\\%
		\hline%
	}%	
}

%neue Umgebung für Tabelle
\newenvironment{tab}{
	% Tabellenzeilen
	\newcommand\tabRows{}
}%
{%
\begin{table}%
\center% 
\begin{tabu}{|X[m]|}%		
	\hline%	
 	TestTabelle\\% 	
 	\hline%  
 	\tabRows%
\end{tabu}%  
\end{table}%
}

\begin{document}
\begin{tab}
\tabItem{TabItem1} 
\tabItem{TabItem2}
\end{tab}

Ausgabe der Tabellenelemente:\\
\tabItems

\end{document}
Bin aber für andere Vorschläge offen!

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Hi, hier ist grad viel los, deswegen die späte Antwort ;-)


Also ich habe gefragt, ob die Elemente eindeutig sind, weil man dann einfach Duplikate aus der Liste löschen könnte.

Ob deine Lösung performant ist, kann ich nicht sagen, damit habe ich mich bei TeX ehrlich gesagt noch nie auseinander gesetzt (setzten müssen …)

Hier eine Lösung mit LaTeX3 (expl3). Ein paar Erklärungen stehen im Code, wenn noch was unklar ist, frag einfach ;-)
\documentclass{scrreprt}
\usepackage{tabu}

% environ brauchen wir, um den Umgebungsinhalt verarbeiten zu können
% xparse benutzen wir für \NewDocumentCommand, außerdem läd es expl3,
% das wir für die LaTeX3-Funktionen brauchen.
\usepackage{environ,xparse}

% Für schönere Tabellen
\usepackage{booktabs}

% LaTeX3-Syntax einschalten:
% - Leerzeichen werden ignoriert
% - erforderliche LZ werden mit ~ gesetzt
% - : und _ als Teil von Befehlsnahmen
% siehe auch expl3.pdf und source3.pdf
\ExplSyntaxOn
% Als erstes legen wir eine neue Sequenz-Variable (vgl. mit Array) an.
\seq_new:N \l_godi_table_items_seq
% Nun definieren wir einen Befhl, um ein Element der Sequenz hinzuzufügen.
\cs_new:Npn \godi_save_table_item:n #1 {
   \seq_gput_right:Nn \l_godi_table_items_seq { #1 }
}
% Dann definieren wir einen neuen Befehl, um den Umgebungsinhalt (\BODY) zu
% verarbeiten: Innerhalb einer Gruppe soll \tabItem zu \godi_save_table_item:n
% werden. Den Inhalt schreiben wir in eine temporäre H-Box, die wir dann
% einfach wegwerfen (bzw. einfach so lassen, wie sie ist) damit er nicht
% im Dokument ausgegeben wird.
\cs_new:Npn \godi_evaluate_table_body:n #1 {
   \group_begin:
      \cs_set_eq:NN \tabItem \godi_save_table_item:n
      \hbox_set:Nn \l_tmpa_box { #1 }
   \group_end:
}
\cs_generate_variant:Nn \godi_evaluate_table_body:n { N }
% Die Umgebung definieren wir mit \NewEnviron: Darin leeren wir zunächst die
% Sequenz und lesen dann die Elemente aus. Danach kann der Inhalt wie gehabt
% mit tabu gesetzt werden.
\NewEnviron { tab } {
   \seq_clear:N \l_godi_table_items_seq
   \godi_evaluate_table_body:N \BODY
   \begin{table} 
      \centering% [\center ist falsch!]
      \begin{tabu} { X[m] }
         \toprule
         Test ~ Tabelle \\% ~für Leerzeichen, normale werden ignoriert.
         \midrule
         \BODY
         \bottomrule
      \end{tabu}
   \end{table}
}
% Den Befehl definieren wir so, dass er einfach nur seinen Inhalt ausgibt;
% die tatsächliche Arbeit (Sequenz ergänzen) macht ja \godi_save_table_item:n.
\NewDocumentCommand { \tabItem } { m } {
   #1 % Element einfach nur ausgeben.
}
% Um die Elemente auszugeben definieren wir dann noch \tabItems.
\NewDocumentCommand { \tabItems } { } {
   \seq_use:Nn \l_godi_table_items_seq { ; ~ }
}
% LaTeX3-Syntax wieder abschalten
\ExplSyntaxOff
% Umrühren – fertig!

\begin{document} 
\begin{tab} 
\tabItem{TabItem1} \\
\tabItem{TabItem2} \\
\end{tab} 

\textbf{Ausgabe der Tabellenelemente:}
\tabItems 

\begin{tab} 
\tabItem{TabItem3} \\
\tabItem{TabItem4} \\
\tabItem{TabItem5} \\
\end{tab} 

\textbf{Ausgabe der Tabellenelemente:}
\tabItems 

\end{document}
Ich habe mir außerdem erlaubt, deine Tabellen etwas aufzughübschen ;-) warum kannst du in meinem Blogartikel über Tabellen nachlesen. Dort habe ich auch ein paar Worte zur Zukunftssicherheit von tabu geschrieben.

\center ist übrigens falsch! Es gibt nur \centering oder die Umgebung {center} letztere fügt aber davon und danach zusätzliche Abstände ein und das willst du hier vermutlich eher nicht. Siehe dazu auch When should we use \begin{center} instead of \centering?


Viele Grüße
Tobi
Ich biete Hilfe, Beratung und Schulung für alle Fragen rund um TeX, Buchgestaltung und Textsatz, sowie Grafik- und Kommunikationsdesign.
Mehr Infos und Kontakt unter tobiw.de.

Hier schreibe ich über TeX: Mein Blog „TeX-Beispiel des Monats“ (Deutsch) und TeX.tips (Englisch).

godi
Forum-Fortgeschrittener
Forum-Fortgeschrittener
Beiträge: 75
Registriert: Mi 11. Feb 2015, 13:49

Beitrag von godi »

Wow,
herzlichen Dank für deine ausführliche Antwort!

Und danke für den Hinweis mit \center vs \centering.
Das mit tabu ist mir bewusst, ich muss mir erst mal eine alternative suchen, aber soweit funktioniert es ja auch nicht schlecht. ;)

Deinen Beispielcode habe ich leider noch nicht vollständig überblicken können da mir grundlegendes Wissen zu Latex3 fehlt. Bin bis jetzt immer mit 2e ausgekommen. ;)
Ich werde mir aber dein Beispiel noch genauer ansehen.

Danke nochmals!

P.S. Interessanter Blog

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Gern geschehen. L3 ist eigentlich recht logisch aufgebaut und gut zu verstehen wenn man die Grundprinzipien kennt. Die findest du in den beiden von mir verlinkten Dokumenten. Und konkrete Fragen zu meinem Code kannst du natürlich auch hier noch stellen ;-)
Ich biete Hilfe, Beratung und Schulung für alle Fragen rund um TeX, Buchgestaltung und Textsatz, sowie Grafik- und Kommunikationsdesign.
Mehr Infos und Kontakt unter tobiw.de.

Hier schreibe ich über TeX: Mein Blog „TeX-Beispiel des Monats“ (Deutsch) und TeX.tips (Englisch).

Benutzeravatar
cgnieder
Forum-Meister
Forum-Meister
Beiträge: 730
Registriert: Fr 22. Okt 2010, 18:37
Wohnort: Herrenberg
Kontaktdaten:

Beitrag von cgnieder »

tabu kennt den Befehl \tabuDisableCommands mit dem man tabu sagen kann, welche Befehl in der Trial-Phase wie zu deaktivieren sind. Damit würde folgendes funktionieren:
\documentclass{article}
\usepackage{tabu}
\usepackage{etoolbox}

\newenvironment{tab}{%
  % \begin{table}
  % \center% Der Befehl heißt \centering. \center ist der Start der
  % {center}-Umbgebung und sollte konsequenterweise mit \endcenter beendet
  % werden.  Allerdings fügt die {center}-Umgebung vertikalen Weißraum ein,
  % weshalb \centering hier die bessere Variante ist.
  \centering
  \begin{tabu}{|X[m]|}  
    \hline     
     TestTabelle \\
    \hline    
  }
  {%
    \end{tabu}%
    % \end{table}%
  }

\newcommand\tabItems{}

\makeatletter
\tabuDisableCommands{\let\tabRecordItem\@gobble}
\makeatother
\newcommand\tabRecordItem[1]{\xappto\tabItems{#1;}}
\newcommand\tabItem[1]{%
   \tabRecordItem{#1}%
   #1 \\
   \hline
}

\begin{document}

\begin{tab}
  \tabItem{TabItem1}
  \tabItem{TabItem2}
\end{tab}

\show\tabItems

\end{document}
> \tabItems=macro:
->TabItem1;TabItem2;.
l.41 \show\tabItems
Grüße
Clemens
Paketauthor

Antworten