Zuordnung/Abfrage von Variablen

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


ionas
Forum-Anfänger
Forum-Anfänger
Beiträge: 13
Registriert: Di 20. Okt 2015, 16:27

Zuordnung/Abfrage von Variablen

Beitrag von ionas »

Hallo!

Ich stehe vor einem Problem und mein LaTex ist auch etwas eingerostet ...
Folgende Problemstellung:
Ich habe verschiedene Prüflinge. 1 2 3 4 ...
Die Prüflinge haben mehrere Namen/Bezeichnungen/Nummern
Diese Prüflinge werden immer unterschiedlichen Prüfungen (auch mehrere möglich) unterzogen.

Ich möchte mir ein Template schreiben, damit ich nur einmal die Infos (Namen/Bezeichnungen/Nummern) pro Prüflinge eingeben muss und im nächsten Schritt den Prüfungen die Prüflinge zuweise.
Nicht wieder jede einzelne Info sondern nur noch: Prüfling 1.
Hier soll er dann Namen/Bezeichnungen/Nummern automatisch indexieren.


Prüflingsdaten:
%Prüfling9%
\newcommand{\NummerIX}{Text}
\newcommand{\IntIX}{Text}
\newcommand{\PosIX}{Text}
.
.
.

Zuordnung zu den Prüfungen:

Wenn man die \newcommand's verschachteln könnte, würde das was ich erreichen will so aussehen: (ich weiß es ist falscher als falsch, aber ihr werdet sehen, was ich vorhabe)

\newcommand{\PrueflingPruefungI}{IX}

Und später im Tex-Dokument bei der Abfrage:
In Prüfung 1 wurde der Prüfling mit der Nummer \NummerPrueflingPruefungI verwendet

[/i]

Noch so einer

Beitrag von Noch so einer »

Du kannst einen Befehl definieren:
\newcommand*{\PrueflingA}{%
  \renewcommand*{\PNummer}{0815}%
  \renewcommand*{\PName}{Mustermann}%
  \renewcommand*{\PVorname}{Peter}%
  % usw.
}
Zusätzlich musst Du noch jedes Feld einmal initialisieren, damit sich die \renewcommand nicht über undefinierte Befehle beschwert:
\newcommand*{\PNummer}{????}
\newcommand*{\PName}{????}
\newcommand*{\Vorname}{????}
Und dann kannst Du am Anfang der Prüfung einfach \PrueflingA aufrufen, um die Pruefung diesem zuzuordnen. Das kann beispielsweise so geschehen, dass der Prüfling ein Argument der Anweisung oder Umgebung wird, also beispielsweise:
\newcommand*{\PruefungA}[1]{#1%
% und hier folgt der Code der Pruefung, in dem dann auch \PNummer, \PName etc. verwendet wird
}
Mit dem Aufruf:
\PruefungA{\PrueflingA}
wird dann die Prüfung mit den Daten des Prüflings versehen.

Wenn Dir das nicht passt, dann musst Du mal ein Beispiel machen, wie die Prüfungen bei Dir aussehen.

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

Beitrag von iTob »

Guten Morgen :-)

hier eine vielleicht noch etwas elegantere Lösung, bei der die Variablen mit @ maskiert werden und jede Person einen Satz von – in diesem Beispiel – drei Variablen hat. Auf die Variablen kann entweder über die ID einer Person zugegriffen werden oder die generischen Befehle \personXX werden auf eine Person eingestellt.
\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\usepackage{etoolbox}% für \csdef und \csuse

\makeatletter% um die internen Variablen mit @ "schützen" zu können

