0

I would like to check that a list of nodes loaded in a DTL database exist on the current page, where each node has a tikzmark. Including a \iftikzmarkoncurrentpage inside a \DTLforeach returns a compiler error:

Extra }, or forgotten \endgroup. }

Is there a better approach for this?

MWE:

\documentclass{article}
\usepackage{datatool}
\usepackage{pgf,tikz}
\usetikzlibrary{calc,arrows,positioning,tikzmark}
\begin{document}
    \DTLnewdb{nodes}
    \DTLnewrow{nodes}
    \DTLnewdbentry{nodes}{Node}{d}
    \begin{tikzpicture}
        \node (a) {a};
        \tikzmark{a}{(a)};
        \node[right=2cm of a] (b) {b}; 
        \iftikzmarkoncurrentpage{a}
            \draw (b)-- (a);
        \fi
        \DTLforeach{nodes}{\element=Node}{%
            \node[below=1cm of a] (\element){\element};
        }
    %This compiles correctly
    \end{tikzpicture}
\newpage
    \begin{tikzpicture}
        \node (c) {c};
        \tikzmark{c}{(c)};
        \DTLforeach{nodes}{\element=Node}{%
            \node[below=1cm of c] (\element){\element};
%           \iftikzmarkoncurrentpage{a}%This breaks
%               \draw (b) -- (a);
%           \fi
        }
    \end{tikzpicture}
\end{document}
3
  • Welcome to TeX.SE!
    – Mensch
    Commented Nov 21, 2021 at 23:40
  • I dont have errors with your MWE. I used pdfLaTeX. Commented Nov 22, 2021 at 8:13
  • @RaffaeleSantoro Did you uncomment the three lines with the comment "This breaks"?
    – gernot
    Commented Nov 22, 2021 at 9:30

1 Answer 1

0

It is not quite clear from your example what you actually want to achieve, as it contains problems such that it will not work even if \iftikzmarkoncurrentpage worked.

  1. Add the option remember picture to all tikzpicture environments that contain nodes that you want to reference from outside the tikzpicture, and also to all tikzpictures that refer to outside nodes. This means both tikzpictures in your example.

  2. Add the option overlay to all tikzpictures that reference nodes in other tikzpictures. This means the second tikzpicture in your example.

    overlay tells tikz not to compute the bounding box, which is necessary as you want to draw outside the tikzpicture. However, this also means that the picture has no default width, so you will have to tell tikz how to compute the bounding box. But this is a different question if you don't know how to do it (and needs more context).

  3. You have to run LaTeX at least twice to propagate the node positions.

  4. Do not use the same node name in several tikzpictures, if the names are public (because of remember picture). In your example, you define d in both pictures.

  5. Finally, \iftikzmarkoncurrentpage apparently does not work within \DTLforeach. The latter expands its argument, and \iftikzmarkoncurrentpage is not expandable. You can check it with the smaller example

    \documentclass{article}
    \usepackage{datatool,tikz}
    \usetikzlibrary{tikzmark}
    \begin{document}
        \DTLnewdb{nodes}
        \DTLnewrow{nodes}
        \DTLnewdbentry{nodes}{Node}{d}
            \DTLforeach{nodes}{\element=Node}{%
            \iftikzmarkoncurrentpage{a}\fi
        }
    \end{document}
    

    As a workaround, use the \if... before the loop to define a command that you then can use within the loop.

    \iftikzmarkoncurrentpage{a}%
      \def\linetoa{\draw (\element) -- (a);}
    \else
      \let\linetoa\relax
    \fi
    \DTLforeach{nodes}{\element=Node}{%
       \node[below=1cm of c] (\element){\element};
       \linetoa
    }
    

Here is the code of the complete example.

\documentclass{article}
\usepackage{datatool}
\usepackage{tikz}
\usetikzlibrary{calc,arrows,positioning,tikzmark}
\begin{document}
    \DTLnewdb{nodes}
    \DTLnewrow{nodes}
    \DTLnewdbentry{nodes}{Node}{d}
    \begin{tikzpicture}[remember picture]
        \node (a) {a};
        \tikzmark{a}{(a)};
        \node[right=2cm of a] (b) {b}; 
        \iftikzmarkoncurrentpage{a}
            \draw (b)-- (a);
        \fi
    \end{tikzpicture}
\newpage
    \begin{tikzpicture}[remember picture,overlay]
        \node (c) {c};
        \tikzmark{c}{(c)};
        \iftikzmarkoncurrentpage{a}%
          \def\linetoa{\draw (\element) -- (a);}
        \else
          \let\linetoa\relax
        \fi
        \DTLforeach{nodes}{\element=Node}{%
           \node[below=1cm of c] (\element){\element};
           \linetoa
        }
    \end{tikzpicture}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .