Rellenar casillas para formularios en TikZ

Rellenar casillas para formularios en TikZ

quiero crear unFormulario de transferencia bancaria SEPA con IBAN

¿Cómo puedo crear un campo de formulario con Ncampos, cada uno de 5 mm de ancho con separaciones como en la imagen? campo de formulario

Por el momento utilizo una solución alternativa con un bucle for, pero esto hace que el código sea difícil de mantener. Finalmente necesito una función \formline{N}{cellwidth}{label}{value}para crear el campo de formulario completo y llenarlo con un valor opcional: campo de formulario completo

El siguiente código está disponible enhttps://github.com/jonasstein/bankformtex.

\documentclass[a4paper,11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{shapes}

\thispagestyle{empty} % no pagenumber. The form should be a stand alone macro... later.

\definecolor{SEPAOrange}{RGB}{254,213,161}
\definecolor{SEPADOrange}{RGB}{253,185,19}
\definecolor{SEPABlindcolor}{RGB}{255,0,0}
\begin{document}
\begin{tikzpicture}[x=1 mm, y=-1mm]
\pgfmathsetmacro{\yh}{4.2333} % y heigth step defined as 1/6 inch => 1/6 * 25.4 mm = 4.2333 mm
\pgfmathsetmacro{\xs}{9} % x start (own definition)
\pgfmathsetmacro{\xe}{141.5} % x end (own definition)
\pgfmathsetmacro{\widefield}{4.9859} % def: 134.62 mm / 27
\pgfmathsetmacro{\narrowfiels}{3.9594} % def: 134.62 mm/ 34

\filldraw[draw=black,color=SEPAOrange] (7.62, 4.5*\yh) rectangle (149.86-7.62,105.83-1); %orange background

\filldraw[draw=black,color=white] (\xs, 5*\yh) rectangle (\xe, 6.5*\yh -1.5); %Recepient 27 Char
\foreach \x in {1,...,26}
{
 \draw[color=SEPAOrange, line width=0.3mm] (7.62 + \x*\widefield, 5*\yh ) -- (7.62 + \x*\widefield, 6.5*\yh);
 \draw[color=SEPAOrange, line width=0.7mm] (7.62 + \x*\widefield, 5.8*\yh ) -- (7.62 + \x*\widefield, 6.5*\yh);
}

\filldraw[draw=black,color=white] (\xs, 7*\yh) rectangle (\xe, 8.5*\yh -1.5); %IBAN 34 Char
\foreach \x in {1,...,33}
 \draw[color=SEPAOrange, line width=0.3mm] (7.62 + \x*4, 7*\yh ) -- (7.62 + \x*4, 8.5*\yh);

\filldraw[draw=black,color=white] (\xs, 9*\yh) rectangle (\xe, 10.5*\yh -1.5); %BIC
\filldraw[draw=black,color=white] (\xe-12*5, 11*\yh) rectangle (\xe, 12.5*\yh -1.5); %Value 12 Char

\filldraw[draw=black,color=white] (\xs, 13*\yh) rectangle (\xe, 14.5*\yh -1.5); %Subject1
\filldraw[draw=black,color=white] (\xs, 15*\yh) rectangle (\xe, 16.5*\yh -1.5); %Subject2
\filldraw[draw=black,color=white] (\xs, 17*\yh) rectangle (\xe, 18.5*\yh -1.5); %Subject3

\filldraw[draw=black,color=white] (\xs, 19*\yh) rectangle (\xs+22*5, 20.5*\yh -1.5); % IBAN 22 Char

\filldraw[draw=black,color=white] (149.86-17.59, 19* \yh) rectangle (\xe, 20.5*\yh -1.5); % counter
\filldraw[draw=black,color=white] (\xs, 21* \yh) rectangle (42.52, 24.5*\yh); % date
\filldraw[draw=black,color=white] (42.52+5, 21*\yh) rectangle (149.86-17.59, 24.5*\yh); % signature

\draw[color=SEPADOrange] (0, 4.5 *\yh) --(149.86, 4.5*\yh); upper dark orange line
\draw[color=SEPADOrange] (0, 20.5 *\yh) --(149.86, 20.5*\yh); lower dark orange line
\draw[draw=black,color=black, line width=0.3mm] (0,0) rectangle (149.86,105.83); % black border
%\draw[align=left] at (\yh,\yh) {SEPA-Überweisung};

\end{tikzpicture}
\end{document} 

Respuesta1

uso

\formline*(coord)[field width][scope options]{N}{label}[value]<dividers>

argumentos obligatorios

  • coord: dónde colocar la línea; El ancla es westdel primer campo.
  • N: numero de campos.
  • label: nombre de la línea.

argumentos opcionales

  • *: ignorar los espacios en value.
  • field width: ancho de un campo.
  • scope options: las opciones se pasan al {scope}.
  • value: complete algo, debe contener solonormalcaracteres.
  • dividers: agrega divisores entre archivos; Puede ser una lista de comas de números de archivos o every n( npuede ser positivo o negativo).

ejemplos

\begin{tikzpicture}
    % background
    \fill [SEPAOrange] (0,0) rectangle (15,12);
    % formlines
    \formline(1,10){25}{Bank}[Deutsche Bank Hamburg]
    \formline(1,9)[6mm]{5}{Number 1}[123456]
    \formline(1,8)[6mm]{5}{Number 2}[1234]
    \formline*(1,7){22}{IBAN 1}[DE00 2105 0170 0012 3456 78]<every 4>
        % dividers every 4th field from right
    \formline*(1,6){22}{IBAN 2}<every -4>% dividers every 4th from left
    \formline*(1,5){22}{IBAN 3}<2,5,10,15,20>% irregular dividers
\end{tikzpicture}

ejemplos

notas

  • Cada campo es un nodo único y se nombra con form field label n, donde labeles el valor del argumento y nes el número del campo (comenzando desde 0). Podrías usar los nombres de estos nodos para agregar marcos o cosas así.
  • Hay varios estilos de TikZ que se pueden usar para cambiar la apariencia.
  • Agregué algunas explicaciones al código.por favor pregunte si algo no está claro!

código completo

\documentclass{article}

% packages
\usepackage{tikz,xparse}
\usetikzlibrary{positioning,fit,calc}

% colors
\definecolor{SEPAOrange}{RGB}{254,213,161}
\definecolor{SEPADOrange}{RGB}{253,185,19}

% switch on expl3 syntax
% (_ and : become part of macro names; spaces are ignored; ~ is normal space)
\ExplSyntaxOn
% make @ available as part of macro name
\makeatletter
% commad to genreate internal lengths
% use \form_generate_lengths:n {<comma list>}
\cs_new:Npn \form_generate_lengths:n #1 {
    \clist_set:Nn \l_tmpa_clist { #1 }
    \clist_map_inline:Nn \l_tmpa_clist {
        \expandafter\newlength \csname form @ x ##1 \endcsname
        \expandafter\newlength \csname form @ y ##1 \endcsname
    }
}
% gererate internal length used in node shapes
\form_generate_lengths:n {
    A, Ab, At, Abt,
    B, Bb, Bt, Bbt,
    D,
    C,
}
% sep between fields
\dim_new:N \g_form_sep_dim
\dim_set:Nn \g_form_sep_dim { 0.5pt }
% dimensions of the edges in fields
\dim_new:N \g_form_x_edge_dim
\dim_set:Nn \g_form_x_edge_dim { 0.5pt }
\dim_new:N \g_form_y_edge_dim
\dim_set:Nn \g_form_y_edge_dim { 3pt }
\dim_new:N \formdividerwidth
\dim_set:Nn \formdividerwidth { 2\g_form_x_edge_dim + \g_form_sep_dim }
\dim_new:N \formdividerheight
\dim_set:Nn \formdividerheight { \g_form_y_edge_dim }
% new node shapes for fields
\pgfdeclareshape{form~field~middle}{% from p. 631 in pgfmanual.pdf
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{north~east}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south~east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{south~west}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{north~west}
    \backgroundpath{%  this is new
        %  store corners
        \southwest \form@xA = \pgf@x \form@yA = \pgf@y
        \northeast \form@xC = \pgf@x \form@yC = \pgf@y
        \form@xB = \form@xC \form@yB = \form@yA
        \form@xD = \form@xA \form@yD = \form@yC
        % calculate edges
        \form@xAt = \form@xA
        \form@yAt = \form@yA \advance \form@yAt by \g_form_y_edge_dim
        \form@xAb = \form@xA \advance \form@xAb by \g_form_x_edge_dim
        \form@yAb = \form@yA
        \form@xAbt = \form@xAb
        \form@yAbt = \form@yAt
        \form@xBt = \form@xB
        \form@yBt = \form@yB \advance \form@yBt by \g_form_y_edge_dim
        \form@xBb = \form@xB \advance \form@xBb by -\g_form_x_edge_dim
        \form@yBb = \form@yB
        \form@xBbt = \form@xBb
        \form@yBbt = \form@yBt
        %  construct main path
        \pgfpathmoveto{\pgfpoint{\form@xAt}{\form@yAt}}
        \pgfpathlineto{\pgfpoint{\form@xD}{\form@yD}}
        \pgfpathlineto{\pgfpoint{\form@xC}{\form@yC}}
        \pgfpathlineto{\pgfpoint{\form@xBt}{\form@yBt}}
        \pgfpathlineto{\pgfpoint{\form@xBbt}{\form@yBbt}}
        \pgfpathlineto{\pgfpoint{\form@xBb}{\form@yBb}}
        \pgfpathlineto{\pgfpoint{\form@xAb}{\form@yAb}}
        \pgfpathlineto{\pgfpoint{\form@xAbt}{\form@yAbt}}
        \pgfpathlineto{\pgfpoint{\form@xAt}{\form@yAt}}
        \pgfpathclose
    }
}
\pgfdeclareshape{form~field~start}{
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{north~east}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south~east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{south~west}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{north~west}
    \backgroundpath{%  this is new
        %  store corners
        \southwest \form@xA = \pgf@x \form@yA = \pgf@y
        \northeast \form@xC = \pgf@x \form@yC = \pgf@y
        \form@xB = \form@xC \form@yB = \form@yA
        \form@xD = \form@xA \form@yD = \form@yC
        % calculate edges
        \form@xAt = \form@xA
        \form@yAt = \form@yA \advance \form@yAt by \g_form_y_edge_dim
        \form@xAb = \form@xA \advance \form@xAb by \g_form_x_edge_dim
        \form@yAb = \form@yA
        \form@xAbt = \form@xAb
        \form@yAbt = \form@yAt
        \form@xBt = \form@xB
        \form@yBt = \form@yB \advance \form@yBt by \g_form_y_edge_dim
        \form@xBb = \form@xB \advance \form@xBb by -\g_form_x_edge_dim
        \form@yBb = \form@yB
        \form@xBbt = \form@xBb
        \form@yBbt = \form@yBt
        %  construct main path
        \pgfpathmoveto{\pgfpoint{\form@xA}{\form@yA}}
        \pgfpathlineto{\pgfpoint{\form@xD}{\form@yD}}
        \pgfpathlineto{\pgfpoint{\form@xC}{\form@yC}}
        \pgfpathlineto{\pgfpoint{\form@xBt}{\form@yBt}}
        \pgfpathlineto{\pgfpoint{\form@xBbt}{\form@yBbt}}
        \pgfpathlineto{\pgfpoint{\form@xBb}{\form@yBb}}
        \pgfpathlineto{\pgfpoint{\form@xA}{\form@yA}}
        \pgfpathclose
    }
}
\pgfdeclareshape{form~field~end}{
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{north~east}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south~east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{south~west}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{north~west}
    \backgroundpath{%  this is new
        %  store corners
        \southwest \form@xA = \pgf@x \form@yA = \pgf@y
        \northeast \form@xC = \pgf@x \form@yC = \pgf@y
        \form@xB = \form@xC \form@yB = \form@yA
        \form@xD = \form@xA \form@yD = \form@yC
        % calculate edges
        \form@xAt = \form@xA
        \form@yAt = \form@yA \advance \form@yAt by \g_form_y_edge_dim
        \form@xAb = \form@xA \advance \form@xAb by \g_form_x_edge_dim
        \form@yAb = \form@yA
        \form@xAbt = \form@xAb
        \form@yAbt = \form@yAt
        \form@xBt = \form@xB
        \form@yBt = \form@yB \advance \form@yBt by \g_form_y_edge_dim
        \form@xBb = \form@xB \advance \form@xBb by -\g_form_x_edge_dim
        \form@yBb = \form@yB
        \form@xBbt = \form@xBb
        \form@yBbt = \form@yBt
        %  construct main path
        \pgfpathmoveto{\pgfpoint{\form@xAt}{\form@yAt}}
        \pgfpathlineto{\pgfpoint{\form@xD}{\form@yD}}
        \pgfpathlineto{\pgfpoint{\form@xC}{\form@yC}}
        \pgfpathlineto{\pgfpoint{\form@xB}{\form@yB}}
        \pgfpathlineto{\pgfpoint{\form@xAb}{\form@yAb}}
        \pgfpathlineto{\pgfpoint{\form@xAbt}{\form@yAbt}}
        \pgfpathlineto{\pgfpoint{\form@xAt}{\form@yAt}}
        \pgfpathclose
    }
}
% new command to draw a line of fiels
% usage: \formline*(coord)[field width][scope options]{N}{label}[value]<dividers>
%                #1   #2       #3           #4        #5    #6    #7      #8
%        * = ignore spaces in [value]
%        required: #2, #5, #6,
%        optional: #1, #3, #4, #7, #8
\NewDocumentCommand { \formline } { s r() O{3mm} O{} m m o d<> } {
    % save field width
    \dim_set:Nn \l_tmpa_dim { #3 }
    % begin a scope
    \begin{scope}
        [every~form~field/.append~style={minimum~width=\dim_use:N \l_tmpa_dim}, #4]
        % draw fields
        %% set temp counter to 0
        \int_set:Nn \l_tmpa_int {0}
        %% first node (number 0)
        \node (form~field~#6~0) [at={(#2)}, every~form~field~start] {\strut};
        %% middle nodes, go through list form 1 to N-1
        \int_step_inline:nnnn { 1 } { 1 } { #5 - 2 } {
            %%% draw node
            \node (form~field~#6~##1) [
                every~form~field~middle,
                right=\dim_use:N \g_form_sep_dim of~form~field~#6~\int_use:N \l_tmpa_int
            ] {\strut};
            %%% incremet counter by 1
            \int_incr:N \l_tmpa_int
        }
        %% draw last node (number N)
        \node (form~field~#6~\int_eval:n { #5 - 1 }) [
            every~form~field~end,
            right=\dim_use:N \g_form_sep_dim of~form~field~#6~\int_use:N \l_tmpa_int
        ] {\strut};
        % draw label
        \node [every~form~label, above~right=0pt~of~form~field~#6~0.north~west] {#6};
        % add value, if exist
        \IfValueT { #7 } {
            %% save value to token list
            \tl_set:Nn \l_tmpa_tl { #7 }
            %% replace input space with space token
            \IfBooleanF { #1 } {
                \tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_space_token }
            }
            %% set temp counter to 0
            \int_set:Nn \l_tmpa_int { 0 }
            %% iterate through tokes and print digits above fields
            \tl_map_inline:Nn \l_tmpa_tl {
                %%% chack overlong values
                \int_compare:nT { \l_tmpa_int = #5 } {
                    \node at (form~field~#6~\int_eval:n { \l_tmpa_int - 1 })
                        [fill=red, font=\bfseries] {ERROR:~value~too~long};% some error message
                    \tl_map_break:
                }
                %%% draw digit
                \node [every~form~digit] at (form~field~#6~\int_use:N \l_tmpa_int.base) { ##1 };
                %%% incremet counter by 1
                \int_incr:N \l_tmpa_int
            }
        }
        % add sub-dividers, if exist
        \IfValueT { #8 } {
            %% save lowercase version of #7 to token list
            \tl_set:Nn \l_tmpa_tl { #8 }
            %% if it contains "every"
            \tl_if_in:NnTF \l_tmpa_tl { every } {
                %%% remove "every"
                \tl_remove_all:Nn \l_tmpa_tl { every }
                %%% save to int
                \int_set:Nn \l_tmpa_int { \l_tmpa_tl }
                %%% from left (> 0) or right (< 0)?
                \int_compare:nTF { \l_tmpa_int > 0 } {
                    %%%% draw marks from left
                    \int_step_inline:nnnn { \l_tmpa_int - 1 } { \l_tmpa_int } { #5 - 2 } {
                        \node at
                            ($(form~field~#6~##1.south~east)+(\dim_use:N \g_form_sep_dim / 2,0)$)
                            [every~form~divider] {};
                    }
                } {
                    %%%% draw marks from right
                    \int_step_inline:nnnn { #5 - 1 + \l_tmpa_int } { \l_tmpa_int } { 0 } {
                        \node at
                            ($(form~field~#6~##1.south~east)+(\dim_use:N \g_form_sep_dim / 2,0)$)
                            [every~form~divider] {};
                    }
                }
            } {
                %%% iterate throug comma list
                \clist_map_inline:nn { #8 } {
                    \node at
                        ($(form~field~#6~##1.south~east)+(\dim_use:N \g_form_sep_dim / 2,0)$)
                        [every~form~divider] {};
                }
            }
        }
    \end{scope}
}
% switch off expl3 syntax and @
\ExplSyntaxOff\makeatother

\tikzset{
    every form field/.style = {
        fill=white,
        inner sep=0pt,
        minimum height=4mm,
        align=center,
    },
    every form field middle/.style = {
        every form field,
        form field middle,
    },
    every form field start/.style = {
        every form field,
        form field start,
        anchor=south west,
    },
    every form field end/.style = {
        every form field,
        form field end,
    },
    every form label/.style = {
        fill=white, text=SEPADOrange,
        inner sep=1pt,
        outer sep=0pt,
        font=\tiny\sffamily\bfseries,
    },
    every form digit/.style = {
        anchor=base,
        font=\ttfamily,
        inner sep=0pt,
    },
    every form divider/.style = {
        fill=black,
        inner sep=0pt,
        outer sep=0pt,
        anchor=south,
        minimum width=\formdividerwidth,
        minimum height=\formdividerheight,
    },
}

\begin{document}
\begin{tikzpicture}
    % background
    \fill [SEPAOrange] (0,0) rectangle (15,12);
    % formlines
    \formline(1,10){25}{Bank}[Deutsche Bank Hamburg]
    \formline(1,9)[6mm]{5}{Number 1}[123456]
    \formline(1,8)[6mm]{5}{Number 2}[1234]
    \formline*(1,7){22}{IBAN 1}[DE00 2105 0170 0012 3456 78]<every 4>
        % dividers every 4th field from left
    \formline*(1,6){22}{IBAN 2}<every -4>% dividers every 4th from right
    \formline*(1,5){22}{IBAN 3}<2,5,10,15,20>% irregular dividers
\end{tikzpicture}
\end{document}

información relacionada