当表格生成新页面时添加标题(发票使用 PDFtolatex)

当表格生成新页面时添加标题(发票使用 PDFtolatex)

我会尽量准确地解释我的问题,请随时向我询问更多详细信息:

  • 我目前正在使用 LateX 和模板工具包开发发票生成器,我知道它不是最佳的,但它是遗留代码,我们无法创建新的;

  • 我想在 pdf 文档的某个特定部分(即表格)的顶部添加一个横幅,当表格足够长以创建新页面时,我需要将此横幅放在表格第二页的顶部;

  • 我得到了多个依赖于服务/商品类型的模板,因此调试非常复杂,因为我永远不知道错误真正发生在哪个文件或行(是的,我使用了-file-line-error debug,但它显示var/tmp中编译的临时文件而不是我当前正在处理的文件);

问题 :这真的可能吗?对我来说,LaTex 只能用来设计科学文档,不能用来制作发票,而且包含文件的编译过程似乎运行得很糟糕。

我尝试过:制作一个包含不同模板部分的表格,表格标题看起来像横幅。问题是不同的模板部分也是表格,我遇到了多个错误,由于此发票生成器的架构,我无法解决这些错误,因为调试点位于临时编译的 pdf 中,而不是我所在的工作文件中。错误如下:

  1. 段落第 xxx--xxx 行中的 \hbox 未满(badness 10000);

  2. ./tempi6163.tex:723: } 太多。

欢迎提供任何提示、解决方法和建议,我确实不知道有谁除了论文文档之外使用过 LaTeX,但只是以非常基本的方式。

这是代码,警告它可能会吓到你:

发票布局骨架:

\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[frenchb]{babel}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage{underscore}
\usepackage{color}
\usepackage{colortbl}
\usepackage{xcolor}
\usepackage{transparent}
\usepackage{wallpaper}
\usepackage{atbegshi,picture}
\usepackage{lastpage}
\usepackage{longtable}
%\usepackage[top=[%- document_config.document_top -%],left=0.15cm,bottom=2.5cm,right=0.3cm]{geometry}

