Importando parâmetros de um arquivo separado

Importando parâmetros de um arquivo separado

Procurei por muito tempo uma solução para o meu problema, mas esse problema não parecia se adequar bem ao "google-eez"!

Aqui está o meu problema: tenho uma apresentação do Beamer que apresento a vários clientes. Como gosto de personalizar a apresentação para se adequar à organização de cada cliente, tenho vários "pedaços" de código, com cerca de 10 linhas cada, em meu arquivo pai Beamer .tex que extraem logotipos, definem cores, exibem nomes de organizações - todas as coisas que servem para "personalizar" a apresentação a um determinado cliente. A apresentação de cada cliente separada, é claro, exige que outro pedaço de código de 10 linhas seja inserido no documento .tex pai. Como você pode imaginar, depois de um tempo esses "pedaços de personalização" servem para confundir o documento .tex pai.

O que eu gostaria de fazer é criar arquivos de "dados" separados, um para cada cliente, que contenham os detalhes exclusivos de cada cliente (ou, se possível, armazenartodosditos dados do cliente, detodosclientes, em umsolteiroarquivo). Então, gostaria de poder, usando uma única linha no documento .tex pai, extrair os dados de personalização dos arquivos de dados adequados.

O texto em itálico foi adicionado pelo OP em 16 de fevereiro de 2016: Tenha em mente que meu desejo é ser capaz de gerar, sob demanda, uma apresentação personalizada apenas alguns dias antes de entregá-la.

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}

ArquivoA.txt, é claro, é um dos arquivos de "dados" (ou, talvez, oúnicotal arquivo, se isso for possível) que abordei acima.

Algumas de minhas pesquisas pareciam indicar que o catchfilepacote era a resposta para meus problemas, mas não consegui entender a documentação do pacote.

Como posso fazer isso? E é possível combinar todos os meus arquivos de "dados" em um arquivo (o que eu realmente gostaria de fazer) ou é melhor mantê-los separados, um para cada cliente?

Responder1

Mencionei isso originalmente em um comentário e fui solicitado a postar isso como resposta.

Outra maneira muito simples de fazer isso sem outros pacotes é apenas ter as \newcommanddeclarações em seu próprio .texarquivo e usar um \inputpara carregá-las. Ou seja, tenha:

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

dentro clientA.texe da mesma forma para outros clientes. Isso pode então ser carregado com um simples \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 outros mostraram, isso pode ser estendido com um script para produzir slides em massa, embora o Digger pareça exigir apenas a criação de um conjunto de slides por vez.

Responder2

Eu usaria um script de shell para fazer isso e definiria o nome do arquivo \inputpara cada cliente no script e depois o passaria para o pdflatexcomando (ou qualquer mecanismo que você esteja usando).

Aqui está um exemplo. Para cada cliente, crie um .texarquivo contendo as definições relevantes para esse cliente. Aqui estão três arquivos de exemplo:

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}

A primeira linha do seu client-presentation.texarquivo (antes de \documentclass) conterá a linha:

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

Arquivo de apresentação

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

Então, na linha de comando, definimos \clientfilee passamos para pdflatex. Esta é a aparência de um único arquivo:

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

Isso criará client-presentation.pdfcom comandos definidos em clientA.tex.

Script de shell de uso único

Agora podemos criar um script de shell simples que pega um nome base de arquivo do cliente e um nome base de arquivo de apresentação e então produz um documento para esse cliente. Como é possível que o documento precise de mais de uma compilação para resolver referências etc., eu costumava latexmkfazer a compilação. Isso garantirá, na maioria dos casos, que o documento seja compilado corretamente.

#!/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 automação

Agora podemos automatizar a produção de vários arquivos de clientes de uma só vez, se necessário.

#!/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 usa o nome base do arquivo de apresentação como argumento e gera PDFs separados para cada clientX.texarquivo no diretório atual.

Exemplo de saída:

insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui

Responder3

Você pode considerar uma abordagem de interface de valor-chave. Isso é menos frágil, pois as chaves podem ser especificadas em qualquer ordem, em vez de estarem em linhas específicas.

Além disso, os pacotes de valores-chave permitem que padrões sejam especificados, se determinados dados estiverem faltando para clientes específicos ou para fornecer compatibilidade com versões anteriores se você adicionar mais chaves no futuro. Com alguns pacotes de valores-chave, você pode marcar certas chaves comoobrigatórioou todos os tipos de outras coisas. Basicamente, adiciona muita flexibilidade.

Aqui está um exemplo básico da abordagem. VerUma grande lista de todos os pacotes keyvalpara descrição dos pacotes e artigo do TUGboatImplementando entrada de valor-chave: uma introdução porJosé WrighteChristian Feuersängerpara uma introdução às ideias e possibilidades das interfaces de valor-chave.

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

insira a descrição da imagem aqui

Responder4

Aqui está um exemplo simples de como você pode usar textmerg. Supondo que você saiba quais variáveis ​​deseja em cada caso, você poderia fazer um arquivo individual para cada empresa e depois “mesclar” com o seu documento. Então, dado este arquivo (chamado, digamos, textmerg-example.dat)

FooCo Inc.
rose
whale
serif
4cm
example-image

Você então configura seu arquivo beamer assim:

\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, você vai querer pensar com bastante cuidado sobre quais coisas você pode querer mudar a cada vez.

EditarSe quiser produzir muitos arquivos ao mesmo tempo usando um conjunto diferente de variáveis, você pode modificar o exemplo acima. Vamos pegar dois .datarquivos: 1-textmerg.date 2-textmerg.dat:

FooCo Inc.
rose
whale
serif
4cm
example-image

e

SOME COMPANY
orchid
seahorse
default
7cm
example-image

Em seguida, modificamos o arquivo beamer acima desta forma:

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

Agora, para produzir todos os diferentes PDFs de uma só vez, poderíamos usar algo como:

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

Isso seleciona (inclusive) os arquivos que começam no intervalo "entre" 1 e 2, atribui a eles um nome correspondente 1-ou 2-beamerpara a saída, define o comando \tmdatanumque é usado em nosso comando sem loop \Mergee, em seguida, insere o arquivo principal do projeto , main.tex. O resultado deve ser dois arquivos separados com as configurações nomeadas nos dois .datarquivos diferentes.

Alternativamente, um script de shell (chamado, digamos, mergit) poderia ser construído ao longo destas linhas:

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

Assim, mergit main 2criaria seus dois PDFs como na linha acima.

informação relacionada