在数据工具中打印多个组行的范围

在数据工具中打印多个组行的范围

我使用这个代码这个答案

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{product.tex}
%Type =1,2...10
No,Type,Name,Description
1,1,A1,D1
2,1,A1,D2
3,1,A1,D3
30,1,A1,D30
31,2,A2,D31
131,2,A2,D131
132,3,A3,D132
133,3,A3,D133
134,3,A3,D134
249,4,A4,D249
1000,10,A10,D1000
\end{filecontents*}

\usepackage{datatool}

\DTLloaddb[autokeys=false]{products}{product.tex}

\newcommand{\printtype}[1]{%
  \par
  \section*{Type #1}
  \DTLforeach*
    [\DTLiseq{\Type}{#1}]% Condition
    {products}% Database
    {\No=No,\Type=Type,\Name=Name,\Description=Description}{%
    \noindent\Name \quad \Description\par
  }% 
}

\begin{document}

%Here is some text.

\printtype{1}

Some breaking text here.

\printtype{3}

And then some final text.

\end{document}

我想改变一些东西,请帮帮我。

我可以使用\DTLforeachatype=(1-3)然后为类型范围 1、2、3 创建 pdf 吗?或者任何其他解决方案。

我不想单独调用\printtype{1}\printtype{2}printtype{3}

谢谢

答案1

您可以使用以下expl3基于 的解决方案。它支持纯整数以及可能省略第一个和最后一个元素的范围:

\printtype{1}
\printtype{3}
\printtype{2-4}% all types between 2 and 4 (both inclusive)
\printtype{3-} % all types greater than or equal to 3
\printtype{-2} % all types lower than or equal to 2
\printtype{-}  % all types

负数也受支持。为了不与-范围语法的使用冲突,必须在括号内输入它们(非负数也可以,但不是必需的):

\printtype{{-1}}         % only type -1
\printtype{-{-1}}        % all types t for which  t ≤ -1
\printtype{{-1}-2}       % all types t for which -1 ≤ t ≤ 2
\printtype{{-1}-{2}}     % ditto
\printtype{{-+--1}-{2}}  % ditto (two minus signs cancel each other,
                         % because these are TeX 〈number〉s, actually)
\printtype{{-10}-{-1}}   % all types t for which -10 ≤ t ≤ -1

完整代码:

\RequirePackage{filecontents}
\begin{filecontents*}{product.tex}
No,Type,Name,Description
0,-1,A-1,D-1
1,1,A1,D1
2,1,A1,D2
3,1,A1,D3
30,1,A1,D30
31,2,A2,D31
131,2,A2,D131
132,3,A3,D132
133,3,A3,D133
134,3,A3,D134
249,4,A4,D249
1000,10,A10,D1000
\end{filecontents*}

\documentclass[twocolumn]{article}
\usepackage{datatool}
\usepackage{xparse}

\ExplSyntaxOn

\msg_new:nnn { lforti } { invalid-test-expression-syntax }
  { Invalid~syntax~for~test~expression~'\exp_not:n~{#1}'. }

\regex_const:Nn \l__lforti_intexpr_regex
  { \A (?| (\d+) | \{ ([\+\-]* \d+) \} ) \Z }
\regex_const:Nn \l__lforti_rangeexpr_regex
  { \A (?| (\d*) | \{ ([\+\-]* \d*) \} ) \-
       (?| (\d*) | \{ ([\+\-]* \d*) \} ) \Z }

% #1: value to test
% #2: test expression (integer or range)
\cs_new_protected:Npn \__lforti_check_match:nn #1#2
  {
    \regex_match:NnTF \l__lforti_rangeexpr_regex {#2}
      { \__lforti_check_range_match:nn {#1} {#2} }
      {
        \regex_match:NnTF \l__lforti_intexpr_regex {#2}
          { \__lforti_check_int_match:nn {#1} {#2} }
          { \msg_error:nnn { lforti } { invalid-test-expression-syntax } {#2} }
      }
  }

% #1: value to test
% #2: test expression (conforming to \l__lforti_intexpr_regex)
\cs_new_protected:Npn \__lforti_check_int_match:nn #1#2
  {
    % Extract the integer from the test expresion
    \tl_set:Nn \l_tmpa_tl {#2}
    \regex_replace_once:NnN \l__lforti_intexpr_regex { \1 } \l_tmpa_tl
    % Compare it to #1
    \int_compare:nNnTF {#1} = { \tl_use:N \l_tmpa_tl }
    { \use:c { @dtl@conditiontrue } }
    { \use:c { @dtl@conditionfalse } }
  }

\tl_new:N \l__lforti_crm_first_tl % “start part“ of a range expression
\tl_new:N \l__lforti_crm_last_tl  % “end part“ of a range expression
\bool_new:N \l__lforti_crm_ismatch_bool % result of the test

% #1: value to test
% #2: test expression (conforming to \l__lforti_rangeexpr_regex)
\cs_new_protected:Npn \__lforti_check_range_match:nn #1#2
  {
    \tl_set:Nn \l__lforti_crm_first_tl {#2}
    \regex_replace_once:NnN \l__lforti_rangeexpr_regex { \1 }
                            \l__lforti_crm_first_tl
    \tl_set:Nn \l__lforti_crm_last_tl {#2}
    \regex_replace_once:NnN \l__lforti_rangeexpr_regex { \2 }
                            \l__lforti_crm_last_tl

    \bool_set_true:N \l__lforti_crm_ismatch_bool

    \tl_if_empty:NF \l__lforti_crm_first_tl
      { % the "first" part of the range is non-empty, perform the test
        \int_compare:nNnT {#1} < { \tl_use:N \l__lforti_crm_first_tl }
          { \bool_set_false:N \l__lforti_crm_ismatch_bool }
      }

    \tl_if_empty:NF \l__lforti_crm_last_tl
      { % the "last" part of the range is non-empty, perform the test
        \int_compare:nNnT {#1} > { \tl_use:N \l__lforti_crm_last_tl }
          { \bool_set_false:N \l__lforti_crm_ismatch_bool }
      }

    \bool_if:NTF \l__lforti_crm_ismatch_bool
      { \use:c { @dtl@conditiontrue } }
      { \use:c { @dtl@conditionfalse } }
  }

\makeatletter

% Test function modeled after \DTLiseq
%
% #1: \Type or so (should expand to the integer subject to the test)
% #2: test expression (integer or range expression)
\NewExpandableDocumentCommand \lfortiIsMatch { m m }
  {
    \TE@throw
    % #1 and #2 will be fully expanded when \DTLforeach* checks the condition
    \exp_not:N \__lforti_check_match:nn {#1} {#2}
    \exp_not:N \if@dtl@condition
  }

% From this point on, up to \lforti@print@rbrace included: this is not needed
% for ”basic use” of my code. This allows one to print the test expression
% correctly in a title or so, without having to input it twice.
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nx }

% Store a version of #2 into #1 in a form that is suitable for printing.
%
% #1: token list variable; will be defined if necessary, and assigned locally
% #2: test expression, with the standard catcodes
\cs_new_protected:Npn \__lforti_prepare_testexpr_for_print:Nn #1#2
  {
    \tl_clear_new:N #1
    \tl_set:Nx #1 { \tl_to_str:n {#2} } % \detokenize (needed for the braces)

    \tl_replace_all:Nxn #1
      { \char_generate:nn { `- } { 12 } }
      { \lforti@print@nolig@dash }
    \tl_replace_all:Nxn #1
      { \char_generate:nn { `\{ } { 12 } }
      { \lforti@print@lbrace }
    \tl_replace_all:Nxn #1
      { \char_generate:nn { `\} } { 12 } }
      { \lforti@print@rbrace }
  }

\NewDocumentCommand \lforti@prepare@testexpr@for@print { m m }
  { \__lforti_prepare_testexpr_for_print:Nn #1 {#2} }

% Print a dash that can't participate in ligatures (definition inspired from
% LaTeX2e's \do@noligs)
\NewDocumentCommand \lforti@print@nolig@dash { }
  { \leavevmode \kern \z@ \char `- }

\NewDocumentCommand \lforti@print@lbrace { }
  { \leavevmode \char_generate:nn { `\{ } { 12 } }

\NewDocumentCommand \lforti@print@rbrace { }
  { \leavevmode \char_generate:nn { `\} } { 12 } }

\ExplSyntaxOff

% #1: test expression
\newcommand*{\printtype}[1]{%
  % Save the test expression #1 in a form that is suitable for printing in the
  % text---even in section titles written to the TOC. This little complication
  % is only useful to allow test expressions such as {-+--1}-{2} to be printed
  % correctly in a title and in the TOC without having to input them twice.
  \lforti@prepare@testexpr@for@print{\lforti@testexpr@for@print}{#1}%
  \section*{With test expression \texttt{%
      \lforti@testexpr@for@print}}

  \noindent
  \begin{tabular}{@{}ll@{}}
    \DTLforeach*
    [\lfortiIsMatch{\Type}{#1}]% Condition
    {products}% Database
    {\No=No,\Type=Type,\Name=Name,\Description=Description}{%
      \Name & \Description\\
    }%
  \end{tabular}
  \par
}

\makeatother

\DTLloaddb[autokeys=false]{products}{product.tex}

\begin{document}
\raggedbottom % just for presentation of the example, because page breakpoints
              % are scarce here...

\printtype{{-1}}                % only type -1
\printtype{1}
\printtype{2}
\printtype{3}
\printtype{4}
\printtype{10}

\newpage
\printtype{1-3}                 % types between 1 and 3, both inclusive
\printtype{2-3}                 % types between 2 and 3, both inclusive
\printtype{3-}                  % all types t for which 3 ≤ t
\printtype{-2}                  % all types t for which t ≤ 2

\newpage
\printtype{-}                   % all types
\printtype{10000-}              % types greated than or equal to 10000
\printtype{-{-1}}               % all types t for which  t ≤ -1
\printtype{{-1}-2}              % all types t for which -1 ≤ t ≤ 2
\printtype{{-1}-{2}}            % ditto
\printtype{{-+--1}-{2}}         % ditto (two minus signs cancel each other,
                                % because these are TeX 〈number〉s, actually)
\printtype{{-10}-{-1}}          % all types t for which -10 ≤ t ≤ -1

\end{document}

在第 1 页:

第 1 页


在第 2 页:

第 2 页

如果对于您的应用程序,您删除了在这里完成的测试表达式的特殊打印\section*(添加它是为了为示例提供良好的输出,而不需要输入中的任何冗余),您可能会摆脱一些东西:\__lforti_prepare_testexpr_for_print:Nn,,,和(如果您希望替换文本尽可能简短和简单,则\lforti@prepare@testexpr@for@print可以以 开头)。\lforti@print@nolig@dash\lforti@print@lbrace\lforti@print@rbrace\printtype\noindent

相关内容