PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : einfache Schleifen in einem Latex-Kommando



moerff
09-04-2010, 20:47
Hallo liebe LaTeX-Freunde!

Ich verwende nun seit geraumer Zeit LaTeX und bin bisher mit nahezu allen Problemen durch Recherche im WWW relativ gut fertig geworden - Danke daher an allen Foren-Betreiber und Autoren von Dokumentationen!

Hier ist nun mein erster eigener Beitrag, der sich mit folgendem Problem beschäftigt:

Ich arbeite bei der Erstellung von Tabellen mit dem booktab-Paket und wie wahrscheinlich bekannt ist, wird dabei zur Erzeugung von "kurzen", an speziellen Spalten gebundenen horizontalen Linien der Befehl
\cmidrule(lr){"NrDerStartSpalte"-"NrDerEndSpalte"} verwendet. Diesen Befehl verwende ich meistens für jede Spalte , da dies in meinen Augen für gute Lesbarkeit sorgt.

Nun wollte ich mir die Arbeit erleichtern indem ich einen Befehl definiere, der obigen CODE mehrfach hintereinander schreibt und zwar mit fortlaufender Spaltennummer. Mein Befehl hierzu sieht bisher etwa so aus:



\newcommand{\cmr}[1]{
\newcounter{cmr}
\setcounter{cmr}{0}
\whiledo{\value{cmr}<#1}{
\stepcounter{cmr}
\cmidrule(lr){\value{cmr}-\value{cmr}}
}
}


Dies ist übrigens mein erster Versuch in LaTeX mit Schleifen zu arbeiten, daher bitte ich um Verzeihung, falls irgendwas total banales vergessen wurde.

Dieser CODE führt jedenfalls nicht zum Ziel, daher wäre ich für einen Vorschlag oder gar eine Lösung sehr dankbar.

Gruß
Moerff

mechanicus
09-04-2010, 22:14
Hi,

ich habe leider keine direkte Idee für eine Schleife, aber eine Möglichkeit:

\documentclass{scrartcl}
\usepackage{array,booktabs}
\newcommand{\cmr}[1]{%
\ifcase#1
\or
\cmidrule(lr){1-1}
\or
\cmidrule(lr){1-1}\cmidrule(lr){2-2}
\or
\cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}
\or
\cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}\cmidrule(lr){4-4}
\or
\cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}\cmidrule(lr){4-4}\cmidrule(lr){5-5}
\or
\cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}\cmidrule(lr){4-4}\cmidrule(lr){5-5}\cmidrule(lr){6-6}
\fi
}
\begin{document}
\begin{tabular}{*{6}{c}}
Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt \\\cmr{2}%
Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt \\\cmr{4}%
Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt \\\cmr{6}%
\end{tabular}
\end{document}

Gruß
Marco

PS:
Dein Code kann aber nicht funktionieren, weil du beim Aufruf von \newcommand den Counter cmr jedesmal neu definieren willst, was natürlich nicht funktionieren kann.

voss
09-04-2010, 22:40
Nun wollte ich mir die Arbeit erleichtern indem ich einen Befehl definiere, der obigen CODE mehrfach hintereinander schreibt und zwar mit fortlaufender Spaltennummer. Mein Befehl hierzu sieht bisher etwa so aus:

Dies ist übrigens mein erster Versuch in LaTeX mit Schleifen zu arbeiten, daher bitte ich um Verzeihung, falls irgendwas total banales vergessen wurde.

Dieser CODE führt jedenfalls nicht zum Ziel, daher wäre ich für einen Vorschlag oder gar eine Lösung sehr dankbar.



\documentclass{article}
\usepackage{array,multido,booktabs}
\makeatletter
\newcount\colNo
\def\addtoks#1{\toks@=\expandafter{\the\toks@\cmid rule(lr){#1-#1}}}
\newcommand\CL[1][1]{%
\toks@={\tabularnewline}%
\colNo=0\relax
\loop\ifnum\colNo<#1\relax
\advance\colNo by 1
\expandafter\addtoks\expandafter{\the\colNo}%
\repeat%
\the\toks@%
}
\makeatother
\begin{document}

