# Datatool \DTLnewdbentry does not take value for key column

I am quite frustrated about the following: Iam writing a document with requirements which have requirement IDs as a beginning of a line (I'm using these in an enumerate environment). I want to collect the requirements in a DATATOOL database and output the requirements at the end of the document in a table.

Whatever I tried, the following macro works fine in the sense that it adds a requirement line with proper requirement ID into the enumerate environment, but it odes NOT add output the requirement ID in the column "reqKey" when I display the table at the end - I have the suspicion that something with the variable access to "\@reqID" does not work.

Any help very much appreciated.

\DTLnewdb{reqs}
\DTLnewdbcolumn{reqs}{reqKey}
\DTLnewdbcolumn{reqs}{reqText}

...

\makeatletter
\newcommand\req@nomen@count[1]{%
\@ifundefined{c@#1}
{% the counter doesn't exist
\newcounter{#1}\setcounter{#1}{1}%
}
{% the counter exists
\stepcounter{#1}%
}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% markers for requirements
\newcommand{\req}[2][0]{%
\req@nomen@count{#2}%
\ifthenelse{\equal{#1}{0}}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\@reqID}{}
\newcommand{\itemReq}[3][0]{
\DTLnewrow{reqs}
\ifthenelse{\equal{#1}{0}}
{\renewcommand{\@reqID}{\req{#2}}}
{\renewcommand{\@reqID}{\req{#1}{#2}}}
\item[\textcolor{blue}{[\@reqID]}]#3%
\DTLnewdbentry{reqs}{reqKey}{\@reqID}
\DTLnewdbentry{reqs}{reqText}{#3}
}
\makeatother
...
\begin{document}
\begin{enumerate}
\itemReq{reqCategory}{Requirement text, can be lengthy}
\end{enumerate}
...
\DTLdisplaylongdb{reqs}
\end{document}


The output of this code looks like this:

Edit as requested I want to share an minimal adjusted (according to esdd's solution) example:

\documentclass{article}
\usepackage{enumitem}
\usepackage{fmtcount}
\usepackage{datatool}

\DTLnewdb{reqs}

\makeatletter
% macro creating a new latex counter for every new entitiy name and requirement
\newcommand\req@nomen@count[1]{%
\@ifundefined{c@#1}
{% the counter doesn't exist
\newcounter{#1}\setcounter{#1}{1}%
}%
{% the counter exists
\stepcounter{#1}%
}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% markers for requirements
\newcommand{\req}[2][0]{%
\ifthenelse{\equal{#1}{0}}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\@reqID}{}

\newcommand{\itemReq}[3][0]{
\req@nomen@count{#2}%
\DTLnewrow{reqs}%
\ifthenelse{\equal{#1}{0}}
{\renewcommand{\@reqID}{\req{#2}}}
{\renewcommand{\@reqID}{\req[#1]{#2}}}%
\item[{[\@reqID]}]#3%
\dtlexpandnewvalue%
\DTLnewdbentry{reqs}{reqKey}{\@reqID}%
\DTLnewdbentry{reqs}{reqText}{#3}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\begin{enumerate}
\itemReq{CategoryA}{Requirement category 1 text 1.}
\itemReq{CategoryA}{Requirement category 1 text 2.}
\itemReq{CategoryB}{Requirement category 1 text 1.}
\end{enumerate}
\DTLdisplaydb{reqs}
\end{document}


This code has another problem: the IDs in the table are always the ID with the highest counter in the text.

• Welcome to TeX.SX! Can you please expand the code snippet that you have posted to a full minimal working example. A MWE should compile and be as small as possible to demonstrate your problem. it's much easier to help you if we have working code to start from. – Andrew Jun 19 '17 at 16:50

Update

\dtlexpandnewvalue seems to expand only once. So you have to use an additional argument for \req that takes \arabic{<countername>}.

\documentclass{article}
\usepackage{fmtcount}
\usepackage{datatool}

\DTLnewdb{reqs}

\makeatletter
% macro creating a new latex counter for every new entitiy name and requirement
\newcommand\req@nomen@count[1]{%
\@ifundefined{c@#1}
{% the counter doesn't exist
\newcounter{#1}\setcounter{#1}{1}%
}%
{% the counter exists
\stepcounter{#1}%
}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% markers for requirements
\newcommand{\req}[3][0]{%
\ifthenelse{\equal{#1}{0}}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\@reqID}{}

\newcommand{\itemReq}[3][0]{%
\req@nomen@count{#2}%
\DTLnewrow{reqs}%
\ifthenelse{\equal{#1}{0}}
{\renewcommand{\@reqID}{\req{#2}{\arabic{#2}}}}
{\renewcommand{\@reqID}{\req[#1]{#2}{\arabic{#2}}}}%
\item[{[\@reqID]}]#3%
\dtlexpandnewvalue%
\DTLnewdbentry{reqs}{reqKey}{\@reqID}%
\DTLnewdbentry{reqs}{reqText}{#3}%
}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\begin{enumerate}
\itemReq{CategoryA}{Requirement category 1 text 1.}
\itemReq{CategoryA}{Requirement category 1 text 2.}
\itemReq{CategoryB}{Requirement category 1 text 1.}
\end{enumerate}
\DTLdisplaydb{reqs}
\end{document}


Result:

But maybe you can avoid the nesting of commands:

\documentclass{article}
\usepackage{fmtcount}
\usepackage{datatool}

\DTLnewdb{reqs}

\makeatletter
\newcommand{\@reqID}{}
\newcommand{\itemReq}[3][0]{%
\@ifundefined{c@#2}{\newcounter{#2}}{}%
\stepcounter{#2}%
\DTLnewrow{reqs}%
\ifthenelse{\equal{#1}{0}}
\item[{[\@reqID]}]#3%
\dtlexpandnewvalue%
\DTLnewdbentry{reqs}{reqKey}{\@reqID}%
\DTLnewdbentry{reqs}{reqText}{#3}%
}
\makeatother

\begin{document}
\begin{enumerate}
\itemReq{CategoryA}{Requirement category 1 text 1.}
\itemReq{CategoryA}{Requirement category 1 text 2.}
\itemReq{CategoryB}{Requirement category 1 text 1.}
\end{enumerate}
\DTLdisplaydb{reqs}
\end{document}


The result is the same as above.

With the following code only the last values of the counters are used, when the database is printed.

datatool does not expand added values by default. When you display the table the original definition is valid. So all printed keys are empty.

To expand the values while added to database reqs use \dtlexpandnewvalue inside the definition of \@regID.

Additionally I think you do not want to step the counter in \req because \req is excecuted twice per \@regID: onces for printing as argument of \item and once for adding to the database.

And I have changed another row of the code, because \req takes an optional and an mandatory argument (not two mandantory arguments).

In the following example I also use package enumitem to define an own listenvironment reqDecsr.

\documentclass{article}
\usepackage{fmtcount}
\usepackage{xcolor}
\usepackage{longtable}
\usepackage{enumitem}
\newlist{reqDescr}{description}{1}
\setlist[reqDescr]{leftmargin=8em}

\usepackage{datatool}

\DTLnewdb{reqs}

\makeatletter
\newcommand\req@nomen@count[1]{%
\@ifundefined{c@#1}
{% the counter doesn't exist
\newcounter{#1}\setcounter{#1}{1}%
}
{% the counter exists
\stepcounter{#1}%
}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% markers for requirements
\newcommand{\req}[2][0]{%
%\req@nomen@count{#2}% <- remove it here
\ifthenelse{\equal{#1}{0}}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\@reqID}{}
\newcommand{\itemReq}[3][0]{%
\req@nomen@count{#2}% <- use it here
\DTLnewrow{reqs}%
\ifthenelse{\equal{#1}{0}}
{\renewcommand{\@reqID}{\req{#2}}}
{\renewcommand{\@reqID}{\req[#1]{#2}}}% <- changed
\item[\textcolor{blue}{[\@reqID]}]#3%
\DTLnewdbentry{reqs}{reqKey}{\@reqID}%
\DTLnewdbentry{reqs}{reqText}{#3}%
}
\makeatother
\begin{document}
\begin{reqDescr}
\itemReq{reqCategory}{Requirement text, can be lengthy.}
\end{reqDescr}
...
\DTLdisplaylongdb{reqs}
\end{document}


Result:

If the entries are longer, then you can replace

\DTLdisplaylongdb{reqs}


by something like

\begin{longtable}{lp{.65\textwidth}}
\textbf{reqKey}&\multicolumn{1}{l}{\textbf{reqText}}\\