Importieren von Parametern aus einer separaten Datei

Importieren von Parametern aus einer separaten Datei

Ich habe lange nach einer Lösung für mein Problem gesucht, aber das Problem schien sich für „google-eez“ nicht gut zu eignen!

Hier ist mein Problem: Ich habe eine Beamer-Präsentation, die ich verschiedenen Kunden vorführe. Da ich diese Präsentation gerne an die Organisation jedes Kunden anpasse, habe ich in meiner übergeordneten Beamer-.tex-Datei mehrere „Codeblöcke“ von jeweils etwa 10 Zeilen, die Logos einfügen, Farben festlegen, Organisationsnamen anzeigen – alles Dinge, die dazu dienen, die Präsentation für einen bestimmten Kunden zu „personalisieren“. Für jede einzelne Kundenpräsentation muss natürlich ein weiterer 10-zeiliger Codeblock in das übergeordnete .tex-Dokument eingefügt werden. Wie Sie sich vorstellen können, führen diese „Personalisierungsblöcke“ nach einer Weile dazu, dass das übergeordnete .tex-Dokument durcheinander gerät.

Ich möchte separate „Datendateien“ erstellen, eine für jeden Kunden, die die für jeden Kunden einzigartigen Angaben enthalten (oder, wenn möglich,allebesagte Kundendaten,alleKunden, in eineeinzelDatei). Dann möchte ich in der Lage sein, mithilfe einer einzigen Zeile im übergeordneten .tex-Dokument die Anpassungsdaten aus den richtigen Datendateien zu extrahieren.

Kursiver Text wurde vom OP am 16. Februar 2016 hinzugefügt: Bitte bedenken Sie, dass es mein Wunsch ist, auf Anfrage eine individuelle Präsentation wenige Tage vor dem Abgabetermin zu erstellen.

Etwas wie:

\documentclass{beamer}
\usepackage{xcolor}

\newcommand{\nameoforg}{1st line from FileA.data}% Name of organization
\newcommand{\mainRGB}{2nd line from FileA.data}% Title color code
\newcommand{\backRGB}{3rd line from FileA.data}% Background color code
\newcommand{\clientlogowidth}{4th line from FileA.data}% Logo width
\newcommand{\clientlogo}{5th line from FileA.data}% Logo file name

\definecolor{mainslidecolor}{RGB}{\mainRGB}
\definecolor{backslidecolor}{RGB}{\backRGB}


\begin{document}

\title[\nameoforg]{Presentation Title}
\titlegraphic{\includegraphics[width=\clientlogowidth]{\clientlogo}}

\begin{frame}
this is boring
\end{frame}

\end{document}

DateiA.txtist natürlich eine der "Daten"-Dateien (oder vielleicht dieSohle, einzig, alleinigeine solche Datei, falls das möglich ist), auf die ich oben eingegangen bin.

Einige meiner Recherchen schienen darauf hinzudeuten, dass das catchfilePaket die Antwort auf meine Probleme war, aber ich konnte die Dokumentation des besagten Pakets nicht verstehen.

Wie kann ich das machen? Und ist es möglich, alle meine „Daten“-Dateien in einer Datei zu kombinieren (was ich wirklich gerne tun würde), oder ist es besser, sie getrennt aufzubewahren, eine pro Kunde?

Antwort1

Ich habe dies ursprünglich in einem Kommentar erwähnt und wurde gebeten, dies als Antwort zu posten.

Eine weitere sehr einfache Möglichkeit, dies ohne andere Pakete zu tun, besteht darin, die \newcommandDeklarationen einfach in einer eigenen .texDatei zu haben und \inputsie mit einem zu laden. Das heißt:

% Name of organization
\newcommand{\nameoforg}{Organization A}
% Title color code
\newcommand{\mainRGB}{255,0,0}
% Background color code
\newcommand{\backRGB}{255,255,255}
% Logo width
\newcommand{\clientlogowidth}{6cm}
% Logo file name
\newcommand{\clientlogo}{example-image-a}