\begin{tabular}{*5c}
foo & bar & baz & foo & bar \CL[5]
foo
\end{tabular}

\end{document}


Herbert

mechanicus
09-04-2010, 22:52
Hi Herbert,

ich hatte fast das identische Beispiel. Allerdings wollte es nicht klappen. Ich habe kein toksdef verwendet.

FUNKTIONIERT NICHT:

\documentclass{scrartcl}
\usepackage{array,booktabs}
\usepackage{ifthen,calc}
\newcount\cmrcounter

\newcommand{\cmr}[1]{%
\cmrcounter=0
\loop
\ifnum\cmrcounter<#1
\advance\cmrcounter by 1
\cmidrule(lr){\the\cmrcounter-\the\cmrcounter}
\repeat
}
\begin{document}
\begin{tabular}{*{6}{c}}
Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt & Hallo Welt \\\cmr{1}%
\end{tabular}
\end{document}

Durch dein toksdef erreichst du etwas, was ich gerade nicht nachvollziehen kann. Magst du bitte ein paar Worte dazu verlieren.

Gruß
Marco

voss
09-04-2010, 23:15
ich hatte fast das identische Beispiel. Allerdings wollte es nicht klappen. Ich habe kein toksdef verwendet.


TeX ist nach einem \\ in der ersten Spalte, wo normalerweise
ja die Spaltendefinition gilt. Mit \omit wird das intern abschaltet.
Nur dadurch ist es möglich, dass \hline usw möglich sind. Allerdings
muss man darauf achten, dass das "Argument" sozusagen als "GAnzes"
unzerlegt an die tabular-Umgebung weitergereicht wird. Das kann ich
mit einem Tokenregister leicht erreichen.

Herbert

mechanicus
09-04-2010, 23:31
Hallo Herbert,

danke für die Antwort. Ich habe mir soetwas ähnliches gedacht. Kannte nur omit noch nicht.

Gruß
Marco

moerff
10-04-2010, 11:48
Vielen Dank schonmal, soweit hab ich das ganze nun umgesetzt und versucht um einen weiteren Parameter zu erweitern. Es soll nun auch möglich sein (wohl eher Pflicht), eine Start-Spalte anzugeben, sodass nicht immer bei Spalte 1 gestartet wird:



\makeatletter
\newcount\colNoA
\newcount\colNoB
\def\addtoks#1{\toks@=\expandafter{\the\toks@\cmid rule(lr){#1-#1}}}
\newcommand\CL[2][1]{%
\toks@={\tabularnewline}%
\colNoA=#1\relax%
\colNoB=#2\relax%
\advance\colNoB by 1%
\loop\ifnum\colNoA<\colNoB\relax
\expandafter\addtoks\expandafter{\the\colNoA}
\advance\colNoA by 1%
\repeat%
\the\toks@%
}
\makeatother


Vielleicht auch nicht besonders schön, aber immerhin läuft es. :-)
Dabei sind mir nun folgende Dinege aufgefallen:

Aufruf: Der Befehl muss nun durch
\CL[StartSpalte]{EndSpalte} aufgerufen werden. Dabei verwirrt mich die Syntax etwas, da eckige Klammern ja eigentlich optionale Parameter angeben, oder?! Hier ist das irgendwie durcheinander. In deiner Version Herbert brauchte ich gar keine geschwungenen Klammern...
Leerzeile/Zeilenumbruch: Normalerweise beendet man die Zeile vor den Trennlinien mit "\\", wenn man dies so beibehält entsteht eine Leerzeile vor den Trennlinien. Da es bei der üblichen Schreibweise bleiben soll, wollte ich deinen CODE auch dahingehend etwas anpassen, jedoch wird mich nicht klar, wo genau der Zeilemumbruch stattfindet - \the\toks@ wird ja erst am Ende aufgerufen...