% Use this package below to modify document layout : https://texdoc.org/serve/geometry.pdf/0
\usepackage[top=2.5cm,left=0.15cm,bottom=2.5cm,right=0.3cm]{geometry}
\usepackage{setspace}
\usepackage{array}
\usepackage{avant}
\usepackage{hyperref}
\usepackage{booktabs}
\usepackage{multicol}
\usepackage{multirow}
\usepackage{makecell}
\usepackage{hhline}
\usepackage[nomessages]{fp}
\definecolor{labelcolor}{HTML}{E8E8E8}
[%- IF document_config.document_watermark %]
\usepackage{draftwatermark}
[%- END %]
[%- IF document_config.entity_ref == 'DCFORDATA' %]
\hypersetup{colorlinks=true,urlcolor=[HTML]{49906D},linkcolor=black}
[%- ELSE %]
\hypersetup{colorlinks=true,urlcolor=blue,linkcolor=black}
[%- END %]
% }}}
% {{{ definition de commandes specifiques
\newcounter{period}
[%- IF document_datas.info_client.bill_period_num %]
\setcounter{period}{[%- document_datas.info_client.bill_period_num -%]}
[%- ELSE %]
\setcounter{period}{1}
[%- END %]
%
% chargement des fichiers multi-langues
%
\input{[%- document_config.template_path -%]/jn_pdf_intl_defs.tex}
[% IF document_datas.headcell_type.head_type == 1 %]
\newcommand{\JNHeadCellTitle}{\Fr{Frais d'acc\`{e}s au Service}\En{Non-reccuring}}
[% ELSIF document_datas.headcell_type.head_type == 2 %]
\newcommand{\JNHeadCellTitle}{\Fr{N\'{e}goce}\En{Resale}}
[% ELSIF document_datas.headcell_type.head_type == 3 %]
\newcommand{\JNHeadCellTitle}{\Fr{FAS / N\'{e}goce}\En{Non-reccuring / Resale}}
[% ELSE %]
\newcommand{\JNHeadCellTitle}{\Fr{Frais d'acc\`{e}s au Service}\En{Non-reccuring}}
[% END %]
%
% definitions de commandes
%
%\renewcommand{\familydefault}{\sfdefault}
\renewcommand{\rmdefault}{phv} % Arial
\renewcommand{\sfdefault}{phv} % Arial
\renewcommand\textrangle{>}
\renewcommand\textlangle{<}
\renewcommand\arraystretch{1}
\renewcommand\footnotemark{}
\renewcommand\footnoterule{}
\newcommand{\HRule}{\rule{\linewidth}{0.1mm}}
\newcommand{\tabularnewline}{\\}
\newcommand{\tabularendbloc}{

    \medskip
    }
\newcommand{\csp}[1]{\hspace{#1mm}}
\newcommand{\cell}{&}
\newcommand{\hcell}[1]{\cell \hspace{#1mm}}
\newcommand{\price}[1]{\footnotesize #1}
\newcommand{\rprice}[1]{\multicolumn{1}{r|}{\footnotesize #1}}
\newcommand{\infoline}[2]{\multicolumn{#1}{c}{\footnotesize\textit{#2} } }
\newcommand{\infoprice}[2]{\multicolumn{#1}{r}{\footnotesize\textit{#2} } }
\newcommand{\infototalprice}[2]{\multicolumn{#1}{r}{#2} }
\newcommand{\emptyline}[1]{\multicolumn{#1}{r}{}}
\providecommand{\bloctitle}[1]{
    {\renewcommand{\arraystretch}{1.3}
        \footnotesize
        \setlength{\tabcolsep}{1mm}
        \begin{tabular}{|>{\raggedright}p{19.12cm}|}
        \hline
        \multicolumn{1}{|>{\columncolor{mycellcolor}}l|}{ \tabulartitlebox{19.12cm}{\LARGE \textbf{#1}} } \tabularnewline
        \hline
        \end{tabular} \tabularendbloc
    }
}
\providecommand{\blocsubtitle}[1]{
    {\renewcommand{\arraystretch}{1}
        \footnotesize
        \setlength{\tabcolsep}{1mm}
        \begin{tabular}{|>{\raggedright}p{19.12cm}|}
            \multicolumn{1}{l}{\multirow{-1}{19.12cm}{\large{\textbf{#1}} \dotfill}} \\
        \end{tabular} \tabularendbloc
    }
}
\providecommand{\tabulartitlebox}[2]{
    \makebox{
        \parbox{#1}{
            \vspace{0.1cm}
            \large{#2}
            \vspace{0.1cm}
        }
    }
}
%taille de la ram
\newcommand{\ramsize}[1]{
    \FPeval\sram{round((#1)/1024,0)}%
    \sram
}
%calcul prix*periode
\newcommand{\PPerPeriod}[2]{
        \FPeval\pperiod{round(\theperiod*(#1)*(#2),2)}%
        \pperiod
}
%calcul prix*periode
\newcommand{\QPerPeriod}[1]{
        \FPeval\pperiod{round(\theperiod*(#1),0)}%
        \pperiod
}
\newcommand{\PPerQuantity}[2]{
        \FPeval\qprice{round((#1)*(#2),2)}%
        \qprice
}
%prix unitaire 0.2f
\newcommand{\UnitPrice}[2][2]{
        \FPeval\pperiod{round(1*(#2),#1)}%
        \pperiod
}
%prix unitaire à 5 chiffres 0.5f
\newcommand{\UnitPriceFiveDigits}[2][5]{
        \FPeval\pperiod{round(1*(#2),#1)}%
        \pperiod
}
%total 0.2f
\newcommand{\TotalPrice}[2][2]{
        \FPeval\pperiod{round(1*(#2),#1)}%
        \pperiod
}
%ligne vide
\newcommand{\DSLineEmpty}{
    \cell
    \cell
    \cell
    \cell
    \cell
    \cell \tabularnewline
}
%ligne titre, nom Service sans prix)
\newcommand{\DSLineTitle}[1]{
    \rowcolor{mycellcolor}
    \normalsize{\textbf{#1}}
    \cell
    \cell
    \cell
    \cell
    \cell
    \cell \tabularnewline
}
%ligne rubrique (options, extremite etc..., sans prix)
\newcommand{\DSLineSubTitle}[2]{
    \csp{#1} \footnotesize{\textbf{#2}}
    \cell
    \cell
    \cell
    \cell
    \cell
    \cell \tabularnewline
}
%ligne texte (sans prix)
\newcommand{\DSLineSimpleText}[2]{
    \csp{#1} \footnotesize{#2}
    \cell
    \cell
    \cell
    \cell
    \cell
    \cell \tabularnewline
}
%ligne texte LABEL (sans prix)
\newcommand{\DSLineSimpleLabel}[2]{
    \cellcolor{labelcolor}\csp{#1} \footnotesize{#2}
    \cell
    \cell
    \cell
    \cell
    \cell
    \cell \tabularnewline
}
%ligne texte (prix fas)
\newcommand{\DSLineFasPrice}[4]{
    \csp{#1} \footnotesize{#2} \dotfill
    \cell \footnotesize{#3}
    \cell \footnotesize{\UnitPrice{#4}}
    \cell \footnotesize{\PPerQuantity{#3}{#4}}
    \cell
    \cell
    \cell \tabularnewline
}
\newcommand{\DSLineFasPriceFiveDigits}[4]{
    \csp{#1} \footnotesize{#2} \dotfill
    \cell \footnotesize{#3}
    \cell \footnotesize{\UnitPriceFiveDigits{#4}}
    \cell \footnotesize{\PPerQuantity{#3}{#4}}
    \cell
    \cell
    \cell \tabularnewline
}
%ligne texte (prix rec)
\newcommand{\DSLineRecPrice}[4]{
    \csp{#1} \footnotesize{#2} \dotfill
    \cell \dotfill
    \cell \dotfill
    \cell \dotfill
    \cell \footnotesize{#3}
    \cell \footnotesize{\UnitPrice{#4}}
    \cell \footnotesize{\PPerQuantity{#3}{#4}} \tabularnewline
}
\newcommand{\DSLineRecPriceFiveDigits}[4]{
    \csp{#1} \footnotesize{#2} \dotfill
    \cell \dotfill
    \cell \dotfill
    \cell \dotfill
    \cell \footnotesize{#3}
    \cell \footnotesize{\UnitPriceFiveDigits{#4}}
    \cell \footnotesize{\PPerQuantity{#3}{#4}} \tabularnewline
}
%ligne texte (prix rec)
\newcommand{\DSLineFasRecPrice}[6]{
    \csp{#1} \footnotesize{#2} \dotfill
    \cell \footnotesize{#3}
    \cell \footnotesize{\UnitPrice{#4}}
    \cell \footnotesize{\PPerQuantity{#3}{#4}}
    \cell \footnotesize{#5}
    \cell \footnotesize{\UnitPrice{#6}}
    \cell \footnotesize{\PPerQuantity{#5}{#6}} \tabularnewline
}
\newcommand{\DSLineFasRecPriceFiveDigits}[6]{
    \csp{#1} \footnotesize{#2} \dotfill
    \cell \footnotesize{#3}
    \cell \footnotesize{\UnitPriceFiveDigits{#4}}
    \cell \footnotesize{\PPerQuantity{#3}{#4}}
    \cell \footnotesize{#5}
    \cell \footnotesize{\UnitPriceFiveDigits{#6}}
    \cell \footnotesize{\PPerQuantity{#5}{#6}} \tabularnewline
}
\definecolor{mycellcolor}{gray}{0.95}
\setlength\arrayrulewidth{0.7pt}
\arrayrulecolor{black}
% }}}
% {{{ definition fond de page
\newcommand\BackgroundPic{
    \put(0,0){
        \parbox[b][\paperheight]{\paperwidth}{
            \vfill
            \centering
            [% IF NOT document_config.document_watermark -%]
            \includegraphics[width=\paperwidth,height=\paperheight,keepaspectratio]{[%- document_config.background_path -%]/[%- document_config.background_file -%]}%
            [%- END %]
            \vfill
        }
    }
}

\newcommand{\margin}[2] {
    \hspace{#1}\makebox{
        \parbox[t]{21cm}{
            #2
        }
    }
}
% }}}
% {{{ entete et pied de page en mode galerien
\AtBeginShipout{
    \AtBeginShipoutUpperLeftForeground{
        %link
        \small
        [%- IF document_config.header_url %]
    \put(16.2cm,-1.5cm){
            \makebox{
                [%- IF NOT document_config.document_watermark -%]
                \href{[%- document_config.document_head_url_link -%]}{[%- document_config.document_head_url_name -%]}
                [%- END -%]
            }
        }
        [%- END %]
    %foot address
        [%- IF document_config.footer ;
            IF document_datas.pdf_langage != 'FR' ;
                document_config.document_foot_address_infos = document_config.document_foot_address_infos.replace('au capital de', 'with a capital of');
            END %]
                \put(0.6cm,-\dimexpr\paperheight-1cm){
                        \makebox{
                                \parbox{\paperwidth-1cm}{
                    [%- IF NOT document_config.document_watermark -%]
                                        \centering
                                        \color[gray]{0.60}
                                        \footnotesize
                    \singlespacing{
                        [% document_config.document_foot_address -%] \\
                        [% document_config.document_foot_address_infos %]
                    }
                    [%- END -%]
                                }
                        }
        }   %End of 'foot address' block
        [%- END %]
                %pager
                \put(0.8cm,-\dimexpr\paperheight-1.1cm){
                        \makebox[19.5cm][r]{
                                \color{black}
                                \small
                                page \thepage / \pageref{LastPage}
                    }
        }   %End of 'pager' block
        %foot engagement
        \put(0.6cm,-\dimexpr\paperheight-2cm){
            \makebox{
                \parbox{\paperwidth-1cm}{
                    \centering
                    \footnotesize
                    \singlespacing{
                        [%- IF NOT document_config.document_watermark -%]
                        %
                        [%- IF document_datas.entity_contract == '' -%]
                        %
                        [% "bdc.cgv_accept" | trans %]\Fr{ [%- document_datas.header.engagment_entity -%]}\En{}.\\
                        [% "bdc.valid_30_days" | trans %]
                        %
                        [%- ELSE -%]
                        %
                        ~ \\
                        [% "bdc.contract_accept" | trans %] \textbf{[%- document_datas.entity_contract -%]}.
                        %
                        [%- END %]
                        %
                        [%- END %]
                    }
                }
            }
        }   %End of 'foot engagement' block
        %foot paraph
        \put(19.5cm, -29.4cm){
            \makebox{
            \normalfont{
                \tiny
                \transparent{0}
                doc\_PR
                }
            }
        }   %End of 'foot paraph' block
        }
    }   %End of 'AtBeginShipoutUpperLeftForeground' block
% }}}
% {{{ document pdf info et watermark
\pdfinfo{
    /Author ([%- document_config.document_author -%])
    /Title  ([%- document_config.document_title -%])
    /CreationDate (D:[%- document_config.document_date -%])
    /Subject ([%- document_config.document_subject -%])
    /Keywords ([%- document_config.document_keywords -%])
    /Creator (JNTools)
    /Producer ([%- document_config.document_author -%])
}
[% IF document_config.document_watermark -%]
%document_wathermark
\SetWatermarkText{[%- document_config.document_watermark_text -%]}
\SetWatermarkScale{[%- document_config.document_watermark_size -%]}
\SetWatermarkAngle{[%- document_config.document_watermark_angle -%]}
[% END -%]
% }}}
% {{{ contenu document
\begin{document}
    \AddToShipoutPicture{\BackgroundPic}
    \pagestyle{empty}
    \singlespacing
    \small
    [% INCLUDE $document_config.body_to_include %]
\end{document}
% }}}

发票正文:

# Customer information
INCLUDE 'bdc/informations.tt' ;
global.voice_grid_list = [] ;
global.storage_is_autosized = 0;
# List of services
INCLUDE 'bdc/description_services.tt' ;
# Sign bloc
IF NOT document_config.document_watermark ;
INCLUDE 'bdc/signature_engagement.tt' ;
END ;
# Grilles voix
IF global.voice_grid_list.size > 0 ;
    global.voice_grid_list_unique = global.voice_grid_list.unique;
    INCLUDE 'bdc/generics/voice_grid.tt' ;
END ;
# Grilles v5
IF document_datas.grids.size > 0 ;
    INCLUDE 'bdc/generics/grids.tt' ;
END ;
IF NOT document_config.document_watermark ;
    # SEPA Mandate
    IF (document_datas.entity_status == 'prospect' && document_datas.info_client.bill_type_payment == 'PRVLT' && document_datas.mandat.rendering == 'auto') || (document_datas.mandat.rendering == 'yes') ;
        INCLUDE 'bdc/mandat_prelevement.tt' ;
    END ;
    IF document_datas.lic_mobility == 'yes' ;
        INCLUDE 'bdc/lic_mobility.tt' ;
    END ;
    # CGV
    IF  ((document_datas.entity_status == 'prospect'
          && document_datas.info_client.bill_type_payment == 'PRVLT'
          && document_datas.cgv.rendering == 'auto')
         || (document_datas.cgv.rendering == 'yes'))
        && (document_datas.entity_contract == '');
        cgvfile = 'bdc/cgv_' _ document_datas.cgv.version _ '.tt' ;
        INCLUDE $cgvfile ;
        INCLUDE 'bdc/cgv_signature.tt' ;
    END ;
END ;
-%]

发票正文中包含的网格部分,我想要添加上面描述的横幅,对于每个 INCLUDE'grids/grid.tt',我想要在其顶部添加横幅,第一页除外:

[%# collect voice groups informations %]
[%
SET global.has_voice_groups = 0;
SET global.voice_group_defs = {};
SET global.voice_uuid_names = {};

FOREACH topgrid IN document_datas.grids;
    SET grid = topgrid.info;
    SET additional_info = topgrid.additional_info;

    INCLUDE 'grids/informations.tt';
%]
\vspace{0.1cm}
[% IF grid.rendering_mode == 'child'; %]
    \bloctitle{[% grid.grid_ref %] : [% "grids.type.${grid.grid_line_type_ref}" | trans %]}
[% ELSE; %]
    \bloctitle{[% grid.grid_ref %] : [% grid.name %]}
[% END; %]

[%
    SET additional_info = topgrid.additional_info;

    IF grid.rendering_mode == 'meta';
        engagement_coefs = grid.engagement_coefs;
        FOREACH grid IN topgrid.childs;
            SET additional_info = grid.additional_info;
            INCLUDE 'grids/grid.tt';
            IF engagement_coefs.${grid.grid_line_type_ref} ;
                INCLUDE 'grids/engagement_coefs.tt';
            END;
         END;
    ELSE;
        INCLUDE 'grids/grid.tt';
    END;
END;

IF global.has_voice_groups > 0;
    INCLUDE 'grids/generic/voice_groups.tt';
END;

IF NOT document_datas.is_preview;
    INCLUDE 'grids/signature.tt';
END;
-%]

在 INCLUDE 'grids/grid.tt' 中我尝试了以下操作:

% The banner I want to include on table format
\vspace{0.1cm}
{\renewcommand{\arraystretch}{1.2}
    \setlength{\LTleft}{0.50cm}
    \setlength{\tabcolsep}{1mm}
    \begin{longtable}{|>{\raggedright}p{11.1cm}|>{\raggedleft}p{0.65cm}|>{\raggedleft}p{1.3cm}|>{\raggedleft}p{1.5cm}|>{\raggedleft}p{0.65cm}|>{\raggedleft}p{1.3cm}|>{\raggedleft}p{1.5cm}|}

% I choose 4 column to test but is there a way to detect how many column are going to be included ?

  \multicolumn{4}{c}{
    [%- IF NOT document_config.document_watermark -%]
    \parbox[t]{19.55cm}{\HRule\\[0cm]
          \parbox[t]{7.7cm}{\footnotesize{\textbf{~\Fr{Responsable de compte}\En{Account Manager}~:~[%- document_datas.header.commercial -%]} } }
          \parbox[t]{5cm}{\vrule\footnotesize{\textbf{~\Fr{Date d'\'{e}mission}\En{Date}~:~}{[%- document_datas.header.date_emission -%]} } }
          [%- IF (document_datas.doctype == 'bdc') -%]
            \parbox[t]{6cm}{\vrule\footnotesize{\textbf{~\Fr{R\'{e}f\'{e}rence de commande}\En{PO Number}~:~}{[%- document_datas.header.bdc_ref -%]} } }
          [%- ELSE -%]
            [%- IF (document_datas.type_ent == 'client') AND (grid.is_signed) -%]
              \parbox[t]{6cm}{\vrule\footnotesize{\textbf{~\Fr{Date de signature}\En{Signature date}~:~}{[%- grid.signature_date -%]} } }
            [%- END -%]
          [%- END -%]
          \\[-0.2cm]\HRule\\
      }
    [%- END -%]
  }

%the different template which depend on type of services/goods
[% INCLUDE "grids/grid/${grid.grid_line_type_ref}.tt" %]


\endhead
\end{longtable}

下面是一个模板 (${grid.grid_line_type_ref}.tt) 的示例,我想在其中集成表格:

{\renewcommand{\arraystretch}{1.5}
    \setlength{\LTleft}{0.50cm}
    \setlength{\tabcolsep}{1mm}
        \begin{longtable}{|c|r|r|r|}
        \hline
        \rowcolor{mycellcolor}
        \multicolumn{1}{|c|}{\multirow{-1}{7cm}{\Fr{Type de ligne}\En{Line type}}}
        & \multicolumn{1}{r|}{\multirow{-1}{2cm}{[%- "grids.type.sfr-adsl.fas"|trans -%]}}
        & \multicolumn{1}{r|}{\multirow{-1}{2cm}{[%- "grids.type.sfr-adsl.abo"|trans -%]}}
        & \multicolumn{1}{r|}{\multirow{-1}{2cm}{[%- "grids.type.sfr-adsl.gtrs1"|trans -%]}}
        \\ [0.7ex]
        \hline
        \endfirsthead
        \hline
        \endfoot
        \hline
        \rowcolor{mycellcolor}
        \multicolumn{1}{|c|}{\multirow{-1}{7cm}{\Fr{Type de ligne}\En{Line type}}}
        & \multicolumn{1}{r|}{\multirow{-1}{2cm}{[%- "grids.type.sfr-adsl.fas"|trans -%]}}
        & \multicolumn{1}{r|}{\multirow{-1}{2cm}{[%- "grids.type.sfr-adsl.abo"|trans -%]}}
        & \multicolumn{1}{r|}{\multirow{-1}{2cm}{[%- "grids.type.sfr-adsl.gtrs1"|trans -%]}}
        \\ [0.7ex]
        \hline
        \endhead
        \infoprice{4}{[%- "grids.infos.all_prices_euros_ht"|trans -%]}
        \endlastfoot
        [% FOREACH object IN grid.objects %]
            \multicolumn{1}{|l|}{[% object.description %]}
            & \multicolumn{1}{r|}{\UnitPrice[2]{[%-object.fas-%]}}
            & \multicolumn{1}{r|}{\UnitPrice[2]{[%-object.abo-%]}}
            [% IF (object.gtrs1 == 0) %]
            & \multicolumn{1}{r|}{\Fr{Incluse}\En{Included}}
            [% ELSE %]
            & \multicolumn{1}{r|}{\UnitPrice[2]{[%-object.gtrs1-%]}}
            [% END %]
            \\
        [% END %]
        \hline
    \end{longtable}
}

相关内容