Importar parámetros desde un archivo separado

Importar parámetros desde un archivo separado

Busqué durante mucho tiempo una solución a mi problema, ¡pero dicho problema no parecía prestarse bien a "google-eez"!

Este es mi problema: tengo una presentación de Beamer que presento a varios clientes. Como me gusta personalizar dicha presentación para adaptarla a la organización de cada cliente, tengo varios "fragmentos" de código, aproximadamente 10 líneas cada uno, en mi archivo principal Beamer .tex que incorpora logotipos, establece colores, muestra nombres de organizaciones, todo lo que sirve "personalizar" la presentación a un cliente determinado. La presentación de cada cliente por separado, por supuesto, requiere que se inserte otro fragmento de código de 10 líneas en dicho documento .tex principal. Como se puede imaginar, después de un tiempo, estos "fragmentos de personalización" sirven para confundir dicho documento .tex principal.

Lo que me gustaría hacer es crear archivos de "datos" separados, uno para cada cliente, que contengan los detalles que son únicos para cada cliente (o, si es posible, almacenartododichos datos del cliente, detodoclientes, en unsolteroarchivo). Luego, me gustaría poder, usando una sola línea en el documento .tex principal, extraer los datos de personalización de los archivos de datos adecuados.

El OP agregó el texto en cursiva el 16 de febrero de 2016: Tenga en cuenta que mi deseo es poder generar, a pedido, una presentación personalizada solo unos días antes de entregarla.

Algo como:

\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}

ArchivoA.txt, por supuesto, es uno de los archivos de "datos" (o, quizás, elúnicodicho archivo, si es posible) que mencioné anteriormente.

Algunas de mis investigaciones parecían indicar que el catchfilepaquete era la respuesta a mis problemas, pero no podía entender la documentación de dicho paquete.

¿Cómo puedo hacer esto? Y, ¿es posible combinar todos mis archivos de "datos" en un solo archivo (lo que realmente me gustaría hacer), o es mejor mantenerlos separados, uno para cada cliente?

Respuesta1

Mencioné esto en un comentario originalmente y me pidieron que lo publicara como respuesta.

Otra forma muy sencilla de hacer esto sin otros paquetes es simplemente tener las \newcommanddeclaraciones en su propio .texarchivo y usar un \inputpara cargarlas. Es decir tener:

% 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}

en clientA.texy de manera similar para otros clientes. Luego se puede cargar con un simple \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}

Como han demostrado otros, esto se puede ampliar con un script para producir diapositivas en masa, aunque Digger parece requerir que solo se cree un conjunto de diapositivas a la vez.

Respuesta2

Usaría un script de shell para hacer esto, definiría el nombre del archivo \inputpara cada cliente en el script y luego lo pasaría al pdflatexcomando (o cualquier motor que esté usando).

He aquí un ejemplo. Para cada cliente, cree un .texarchivo que contenga las definiciones relevantes para ese cliente. Aquí hay tres archivos de muestra:

clienteA.tex

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

clienteB.tex

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

clienteC.tex

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

La primera línea de su client-presentation.texarchivo (antes \documentclass) contendrá la línea:

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

Archivo de presentación

\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}

Luego, en la línea de comando, lo definimos \clientfiley lo pasamos a pdflatex. Así es como se vería un solo archivo:

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

Esto creará client-presentation.pdfcon comandos como se define en clientA.tex.

Script de shell de un solo uso

Ahora podemos crear un script de shell simple que toma un nombre base de archivo de cliente y un nombre base de archivo de presentación y luego produce un documento para ese cliente. Dado que es posible que el documento necesite más de una compilación para resolver referencias, etc., yo solía latexmkhacer la compilación. Esto garantizará en la mayoría de los casos que el documento se compila correctamente.

#!/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

Script de shell para automatización

Ahora podemos automatizar la producción de varios archivos de clientes a la vez, si es necesario.

#!/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

Este script de shell toma el nombre base del archivo de presentación como argumento y genera archivos PDF separados para cada clientX.texarchivo en el directorio actual.

Salida de ejemplo:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Respuesta3

Podría considerar un enfoque de interfaz clave-valor. Esto es menos frágil, ya que las claves se pueden especificar en cualquier orden en lugar de tener que estar en líneas específicas.

Además, los paquetes clave-valor permiten especificar valores predeterminados si faltan ciertos datos para clientes específicos o para proporcionar compatibilidad con versiones anteriores si agrega más claves en el futuro. Con algunos paquetes clave-valor, puede marcar ciertas claves comorequeridoo todo tipo de otras cosas. Básicamente, agrega mucha flexibilidad.

A continuación se muestra un ejemplo básico del enfoque. VerUna gran lista de cada paquete keyvalpara obtener una descripción de los paquetes y el artículo sobre el remolcadorImplementación de entradas de valores clave: una introducción porJosé WrightyChristian Feuersängerpara una introducción a las ideas y posibilidades de las interfaces clave-valor.

\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}

ingrese la descripción de la imagen aquí

Respuesta4

A continuación se muestra un ejemplo sencillo de cómo podría utilizar textmerg. Suponiendo que sepa qué variables desea en cada caso, puede crear un archivo individual para cada empresa y luego "fusionarlo" con su documento. Entonces, dado este archivo (llamado, digamos, textmerg-example.dat)

FooCo Inc.
rose
whale
serif
4cm
example-image

Luego configura su archivo beamer de esta manera:

\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}

Obviamente, querrás pensar con bastante cuidado qué cosas podrías querer cambiar cada vez.

EditarSi desea producir muchos archivos al mismo tiempo utilizando un conjunto diferente de variables, puede modificar el ejemplo anterior. Tomemos dos .datarchivos: 1-textmerg.daty 2-textmerg.dat:

FooCo Inc.
rose
whale
serif
4cm
example-image

y

SOME COMPANY
orchid
seahorse
default
7cm
example-image

Luego modificamos el archivo beamer anterior de esta manera:

% 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}

Ahora, para producir todos los diferentes archivos PDF de una sola vez, podríamos usar algo como:

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

Esto selecciona (inclusive) los archivos que comienzan en el rango "entre" 1 y 2, les asigna un nombre correspondiente 1-o 2-beamerpara la salida, define el comando \tmdatanumque se usa en nuestro comando sin bucle \Mergey luego ingresa el archivo principal del proyecto. , main.tex. El resultado deberían ser dos archivos separados con las configuraciones nombradas en los dos .datarchivos diferentes.

Alternativamente, mergitse podría construir un script de shell (llamado, por ejemplo, ) siguiendo estas líneas:

#!/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

Por lo tanto, mergit main 2crearía sus dos archivos PDF como en la frase anterior.

información relacionada