Antworten hierzu würden mir sehr weiterhelfen, die LaTeX-Programmierung näher zu verstehen!

Marv

moerff
10-04-2010, 12:04
Vielleicht könnte mir auch noch jmd. erklären, wie die Parameter in


\newcommand\CL[2][1]{...}

zu verstehen sind. Ich kannte das ganze bisher nur mit einer eckigen Klammer...

lockstep
10-04-2010, 12:21
Im ersten eckigen Klammerpaar wird die Zahl der Argumente angegeben (dies kann bei einem Makro ohne Argumente weggelassen werden). Ein zweites eckiges Klammerpaar zeigt an, dass das erste Argument des Makros optional ist; lässt der Anwender das Argument weg, greift LaTeX auf den Inhalt der zweiten eckigen Klammer zurück.



\documentclass{article}

\newcommand*{\bula}[2][Bundesland]{#1 \textsc{#2}}

\begin{document}

\bula{Schleswig-Holstein}

\bula[Stadtstaat]{Hamburg}

\end{document}


lockstep

mechanicus
10-04-2010, 12:24
In deiner Version Herbert brauchte ich gar keine geschwungenen Klammern...
Mit {..} übergibst du eine Gruppe. Ist keine Gruppe gegeben, so ist das erste Zeichen nach dem Makro die Gruppe:

\documentclass{minimal}

\begin{document}
\textbf Hallo

\textbf{Hallo}
\end{document}



Leerzeile/Zeilenumbruch: Normalerweise beendet man die Zeile vor den Trennlinien mit "\\", .... jedoch wird mich nicht klar, wo genau der Zeilemumbruch stattfindet - \the\toks@ wird ja erst am Ende aufgerufen...

mit tabularnewline oder mit \\ wird die Tabellenzeile beendet. \the\toks@ funktioniert so ähnlich wie eine Aufzählung. In toks@ wird alles aneinander gespeichert und zum Schluss wird der gesamte Befehl ausgeführt:


\documentclass{article}
\toksdef\MyTestTok=0

\begin{document}
\MyTestTok={Hallo}
\MyTestTok=\expandafter{\the\MyTestTok\ Welt}
\MyTestTok=\expandafter{\the\MyTestTok!}
\the\MyTestTok
\end{document}



Vielleicht könnte mir auch noch jmd. erklären, wie die Parameter in
Code:

\newcommand\CL[2][1]{...}

zu verstehen sind. Ich kannte das ganze bisher nur mit einer eckigen Klammer...

Was meinst du mit eckigen Klammern. Du sagst hier, dass \CL zwei Eingaben hat, wobei der erste Eingabeparameter optional ist.

Gruß
Marco

moerff
10-04-2010, 19:36
und wieder bin ich etwas schlauer...

jedoch fehlt mir nun noch eine schöne Umsetzung mit variabler Startspalte und mit dem üblichen Zeileinumbruch

Die unterschiedliche Eingabe

\\ nach der 2. Zeile in der ersten Tabelle
und das etwas unschöne Ergebnis

komische Ausrichtug in der 2.Zeile/3.Spalte der zweiten Tabelle
wird hoffentlich in folgendem Minimalbeispiel deutlich


\documentclass{article}
\usepackage{array,multido,booktabs}
\makeatletter
\newcount\colNoA
\newcount\colNoB
\def\addtoks#1{\toks@=\expandafter{\the\toks@\cmid rule(lr){#1-#1}}}
\newcommand\CL[2][1]{%
\toks@={\tabularnewline}%
\colNoA=#1\relax%
\colNoB=#2\relax%
\advance\colNoB by 1%
\loop\ifnum\colNoA<\colNoB\relax
\expandafter\addtoks\expandafter{\the\colNoA}
\advance\colNoA by 1%
\repeat%
\the\toks@%
}
\makeatother
\begin{document}

\begin{tabular}{*3c}
\toprule
foo & \multicolumn{2}{c}{foo} \\
\cmidrule(lr){2-3}
& A & B \\
\cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}
1 & 111 & 222 \\
2 & 333 & 444 \\
\bottomrule
\end{tabular}