% Befehl, um eine Person zu definieren. Die ID kann frei gewählt werden
% \newperson{ID}{Vorname}{Name}{Nummer}
\newcommand{\newperson}[4]{%
   \csdef{var@name@#1}{#2}%
   \csdef{var@surname@#1}{#3}%
   \csdef{var@number@#1}{#4}%
}

% Befehl, um alle Infos im Block auszugeben
% \showpersoninfo{ID}
\newcommand{\showpersoninfo}[1]{%
   \par\noindent
   Vorname: \csuse{var@name@#1}\\%
   Name: \csuse{var@surname@#1}\\%
   Nummer: \csuse{var@number@#1}%
   \par
}

% Befehl um eine einzelne Info auszugeben
% \getpersoninfofield{ID}{name|surname|number}
\newcommand{\getpersoninfofield}[2]{%
   \csuse{var@#2@#1}%
}

% Platzhalter für die Variablen
\newcommand{\personname}{\textbf{??}}
\newcommand{\personsurname}{\textbf{??}}
\newcommand{\personnumber}{\textbf{??}}

% Befehl, um die Platzhalter auf eine Person einzustellen
% \setpersoninfo{ID}
\newcommand{\setpersoninfo}[1]{%
   \edef\personname{\csuse{var@name@#1}}%
   \edef\personsurname{\csuse{var@surname@#1}}%
   \edef\personnumber{\csuse{var@number@#1}}%
}

\makeatother% @ als Bestandteil von Befehlen wieder deaktivieren

\begin{document}
% Personen definieren
\newperson{mamu}{Max}{Mustermann}{34687}
\newperson{suso}{Susi}{Sorglos}{54987}
\newperson{otno}{Otto}{Normalverbraucher}{46879}

% zum Test die Infos ausgeben
\showpersoninfo{mamu}

% einzelne Infos abrufen
Die Nummer von Susi ist \getpersoninfofield{suso}{number}.

% Variablen auf Person setzen
\setpersoninfo{otno}

Der Prüfling \personname~\personsurname\ hat die Nummer \personnumber.
\end{document}
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).

ionas
Forum-Anfänger
Forum-Anfänger
Beiträge: 13
Registriert: Di 20. Okt 2015, 16:27

Beitrag von ionas »

Hallo!

Vielen Dank für die superschnellen und kompetenten Antworten!
Ich habe es geschafft!

:-)

ionas-1

Beitrag von ionas-1 »

Hallo Tobi,

ich noch mal - wenn auch nach langer Zeit ;-)

Aus gegebenem Anlass möchte ich mich noch einmal melden.

Kann es sein, dass man durch diese Methode nur 9 Parameter festlegen kann?

Danke

Gruß

Jonas

ionas-1

Beitrag von ionas-1 »

Ich habe es so versucht, aber es funktioniert nicht:
%\newcommand{\NewTest}[9]{% 
    \csdef{var@TestIntNum@#1}	{#2}% 
    \csdef{var@TestName@#1}		{#3}% 
    \csdef{var@TestNorm@#1}		{#4}% 
    \csdef{var@TestBANV@#1}		{#5}% 
    \csdef{var@TestBAHV@#1}		{#6}% 
    \csdef{var@TestSPNV@#1}		{#7}% 
    \csdef{var@TestSPHV@#1}		{#8}% 

    \NewTestContinued
    }
    \newcommand{\NewTestContinued}[9]{%
    \csdef{var@TestTemp@#1}		{#2}% 
    \csdef{var@TestPM@#1}		{#3}% 
    \csdef{var@TestMon@#1}		{#4}% 
    \csdef{var@TestBed@#1}		{#5}% 
    \csdef{var@TestExec@#1}		{#6}% 
    \csdef{var@TestPic@#1}		{#7}% 
    \csdef{var@TestReq@#1}		{#8}% 
    \csdef{var@TestRes@#1}		{#9}% 
}

Gast

Beitrag von Gast »

Mal 'ne blöde Frage: Wer soll sich denn die Reihenfolge von mehr als 9 Parametern merken? Ich kann man schon bei zwei oder drei oft nicht merken, in welcher Reihenfolge die anzugeben sind. Wäre da nicht eine key-value-Schnittstelle besser?

Ansonsten: Mach ein Minimalbeispiel. Bei unvollständigem Code mit auskommentierter (wichtigen) ersten Zeile kann kein Mensch wissen, was du wirklich gemacht hast.

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

Beitrag von iTob »

Hi ionas,

genau über diese Variante kann man (im Prinzip) nur neun Argumente verarbeiten. Mit ein paar Tricks gehen auch mehr, siehe z.B. http://tex.stackexchange.com/q/2132/4918

Aber ich gebe "Gast" recht, das in dem Fall eine andere Syntax sicher die bessere Variante wäre. Ich habe hier mal fix skizziert, wie man das mit LaTeX3 machen könnte:
\documentclass{scrartcl}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{xparse}

\ExplSyntaxOn

% Variable für Liste mit allen Personen
\seq_new:N \g_ionas_persons_seq

% Befehl zum Anlegen einer neuen Person
% - #1: ID (nur Buchstaben)
% - #2: Key-Value-Paare als Komma-getrennte Liste
\NewDocumentCommand { \newPerson } { m m } {
   % neue Person in der Liste aller Personen registrieren, wenn ID nicht vorhanden
   \seq_if_in:NnTF \g_ionas_persons_seq { #1 } {
      % TRUE: ID ist bereits vergeben
      \ERROR ID ~ bereits ~ vergeben!
   } {
      % FALSE: ID ist noch frei
      \seq_gput_right:Nn \g_ionas_persons_seq { #1 }
      % neue Property-Liste (basierend auf der ID)
      \prop_new:c { g_ionas_person_with_ID_#1_prop }
      % Liste der Schlüssel-Wert-Paare durchlaufen
      \clist_map_inline:nn { #2 } {
%         \#\#1 = ##1\\
         \ionas_parse_key_value:w ##1 \q_stop
         \prop_gput:cVV { g_ionas_person_with_ID_#1_prop }
            \l_ionas_current_key_tl
            \l_ionas_current_value_tl
      }
      % Prüfen ob alle nötigen Werte angeben wurden
      \clist_map_inline:nn { name, given-name, number } {
         \prop_if_in:cnF { g_ionas_person_with_ID_#1_prop } { ##1 } {
            \ERROR Wert ~ für ~ '##1' ~ fehlt.
         }
      }
   }
}

% Variablen und Befehle zum Einlesen von Schlüssel-Wert-Paaren
\tl_new:N \l_ionas_current_key_tl
\tl_new:N \l_ionas_current_value_tl
\cs_new:Npn \ionas_parse_key_value:w #1 = #2 \q_stop {
   \tl_set:Nn \l_ionas_current_key_tl { #1 }
   \tl_trim_spaces:N \l_ionas_current_key_tl
   \tl_set:Nn \l_ionas_current_value_tl { #2 }
   \tl_trim_spaces:N \l_ionas_current_value_tl
%   K = \l_ionas_current_key_tl \\
%   V = \l_ionas_current_value_tl \\
}

% Befehl zum Ausgeben aller Personen
\NewDocumentCommand { \getAllPersons } { } {
   \begin{itemize}
      \seq_map_inline:Nn \g_ionas_persons_seq {
         \item
            \getPersonInfo { ##1 } { given-name }
            \c_space_tl
            \getPersonInfo { ##1 } { name }
      }
   \end{itemize}
}

% Befehl zum Auslesen einer Bestimmten Eigenschaft
% - #1: ID
% - #2: Eigenschaft
\NewDocumentCommand { \getPersonInfo } { m m } {
   \prop_item:cn { g_ionas_person_with_ID_#1_prop } { #2 }
}

\ExplSyntaxOff

\begin{document}

\minisec{Neue Personen anlegen}
(führt nicht zu einer Text-Ausgabe)
\newPerson{mmustermann}{
   name = Mustermann,
   given-name = Max,
   number = 12345,
}
\newPerson{jdoe}{
   name = Doe,
   given-name = John,
   number = 555123,
   cuntry = USA,% Diese Angabe ist optional
}
\newPerson{jdoe2}{
   name = Doe,
   given-name = Jane,
   number = 555321,
   cuntry = USA,% Diese Angabe ist optional
}
% Das Folgende erzeugt einen Fehler, weil keine Nummer angeben ist
%\newPerson{ssorglos}{
%   name = Sorglos,
%   given-name = Susi,
%}
% Das Folgende erzeugt einen Fehler, weil die ID schon vergeben ist
%\newPerson{mmustermann}{
%   name = Mustermann,
%   given-name = Martin,
%   number = 54321,
%}

\minisec{Alle Personen ausgeben}
\getAllPersons

\minisec{Bestimmte Infos abfragen}
Name: \getPersonInfo{mmustermann}{name}\\
Matrikelnummer: \getPersonInfo{jdoe}{number}
\end{document}
Für ausführliche Erklärungen fehlt mir grad die Zeit aber für einen Einstig in LaTeX3 schau gern mal in meinem Blog vorbei: http://tobiw.de/tbdm/funktionssymbole

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).

ionas-1

Beitrag von ionas-1 »

Vielen Dank! Das ist so tatsächlich viel übersichtlicher! Vielen Dank, dass du dir trotz des Zeitmangels die Zeit für diesen Code genommen hast! Das hat mir sehr weitergeholfen! :-)

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

Beitrag von iTob »

Gerne ;-) bedenke aber das das eher als Skizze zu verstehen ist, so wirklich bis zu ende gedacht ist das noch nicht, beispielsweise findet ja nur eine minimale Fehlerbehandlung statt …
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).

Antworten