2

Using the code from How to check if a datatool db has an existing member with the same problem (build a datatool DB with unique strings) it works well as long if there is not an additional level (here via \DeclareDocumentCommand) with the same functionality. Now the solution dosen't recognize the ABC string and add it again to the DB. The definition \tmp should be fully expanded (xstring User’s manual). The result should be only one string ABC in the duplicates DB.

The strings I need to bring in are assigned to various definitions several times before ending in a DB (a simplified MWE below).

\documentclass{article}
\usepackage{datatool}
\usepackage{xparse,xstring}

\makeatletter
% Patch \DTLgetlocation to gobble the error
\let\ErrorFreeDTLgetlocation\DTLgetlocation
\patchcmd{\ErrorFreeDTLgetlocation}% <cmd>
  {\PackageError}% <search>
  {\@gobbletwo}% <replace>
  {}{}% <success><failure>
\def\@@dtlnovalue{\@dtlnovalue} 

\newcommand*{\DBKey}{Value}

\newcommand*{\AddMemberToDB}[2]{%
    % #1 = name of DB
    % #2 = member to be added to DB
    \DTLnewrow{#1}%
    \DTLnewdbentry{#1}{\DBKey}{#2}%
}
\newcommand*{\IfIsInDB}[4]{% %New definition!
    % #1 = name to be used for this duplicate's DB
    % #2 = member to check if in DB (gets added if not)
    % #3 = code to execute if member is in DB
    % #4 = code to execute if member is not in DB
    \ErrorFreeDTLgetlocation{\RowIndex}{\ColIndex}{#1}{#2}%
    \ifx\RowIndex\@@dtlnovalue
        #4%
        \AddMemberToDB{#1}{#2}%
    \else
        #3
    \fi
}
\makeatother

\DeclareDocumentCommand{\AddEntrytoDB}{m m}{
  \def\tmp{}
  \StrDel{#2}{ }[\tmp]% delete the spaces
  \IfIsInDB{#1}{\tmp}
    {CMD: \tmp is a duplicate}
    {CMD: \tmp\, added DB}
}

\begin{document}

  \def\ABC{A B C} % ABC string with spaces
  \def\varABC{}
  \StrDel{\ABC}{ }[\varABC]% delete the spaces

  \DTLnewdb{duplicates} % create new DB

  \AddMemberToDB{duplicates}{\varABC} % add ABC string w/o spaces to DB

  Current DB:\par % display the DB
  \DTLdisplaydb{duplicates}
  \medskip

  \IfIsInDB{duplicates}{\varABC} % check another ABC string w/o spaces
    {ABC is a duplicate}% Yes: is in
    {ABC added DB}% No: is not in, add it
  \par

  \AddEntrytoDB{duplicates}{\ABC} % add another ABC string via Command

  \medskip
  Current DB:\par % display the DB
  \DTLdisplaydb{duplicates}

\end{document}
5
  • I think you just need to add a \dtlexpandnewvalue to the \AddMemberToDB. I thought the code formatting looked familiar. :-) – Peter Grill Oct 22 '19 at 6:15
  • @Peter: Unfortunately \dtlexpandnewvalue dosen't help. Now there are 3x ABC in the DB. – Luis Potter Oct 22 '19 at 8:21
  • I think if you modify \IfIsInDB to include the line \edef\@ExpandedTarget{#2} and then use \@ExpandedTarget instead of #2 and replace the call to AddMemberToDB with \AddEntrytoDB, things work as desired. – Peter Grill Oct 22 '19 at 19:33
  • @Peter: In the first view it works well, but it looks that there is a different (expansion?) problem. Say we define \def\efg{efg} and add \AddEntrytoDB{duplicates}{\efg} to the document. The DB should now contain 2 entries, but every additional entry is a duplicate and only the last definition is in the DB. It looks that the DB stores the definition of '\@ExpandedTarget' and not it's value. – Luis Potter Oct 23 '19 at 10:42
  • I think I found at lest one problem: You need to compare to \@dtlnovalue, not \@@dtlnovalue. – Peter Grill Oct 24 '19 at 6:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.