\begin{tabular}{*3c}
\toprule
foo & \multicolumn{2}{c}{foo} \\
\cmidrule(lr){2-3}
& A & B \CL{3}
1 & 111 & 222 \\
2 & 333 & 444 \\
\bottomrule
\end{tabular}

\end{document}

rais
10-04-2010, 20:32
Moin moin,


und das etwas unschöne Ergebnis

komische Ausrichtug in der 2.Zeile/3.Spalte der zweiten Tabelle
wird hoffentlich in folgendem Minimalbeispiel deutlich

naja, Dein


\expandafter\addtoks\expandafter{\the\colNoA}

fügt Leerzeichen noch vor dem \tabularnewline ein ... und das noch innerhalb Deiner Schleife.
Schau Dir Herberts Code vllt nochmal genau an



\expandafter\addtoks\expandafter{\the\colNo}%

das Kommentarzeichen hier unterdrückt just solche Leerzeichen.;)

MfG

Krutius
13-03-2012, 15:05
Hallo

Ich bin via Google hier gelandet, da dieser Thread genau das Problem behandelt welches ich habe. Von daher mal an alle Poster ein Danke, ihr habt mir sehr geholfen.

Ich habe nun probiert dieses Beispiel so zu adaptieren, das bei der ersten und letzten aussen nicht getrimmt wird. Jedoch habe ich nun vor der unterbrochenen generierten Linie eine unerwünschte Leerzeile.

Den tipp mit dem % Zeichen von rais habe ich ja befolgt, allerdings habe ich wohl irgendwo ein Leerzeichen übersehen.

Funktionierendes Minimalbeispiel:


\documentclass[listof=totoc,oneside, 12pt, a4paper, titlepage, onecolumn, parskip=half]{scrreprt}
\usepackage[ngerman]{babel}
\usepackage{tabularx}
\usepackage{booktabs}
\usepackage{ifthen}

% Script für mehrere cmidrules
\makeatletter
\newcount\colNo
\def\addtoks#1#2#3{\toks@=\expandafter{\the\toks@\ cmidrule[#3](#2){#1-#1}}}
\newcommand\smidrule[2][\lightrulewidth]{%
\ifnum#2=1
\expandafter\addtoks\expandafter{\the\colNo}{}{#1} %
\else
\toks@={\tabularnewline}%
\colNo=0\relax
\loop\ifnum\colNo<#2\relax
\advance\colNo by 1
\ifnum\colNo=1% Erste Zeile
\expandafter\addtoks\expandafter{\the\colNo}{r}{#1 }%
\else%
\ifnum\colNo=#2 %Letzte Zeile
\expandafter\addtoks\expandafter{\the\colNo}{l}{#1 }%
\else% Mittlere Zeile
\expandafter\addtoks\expandafter{\the\colNo}{lr}{# 1}%
\fi%
\fi%
\repeat%
\the\toks@%
\fi%
}
\makeatother

\begin{document}
\begin{tabularx}{\textwidth}{XX}
\toprule{}
Col1
& Col2
\\
\smidrule[0.15em]{2}
Lorem Ipsum
& 12
\\
\bottomrule
\end{tabularx}
\end{document}

rstuby
13-03-2012, 18:31
Die Leerzeile kriege ich weg, indem ich das \\ weglasse.
Wo allerdings die "overfull \hbox"-Meldung herkommt, ist mir noch nicht klar.

rstuby
13-03-2012, 19:28
Wobei mir das mit dem \\ weglassen eigentlich auch rätselhaft ist, denn im Grunde gehört ja da ein \\ oder \tabularnewline hin. In denem smidrule-Befehl muss also irgendwie schon eins eingebaut sein?

Krutius
13-03-2012, 19:47
In denem smidrule-Befehl muss also irgendwie schon eins eingebaut sein?

Genau das hab ich mir auch schon gedacht, nur find ich ihn einfach nicht. :confused: