switch case 中的 Ifoddpage 语句

switch case 中的 Ifoddpage 语句

继续讨论主题 tcolorbox:奇数页和偶数页的特定宽度和高度设置前页或后页的距离可变

我想根据宏的扩展(\C这里,由我的代码设置datatool)以及我们是在奇数页还是偶数页有条件地设置长度:

\C = 1 & ifoddpage = true  => \xLength = 2cm, \yLength = 1.5cm
\C = 1 & ifoddpage = false => \xLength = 4cm, \yLength = 2cm
\C = 2 & ifoddpage = true  => \xLength = 3cm, \yLength = 2cm
\C = 2 & ifoddpage = false => \xLength = 5cm, \yLength = 3cm
\C = 3 & ifoddpage = true  => \xLength = 4cm, \yLength = 3cm
\C = 3 & ifoddpage = false => \xLength = 4cm, \yLength = 1.5cm
\C = 10...

以下是基于以上链接代码的最少代码:

\documentclass{article}
\usepackage{datatool}
\usepackage[strict]{changepage}
\usepackage{filecontents}
\usepackage{tcolorbox}
\usepackage[absolute,overlay]{textpos}
\usepackage{xcolor}
\begin{filecontents*}{test1.csv}
Acol, Bcol,Ccol
Ax,Bx,1
Ay,By,3
A1,B22,1
A2,B44,2
A3,B11,3
A4,B55,4
\end{filecontents*}

\DTLloaddb{mydata1}{test1.csv}

\newlength{\xlengthForOddPages}
\newlength{\xlengthForEvenPages}
\newlength{\ylengthForOddPages}
\newlength{\ylengthForEvenPages}

\setlength{\xlengthForOddPages}{2cm}
\setlength{\xlengthForEvenPages}{10cm}
\setlength{\ylengthForOddPages}{1.5cm}
\setlength{\ylengthForEvenPages}{5cm}

\newif\ifmyoddpage              % always set globally, contrary to \ifoddpage

\newcommand*{\xpageDependent}{%
  \ifmyoddpage
    \expandafter
    \xlengthForOddPages
  \else
    \expandafter
    \xlengthForEvenPages
  \fi
}

\newcommand*{\ypageDependent}{%
  \ifmyoddpage
    \expandafter
    \ylengthForOddPages
  \else
    \expandafter
    \ylengthForEvenPages
  \fi
}

\newcommand*{\mycheckoddpage}{%
  \checkoddpage
  \global\let\ifmyoddpage=\ifoddpage
}

\newlength{\xLength}
\newlength{\yLength}

\begin{document}

\DTLforeach*{mydata1}{\A=Acol,\B=Bcol,\C=Ccol}%
{%
\begin{tcolorbox}[phantom={\mycheckoddpage},
                  width=\xpageDependent,height=\ypageDependent,
                  title={Title}]
  \C
\end{tcolorbox}
% --> Here, \xLength and \yLength should be set according
%     to the conditions described above. <--
\begin{textblock*}{5cm}(\xLength,\yLength)
\color{red} text abc
\end{textblock*}

\newpage
}
\end{document}

提前致谢。

答案1

如果我正确理解了您的需求,那么以下内容应该可以满足您的要求:

\documentclass{article}
\usepackage{datatool}
\usepackage[strict]{changepage}
\usepackage{filecontents}
\usepackage{tcolorbox}
\usepackage[absolute,overlay]{textpos}
\usepackage{xcolor}
\usepackage{xparse}

\begin{filecontents*}{test1.csv}
Acol, Bcol,Ccol
Ax,Bx,1
Ay,By,3
A1,B22,1
A2,B44,2
A3,B11,3
\end{filecontents*}
% If you include a line such as 'A4,B55,4' without saying how \xLength and
% \yLength should be set in this case, you'll get the error message:
%
%   Package lforti Error: Encountered value '4', but no case was written for it.

\DTLloaddb{mydata1}{test1.csv}

\newlength{\xlengthForOddPages}
\newlength{\xlengthForEvenPages}
\newlength{\ylengthForOddPages}
\newlength{\ylengthForEvenPages}

\setlength{\xlengthForOddPages}{2cm}
\setlength{\xlengthForEvenPages}{10cm}
\setlength{\ylengthForOddPages}{1.5cm}
\setlength{\ylengthForEvenPages}{5cm}

\newif\ifmyoddpage              % always set globally, contrary to \ifoddpage

\newcommand*{\xpageDependent}{%
  \ifmyoddpage
    \expandafter
    \xlengthForOddPages
  \else
    \expandafter
    \xlengthForEvenPages
  \fi
}

\newcommand*{\ypageDependent}{%
  \ifmyoddpage
    \expandafter
    \ylengthForOddPages
  \else
    \expandafter
    \ylengthForEvenPages
  \fi
}

\newcommand*{\mycheckoddpage}{%
  \checkoddpage
  \global\let\ifmyoddpage=\ifoddpage
}

\ExplSyntaxOn

\msg_new:nnn { lforti } { unhandled-value }
  { Encountered~value~'\exp_not:n~{#1}',~but~no~case~was~written~for~it. }

\tl_new:N \l__lforti_cond_length_setup_conds_tl
\seq_new:N \l__lforti_cond_length_setup_tmpa_seq
\seq_new:N \l__lforti_cond_length_setup_tmpb_seq