in clientA.texund ebenso für andere Clients. Dies kann dann mit einem einfachen geladen werden \input{clientA.tex}:

\documentclass{beamer}
\usepackage{mwe}

\input{clientA.tex}

\definecolor{mainslidecolor}{RGB}{\mainRGB}
\definecolor{backslidecolor}{RGB}{\backRGB}

\title[\nameoforg]{Presentation Title}
\titlegraphic{\includegraphics[width=\clientlogowidth]{\clientlogo}}

\begin{document}
\begin{frame}
  \maketitle
\end{frame}

\begin{frame}
  Hello, World!
\end{frame}
\end{document}

Wie andere bereits gezeigt haben, kann dies mit einem Skript erweitert werden, um Folien in Massen zu produzieren. Bei Digger scheint jedoch immer nur die Erstellung eines Foliensatzes zu erfordern.

Antwort2

Ich würde dazu ein Shell-Skript verwenden und den Dateinamen \inputfür jeden Client im Skript definieren und ihn dann an den pdflatexBefehl (oder die von Ihnen verwendete Engine) übergeben.

Hier ist ein Beispiel. Erstellen Sie für jeden Client eine .texDatei mit den relevanten Definitionen für diesen Client. Hier sind drei Beispieldateien:

clientA.tex

\newcommand\clientname{Client A}
\newcommand\clienttheme{EastLansing}

clientB.tex

\newcommand\clientname{Client B}
\newcommand\clienttheme{Madrid}

clientC.tex

\newcommand\clientname{Client C}
\newcommand\clienttheme{Bergen}

Die erste Zeile Ihrer client-presentation.texDatei (vor \documentclass) enthält dann die Zeile:

\InputIfFileExists{\clientfile}{}{\typeout{\detokenize{\clientfile}\ not found!}}

Präsentationsdatei

\InputIfFileExists{\clientfile}{}{\typeout{\detokenize{\clientfile}\ not found!}}
\documentclass{beamer}
\usetheme{\clienttheme}
\title{My Presentation}
\author{Prepared for:\\\clientname}
\date{}
\begin{document}
\begin{frame}[plain]
\maketitle
\end{frame}
\begin{frame}
\begin{block}{This is a block}
\begin{itemize}
\item An item
\end{itemize}
\end{block}
\end{frame}
\end{document}

Dann definieren wir es in der Befehlszeile \clientfileund übergeben es an pdflatex. So würde eine einzelne Datei aussehen:

pdflatex "\def\clientfile{clientA}\input{client-presentation}"

Dies wird client-presentation.pdfmit den in definierten Befehlen erstellt clientA.tex.

Shell-Skript zur einmaligen Verwendung

Wir können jetzt ein einfaches Shell-Skript erstellen, das einen Client-Datei-Basisnamen und einen Präsentationsdatei-Basisnamen verwendet und dann ein Dokument für diesen Client erstellt. Da es möglich ist, dass das Dokument mehr als eine Kompilierung benötigt, um Referenzen usw. aufzulösen, habe ich latexmkdie Kompilierung durchgeführt. Dadurch wird in den meisten Fällen sichergestellt, dass das Dokument ordnungsgemäß kompiliert wird.

#!/bin/sh
#Usage: first argument = client file base name, second = latex document base
latexmk -pdf -silent    \
        -jobname="$1_$2" \
        -pdflatex="pdflatex --file-line-error --shell-escape --synctex=1 %O '\def\clientfile{$1}\input{%S}'" $2.tex

Shell-Skript zur Automatisierung

Bei Bedarf können wir jetzt die gleichzeitige Erstellung mehrerer Clientdateien automatisieren.

#!/bin/sh
#Usage: pass the basename of the presentation file as an argument
for f in client*.tex; do
basefile=$(basename "$f")
if [ "${basefile%.*}" != "$1" ]
then
latexmk -pdf     \
        -jobname="${basefile%.*}_$1" \
        -pdflatex="pdflatex --file-line-error --shell-escape --synctex=1 %O '\def\clientfile{${basefile%.*}}\input{%S}'" $1.tex
