Preencher caixas para formulários no TikZ

Preencher caixas para formulários no TikZ

Eu quero criar umFormulário de transferência bancária SEPA com IBAN

Como posso criar um campo de formulário com Ncampos, cada um com 5 mm de largura e separações como na imagem? campo de formulário

No momento eu uso uma solução alternativa com um loop for, mas isso torna o código difícil de manter. Finalmente preciso de uma função \formline{N}{cellwidth}{label}{value}para criar o formfield completo e preenchê-lo com um valor opcional: campo de formulário completo

O seguinte código está disponível emhttps://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} 

Responder1

uso

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

argumentos obrigatórios

  • coord: onde colocar a linha; a âncora é westdo primeiro campo.
  • N: número de campos.
  • label: nome da linha.

argumentos opcionais

  • *: ignore espaços em value.
  • field width: largura de um campo.
  • scope options: as opções são passadas para o {scope}.
  • value: preencha alguma coisa, deve conter apenasnormalpersonagens.
  • dividers: adicione divisórias entre arquivos; pode ser uma lista de vírgulas de números de arquivo ou every n( npode ser positivo ou negativo).

exemplos

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

exemplos

notas

  • Cada campo é um único nó e é nomeado com form field label n, onde labelé o valor do argumento e né o número do campo (começando em 0). Você pode usar esses nomes de nós para adicionar quadros ou algo assim.
  • Existem vários estilos TikZ que podem ser usados ​​para alterar a aparência.
  • Eu adicionei algumas explicações ao código –por favor pergunte se algo não estiver 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}

informação relacionada