5

In a big report with many subfiles and authors, I am using the datatool package to write out some data collected across the document. At the end of the document, the data should be stored in a CSV file with \DTLsavedb. For this, I am currently using the \AtEndDocument hook.

The problem is that this does not work reliably. From looking into the datatool sources, I think this is because datatool does not write out to the file \immediate, so that the writing is delayed until shipout time. However, if there is no remaining content to shipout at the end of the document, the file never gets written.

I could try to patch datatool to use \immediate, however, I with respect to performance, the delayed writing is probably a good thing. So a better solution would probably be to somehow make sure that at the end of the document all outstanding data gets written independently from the shipout routine? Or maybe there is a "last page hook" I could use instead of \AtEndDocument?

\documentclass{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{datatool}
\usepackage{lipsum}

\AtBeginDocument{%
  \DTLgnewdb{importantguys}%
}
\AtEndDocument{%
  \DTLsavedb{importantguys}{importantguys.csv}%
}

\newcommand{\importantguy}[2]{%
  \DTLnewrow{importantguys}%
  \DTLnewdbentry{importantguys}{firstname}{#1}%
  \DTLnewdbentry{importantguys}{surname}{#1}%
  \paragraph{#1 #2:}%
}

\begin{document}
  \lipsum
  \importantguy{Foo}{Bar} does cool stuff.
  \importantguy{Computer}{Mouse} is really important for the project.
  \lipsum
  \importantguy{Becky}{Brewer} helps to keep us running.
  \clearpage
\end{document}
  • The main problem is that when LaTeX issues its final \clearpage to clear all queues and possibly shipout other pages, it's not known whether an actual \shipout will be performed. One could think of using \AtVeryEndDocument (package atveryend) and changing there datatool's \write to \immediate\write. A \write that's not \immediate is performed only during shipout. – egreg Oct 8 '13 at 9:30
6

Deferred writing and package atenddvi

Package atenddvi provides the hook \AtEndDvi to get stuff written at the shipout of the last page. Two LaTeX runs are needed at least for knowing, which is the last page. Despite the name the output type DVI, PDF or whatever does not matter.

Immediate writing and package atveryend

If your data does not contain data that require deferred writing, then \DTLsaveddb can be patched to immediate mode as shown in the following example. It also uses package atveryend with hook \AtVeryEnd for the case that someone adds an important guy via \AtEndDocument:

\documentclass{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{datatool}
\usepackage{lipsum}
\usepackage{atveryend}

\AtBeginDocument{%
  \DTLgnewdb{importantguys}%
}
\AtVeryEndDocument{%
  \begingroup
    \let\SavedOpenout\openout
    \let\SavedWrite\write
    \def\openout{\immediate\SavedOpenout}%
    \def\write{\immediate\SavedWrite}%
    \DTLsavedb{importantguys}{importantguys.csv}%
  \endgroup
}

\newcommand{\importantguy}[2]{%
  \DTLnewrow{importantguys}%
  \DTLnewdbentry{importantguys}{firstname}{#1}%
  \DTLnewdbentry{importantguys}{surname}{#2}%
  \paragraph{#1 #2:}%
}

\begin{document}
  \lipsum
  \importantguy{Foo}{Bar} does cool stuff.
  \importantguy{Computer}{Mouse} is really important for the project.
  \lipsum
  \importantguy{Becky}{Brewer} helps to keep us running.
  \clearpage
\end{document}

File importantguys.csv:

firstname,surname
Foo,Bar
Computer,Mouse
Becky,Brewer
  • Thanks Heiko, that seems to work! BTW: The first thing I was wondering was if \AtEndDvi does also work in PDF mode. To avoid confusion, I edited the respective sentence from your package docs into the answer. – Daniel Oct 14 '13 at 8:28

Your Answer

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

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