fi
done

Dieses Shell-Skript verwendet den Basisnamen der Präsentationsdatei als Argument und generiert für jede clientX.texDatei im aktuellen Verzeichnis ein separates PDF.

Beispielausgabe:

Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben

Antwort3

Sie könnten einen Schlüssel-Wert-Schnittstellenansatz in Betracht ziehen. Dieser ist weniger anfällig, da die Schlüssel in beliebiger Reihenfolge angegeben werden können und nicht in bestimmten Zeilen stehen müssen.

Darüber hinaus ermöglichen Schlüssel-Wert-Pakete die Angabe von Standardwerten, wenn bestimmte Daten für bestimmte Clients fehlen oder um Abwärtskompatibilität zu gewährleisten, wenn Sie in Zukunft weitere Schlüssel hinzufügen. Mit einigen Schlüssel-Wert-Paketen können Sie bestimmte Schlüssel alserforderlichoder alle möglichen anderen Dinge. Im Grunde genommen bringt es eine ganze Menge Flexibilität.

Hier ist ein einfaches Beispiel für diesen Ansatz. SieheEine große Liste aller Keyval-Paketefür eine Beschreibung der Pakete und den TUGboat-ArtikelImplementierung von Schlüssel-Wert-Eingaben: Eine Einführung vonJoseph WrightUndChristian Feuersängerfür eine Einführung in die Ideen und Möglichkeiten von Schlüssel-Wert-Schnittstellen.

