\documentclass{article}
\usepackage{datatool}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.csv}
1,a
2,a
2,a
2,a
3,a
3,a
4,a
4,a
4,a
4,a
5,a
5,a
6,a
6,a
7,a
\end{filecontents*}
\DTLloaddb[noheader,keys={num}]{raw}{\jobname.csv}
\DTLnewdb{hist}
\newcounter{numcnt}
% fill table "hist"
\newcommand*{\SaveRow}{%
\ifnum\value{numcnt}>0 %
\DTLnewrow{hist}%
\begingroup
\dtlexpandnewvalue
\DTLnewdbentry{hist}{num}{\oldnum}%
\DTLnewdbentry{hist}{count}{\the\value{numcnt}}%
\endgroup
\fi
}%
\newcommand*{\oldnum}{}%
\setcounter{numcnt}{0}%
\DTLforeach*{raw}{\num=num}{%
\ifx\oldnum\num
\stepcounter{numcnt}%
\else
\SaveRow
\setcounter{numcnt}{1}%
\let\oldnum\num
\fi
}%
\SaveRow
% write table "hist" with header
\DTLsetdelimiter{,}
\DTLsavedb{hist}{\jobname.hist}
\begin{document}
Hello World% nothing would be written without output page
\end{document}
Result is database hist or the file \jobname.hist:
num,count
1,1
2,3
3,2
4,4
5,2
6,2
7,1
Remarks:
- When writing a file, package
datatool does not use \immediate, therefore
a database file is writen at the next output of a page and is not written at all
after the last page.
Variation, writing file \jobname.hist without headers:
\documentclass{article}
\usepackage{datatool}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.csv}
1,a
2,a
2,a
2,a
3,a
3,a
4,a
4,a
4,a
4,a
5,a
5,a
6,a
6,a
7,a
\end{filecontents*}
\DTLloaddb[noheader,keys={num}]{raw}{\jobname.csv}
\DTLnewdb{hist}
\newcounter{numcnt}
% fill table "hist" and manually write it
\makeatletter
\immediate\openout\@dtl@write=\jobname.hist\relax
% reusing datatool's write handle
\newcommand*{\SaveRow}{%
\ifnum\value{numcnt}>0 %
\DTLnewrow{hist}%
\begingroup
\dtlexpandnewvalue
\DTLnewdbentry{hist}{num}{\oldnum}%
\DTLnewdbentry{hist}{count}{\the\value{numcnt}}%
\immediate\write\@dtl@write{\oldnum,\the\value{numcnt}}%
\endgroup
\fi
}%
\newcommand*{\oldnum}{}%
\setcounter{numcnt}{0}%
\DTLforeach*{raw}{\num=num}{%
\ifx\oldnum\num
\stepcounter{numcnt}%
\else
\SaveRow
\setcounter{numcnt}{1}%
\let\oldnum\num
\fi
}%
\SaveRow
\immediate\closeout\@dtl@write
\makeatother
\begin{document}
\end{document}
Again the result is database hist and file \jobname.hist, but this time the file is written without headers:
1,1
2,3
3,2
4,4
5,2
6,2
7,1
Remarks:
- The (internal) write handle of package
datatool is reused, because write handles are a very limited resource.
- The data base is written immediately (
\immediate\write) and not delayed to the
next page output.