% Flexible length setup that may depend on whether it is called on an odd page
% or on an even page.
%
% #1: a LaTeX length command (or a TeX \skipdef token) to set according to
%     #2 and #3
% #2: the value to test against
% #3: a comma list describing the different cases:
%
%     {
%       {value_1, length-for-odd-pages, length-for-even-pages},
%       {value_2, length-for-odd-pages, length-for-even-pages},
%       ...
%       {value_n, length-for-odd-pages, length-for-even-pages},
%     }
%
% #2 is compared against value_1, value_2, ..., value_n to determine a
% matching “line”, then length command #1 is set to the length-for-odd-pages or
% length-for-even-pages of the matching line, depending on whether the label set
% by \checkoddpage (used at the beginning of the function) is located on an
% odd page or on an even page.
\cs_new_protected:Npn \lforti_cond_length_setup:Nnn #1#2#3
  {
    \checkoddpage               % make sure it is used on the relevant page
    \seq_set_from_clist:Nn \l__lforti_cond_length_setup_tmpa_seq {#3}
    \tl_clear:N \l__lforti_cond_length_setup_conds_tl

    \seq_map_inline:Nn \l__lforti_cond_length_setup_tmpa_seq
      {
        \seq_set_from_clist:Nn \l__lforti_cond_length_setup_tmpb_seq {##1}
        \tl_put_right:Nx \l__lforti_cond_length_setup_conds_tl
          {
            % Value to check against
            { \seq_item:Nn \l__lforti_cond_length_setup_tmpb_seq { 1 } }
            { % Corresponding setup code for #1
              \exp_not:n { \skip_set:Nn #1 }
                {
                  \seq_item:Nn
                    \l__lforti_cond_length_setup_tmpb_seq
                    { \ifoddpage 2 \else 3 \fi }
                }
            }
          }
      }

    % Handle value #2 according to the cases described by
    % \l__lforti_cond_length_setup_conds_tl, which was assembled from #3
    \str_case:nVF {#2} \l__lforti_cond_length_setup_conds_tl
      { \msg_error:nnn { lforti } { unhandled-value } {#2} }
  }

\cs_generate_variant:Nn \lforti_cond_length_setup:Nnn { Nx }

% Same as \lforti_cond_length_setup:Nnn (see above), except that the second
% argument will be fully expanded (\lforti_cond_length_setup:Nnn will only see
% the *result* of this expansion in its #2).
\NewDocumentCommand \lforticondlengthsetup { m m m }
  {
    \lforti_cond_length_setup:Nxn #1 {#2} {#3}
  }

\ExplSyntaxOff

\newlength{\xLength}
\newlength{\yLength}

\begin{document}

\DTLforeach*{mydata1}{\A=Acol,\B=Bcol,\C=Ccol}%
{%
\lforticondlengthsetup{\xLength}{\C}{%
  {1, 2cm, 4cm}, % When \C expands to 1, use 2cm on odd pages, 4cm on even pages
  {2, 3cm, 5cm}, % When \C expands to 2, use 3cm on odd pages, 5cm on even pages
  {3, 4cm, 4cm}, % When \C expands to 3, use 4cm on all pages
}%
\lforticondlengthsetup{\yLength}{\C}{% analogous setup for \yLength
  {1, 1.5cm, 2cm},
  {2, 2cm, 3cm},
  {3, 3cm, 1.5cm},
}%
\begin{textblock*}{5cm}(\xLength,\yLength)
  \color{blue!50!black}%
  \noindent
  \texttt{\string\xLength} = \the\xLength\\
  \texttt{\string\yLength} = \the\yLength
\end{textblock*}

\begin{tcolorbox}[phantom={\mycheckoddpage},
                  width=\xpageDependent,height=\ypageDependent,
                  title={Title}]
  \C
\end{tcolorbox}

\newpage
}

\end{document}

以下是每个页面的顶部:

第 1 页


第2页


第 3 页


第 4 页


第 5 页

我的代码依赖于我调用的灵活长度设置命令\lforticondlengthsetup。此命令要求其第一个参数是 LaTeX 长度命令(或 TeX\skipdef标记)。它完全展开其第二个参数,并将结果与​​第三个参数中指定的每个子列表的第一个元素进行比较。例如,\xLength\yLength按以下方式设置以遵循您问题中的规范:

\lforticondlengthsetup{\xLength}{\C}{%
  {1, 2cm, 4cm}, % When \C expands to 1, use 2cm on odd pages, 4cm on even pages
  {2, 3cm, 5cm}, % When \C expands to 2, use 3cm on odd pages, 5cm on even pages
  {3, 4cm, 4cm}, % When \C expands to 3, use 4cm on all pages
}%
\lforticondlengthsetup{\yLength}{\C}{% analogous setup for \yLength
  {1, 1.5cm, 2cm},
  {2, 2cm, 3cm},
  {3, 3cm, 1.5cm},

您必须确保此类长度设置命令在使用\xLength和的同一页面上发出\yLength。我上面提供的完整文档中应该是这种情况。

长度值( 的第三个参数中每个子列表的第二个和第三个元素\lforticondlengthsetup)可以是任何有效的 LaTeX3 〈skip 表达式〉。例如,只要满足以下条件,以下代码就是有效的:

  • \xLength\yLength已声明\newlength

  • \someMacro递归扩展为1,或foo,或(在您的示例中,此角色由扩展到位于文件第三列的值的宏bar baz扮演)。\C.csv

\lforticondlengthsetup{\yLength}{\someMacro}{
  {1, 0.7\xLength, 2cm plus 0.1cm minus 0.2cm},
  {foo, 2cm plus 1fill, 0pt plus 3fill},
  {bar baz, 3cm plus 1fil minus 0.2fill, 1.5cm},
}

最后,由于\checkoddpage使用标签/引用机制,请不要忘记您需要编译几次(通常只需两次)才能获得可靠的结果!

相关内容