Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In the following MWE (which make no real sense, but which is minimal:) ) I have two nested DTLforeach loops. The values displayed in the line "%for debugging" show the expected behaviour for the DTLforeach loops: the first loop runs on all entries (4 rows). For each of these rows, the second loop runs on rows. But the command \DTLreplaceentryforrow{a}{xx}, which should replace the value of a by "xx", does not do it. Notice, that if you move \DTLreplaceentryforrow{a}{xx} outside from the inner loop, then it works as expected. Thus, there seems to be a problem with this command in a nested loop. (REM: according to datatools-documentation, DTLforeach can be nested up to three times.)

\documentclass[12pt]{article}
\usepackage{datatool}
\begin{document}
\DTLnewdb{table}
\DTLrowcount{table}

\DTLnewrow{table}
\DTLnewdbentry{table}{a}{1}
\DTLnewdbentry{table}{b}{oui}
\DTLnewrow{table}
\DTLnewdbentry{table}{a}{2}
\DTLnewdbentry{table}{b}{oui}
\DTLnewrow{table}
\DTLnewdbentry{table}{a}{1}
\DTLnewdbentry{table}{b}{non}
\DTLnewrow{table}
\DTLnewdbentry{table}{a}{2}
\DTLnewdbentry{table}{b}{non}

\section{original table}

\DTLdisplaydb{table}

\section{modified table}

\DTLforeach{table}{\a=a,\b=b}{%
\DTLforeach{table}{\aa=a,\bb=b}{%
a= \a , b= \b , aa=\aa , bb=\bb % only for debugging

\DTLreplaceentryforrow{a}{xx}
}
}

\DTLdisplaydb{table}
\end{document}
share|improve this question

2 Answers 2

up vote 5 down vote accepted

The problem probably arises due to internal handling of the replacement and grouping of loops.
If your outer loop is never in a write position (will never change the contents of the table.) you can use the starred version, which is read only and will not save the state of the table.

I.e.

\DTLforeach*{table}{\a=a,\b=b}{%
    \DTLforeach{table}{\aa=a,\bb=b}{%
        a= \a , b= \b , aa=\aa , bb=\bb % only for debugging
        \DTLreplaceentryforrow{a}{xx}
    }
}

this will produce what you want. I guess it is a security of the table loop, to not be able to double foreach of the same table. I suggest the above strategy. However if you wish to change in both loops other methods has to be employed. I do not know how to do this.

share|improve this answer
    
good hint ! thanks –  nicolas roy Jan 23 '12 at 15:47

Not a solution, but at least an explanation from Nicola Talbot (author of datatool):

The contents of a database are stored in a single token register (toks) with markers indicating rows and cells. When the database is edited, the contents of the token are split into three parts: the part that needs replacing, everything that comes before and everything that comes after. The updated database is then formed from merging the before part, the replacement and the after part. To improve efficiency, the \DTLforeach loop makes a copy of the current row and manipulates just the row copy rather than the entire database. At the end of the iteration, the current row in the database is replaced with the copy. In the nested loop in the example, when both loops are editing the same row of the database, there are two copies of that row, one being manipulated by the outer loop, the other by the inner loop. At the end of the inner loop, the database is updated with the inner copy, but when the outer loop reaches the end of its iteration, it substitutes its row, which overwrites the effect of the inner loop.

share|improve this answer
    
very instructive. –  nicolas roy Jan 24 '12 at 14:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.