\RequirePackage{filecontents}
\begin{filecontents*}{clientA.data}
\diggersetup{
  orgname = First Organization,
  mainRGB = {1,0,0},
  backRGB = {0,0,1},
  clientlogowidth = 1in,
  clientlogo = example-image-a,
}
\end{filecontents*}
\begin{filecontents*}{clientB.data}
\diggersetup{
  orgname = Second Organization,
  mainRGB = {1,1,0},
  backRGB = {0,1,0},
  clientlogowidth = 1.5in,
  clientlogo = example-image-b,
}
\end{filecontents*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\documentclass{beamer}
\usetheme{Boadilla}

\usepackage{lmodern} % no font substitution warnings
\usepackage{graphicx}
\usepackage{keyval} % or your favorite key-value package of the month

\makeatletter
\newlength\clientlogowidth
\define@key{digger}{orgname}{\def\nameoforg{#1}}
\define@key{digger}{mainRGB}{\definecolor{mainslidecolor}{RGB}{#1}}
\define@key{digger}{backRGB}{\definecolor{backslidecolor}{RGB}{#1}}
\define@key{digger}{clientlogo}{\def\clientlogo{#1}}
\define@key{digger}{clientlogowidth}{\setlength\clientlogowidth{#1}}
\setkeys{digger}{ % default key settings
  orgname = No Name!, 
  mainRGB = {1,1,1}, 
  backRGB = {1,0,1}, 
  clientlogo = example-image, 
  clientlogowidth = 1in,
}
\newcommand{\diggersetup}[1]{\setkeys{digger}{#1}}
\makeatother

%-------------------------------------
\input{clientA.data}
%\input{clientB.data}
%-------------------------------------

\begin{document}

\title[\nameoforg]{Presentation Title}
\titlegraphic{\includegraphics[width=\clientlogowidth]{\clientlogo}}

\begin{frame}
\titlepage
\end{frame}

\begin{frame}
this is boring
\end{frame}
\end{document}

Bildbeschreibung hier eingeben

Antwort4

Hier ist ein einfaches Beispiel, wie Sie verwenden könnten textmerg. Vorausgesetzt, Sie wissen, welche Variablen Sie in jedem Fall benötigen, könnten Sie für jedes Unternehmen eine einzelne Datei erstellen und diese dann mit Ihrem Dokument „zusammenführen“. Angenommen, diese Datei (mit dem Namen textmerg-example.dat)

FooCo Inc.
rose
whale
serif
4cm
example-image

Anschließend richten Sie Ihre Beamer-Datei wie folgt ein:

\documentclass{beamer}%
\usepackage{mwe}% to get "example-image" named in .dat file
\usepackage{textmerg}
% the "Fields" are read and assigned in the order of the .dat file
\Fields{
\nameoforg
\myinnertheme
\myoutertheme
\myfonttheme
\clientlogowidth
\clientlogo
}
% Load the specific options
\Merge{textmerg-example.dat}{}% <-- note the second argument is empty because we are looping anything.

\usecolortheme{\myinnertheme}
\usecolortheme{\myoutertheme}
\usefonttheme{\myfonttheme}
\title[\nameoforg]{Presentation Title}
\titlegraphic{\includegraphics[width=\clientlogowidth]{\clientlogo}}


\begin{document}
\maketitle

\begin{frame}
\frametitle{Some Frame Title}

\nameoforg: This is boring\ldots
\end{frame}

\end{document}

Natürlich sollten Sie jedes Mal genau überlegen, was Sie ändern möchten.

BearbeitenWenn Sie mehrere Dateien gleichzeitig mit einem anderen Variablensatz erstellen möchten, können Sie das obige Beispiel ändern. Nehmen wir zwei .datDateien: 1-textmerg.datund 2-textmerg.dat:

FooCo Inc.
rose
whale
serif
4cm
example-image

Und

SOME COMPANY
orchid
seahorse
default
7cm
example-image

Anschließend modifizieren wir die obige Beamer-Datei folgendermaßen:

% main.tex
\documentclass{beamer}%
\usepackage{mwe}% to get "example-image" named in .dat file
\usepackage{textmerg}
% the "Fields" are read and assigned in the order of the .dat file
\Fields{
\nameoforg
\myinnertheme
\myoutertheme
\myfonttheme
\clientlogowidth
\clientlogo
}
% Hack: we don't want to loop the file, so we leave the second argument empty
\providecommand{\tmdatanum}{1}% set a default input file
\Merge{\tmdatanum-textmerg.dat}{}
\usecolortheme{\myinnertheme}
\usecolortheme{\myoutertheme}
\usefonttheme{\myfonttheme}
\title[\nameoforg]{Presentation Title}
\titlegraphic{\includegraphics[width=\clientlogowidth]{\clientlogo}}


\begin{document}

\maketitle

\begin{frame}
\frametitle{Some Frame Title}

\nameoforg: This is boring\ldots

I have used \textbf{\myinnertheme\ \& \myoutertheme} as the inner and outer themes, with this as the client logo: \texttt{\clientlogo}.

\end{frame}

\end{document}

Um nun alle verschiedenen PDFs auf einmal zu erstellen, könnten wir etwas wie Folgendes verwenden:

for num in {1..2} ; do pdflatex -jobname=$num-beamer "\def\tmdatanum{$num}\input{main.tex}" ; done

Dies wählt (einschließlich) die Dateien aus, die im Bereich „zwischen“ 1 und 2 beginnen, weist ihnen einen entsprechenden Namen für die Ausgabe 1-zu 2-beamer, definiert den Befehl \tmdatanum, der in unserem nicht geloopten \MergeBefehl verwendet wird, und gibt dann die Hauptprojektdatei ein . Das Ergebnis sollten zwei separate Dateien mit den in den beiden verschiedenen Dateien main.texbenannten Einstellungen sein ..dat

Alternativ mergitkönnte ein Shell-Skript (sagen wir mit dem Namen ) nach diesem Muster erstellt werden:

#!/bin/bash
#
# Usage: mergit [FILE] [Highest input file num]
#
MASTERFILE=$1
ENDNUMBER=$2
#
for ((num=1;num<=ENDNUMBER;num++))
do
  pdflatex -jobname=$num-beamer "\def\tmdatanum{$num}\input{$MASTERFILE.tex}"
done

Somit mergit main 2würden Ihre beiden PDFs wie im Einzeiler oben erstellt.

verwandte Informationen