diff options
author | Karl Berry <karl@freefriends.org> | 2007-07-16 16:32:39 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2007-07-16 16:32:39 +0000 |
commit | 84f780af7172e3bd7ea028cd54d13f07711a0821 (patch) | |
tree | ec051cae11857b2c66a505d7fcf084f36dcf3ea6 /Master/texmf-dist/doc/latex/csvtools | |
parent | 1b0d01e91a7b4080895db481fb57b9b8ed53d887 (diff) |
csvtools 1.24 (3jul07)
git-svn-id: svn://tug.org/texlive/trunk@4620 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/latex/csvtools')
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/README | 15 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/csvtools.html | 806 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/csvtools.pdf | bin | 199065 -> 0 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/csvtools.pl | 1305 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/doc/CHANGES | 29 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/doc/csvtools.pdf | bin | 0 -> 225188 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/doc/manual.html | 1615 | ||||
-rwxr-xr-x | Master/texmf-dist/doc/latex/csvtools/script/csvtools.pl | 1995 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/source/csvtools.dtx | 2536 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/source/csvtools.ins | 23 |
10 files changed, 6206 insertions, 2118 deletions
diff --git a/Master/texmf-dist/doc/latex/csvtools/README b/Master/texmf-dist/doc/latex/csvtools/README index 6134501469f..d0e9175ea0c 100644 --- a/Master/texmf-dist/doc/latex/csvtools/README +++ b/Master/texmf-dist/doc/latex/csvtools/README @@ -1,11 +1,12 @@ -LaTeX Package : csvtools v 1.1 +LaTeX Package : csvtools v 1.24 -Last Modified : 19 Oct 2004 +Last Modified : 3 July 2007 Author : Nicola Talbot Files : csvtools.dtx - documented source file csvtools.ins - installation script + csvtools.pl - Perl script The csvtools package allows you to repeatedly perform a set of LaTeX commands on data in each row @@ -13,21 +14,21 @@ of a comma separated variable (CSV) file. This can be used for mail merging, generating tables etc. Examples given in documentation. -Version 1.1 has the new command \CSVtolongtable (analogous to \CSVtotabular) -and a Perl script. See documentation for details. - To extract the code, do: latex csvtools.ins -This will create the files csvtools.sty (package) and csvtools.pl (accompanying -Perl script.) +This will create the files csvtools.sty, csvpie.sty and csvsort.sty. +These files should be place somewhere on TeX's search path. To extract the documentation, do: latex csvtools.dtx latex csvtools.dtx +(If you want the documented source code as well, remove the command +\OnlyDescription from csvtools.dtx) + Alternatively, if you use pdflatex instead of latex, the documentation will have hyperlinks. diff --git a/Master/texmf-dist/doc/latex/csvtools/csvtools.html b/Master/texmf-dist/doc/latex/csvtools/csvtools.html deleted file mode 100644 index 3e0937c4d80..00000000000 --- a/Master/texmf-dist/doc/latex/csvtools/csvtools.html +++ /dev/null @@ -1,806 +0,0 @@ -<html> -<title>csvtools.sty v 1.1</title> -<body> -<a href=http://theoval.cmp.uea.ac.uk/~nlct>Dr Nicola Talbot</a> | -<a href=http://www.cmp.uea.ac.uk/>School of Computing Sciences</a> | -<a href=http://www.uea.ac.uk/>University of East Anglia</a> - -<h1>csvtools.sty v1.1 : A LaTeX2e Package Providing Access to Data Saved in a CSV File</h1> - -<hr> -<h2>Contents</h2> -<ul> -<li><a href=#intro>Introduction</a> -<li><a href=#mailmerge>Mail Merging and Similar Applications</a> -<li><a href=#csv2tab>Converting CSV file into a tabular environment</a> -<li><a href=#longtable>Converting CSV file into a longtable environment</a> -<li><a href=#counters>Associated Counters</a> -<li><a href=#crossref>Cross-Referencing</a> -<li><a href=#save>Saving Entries</a> -<li><a href=#perl>The csvtools.pl Perl Script</a> -<li><a href=#drawbacks>Bugs/Drawbacks/``Features''</a> -</ul> - -<h2>Examples</h2> -<ul> -<li><a href=#ex:mail>Example 1 (Mail Merging)</a> -<li><a href=#ex:ps>Example 2 (Multiple Figures)</a> -<li><a href=#ex:field>Example 3 (Mail Merging using <tt>\field</tt>)</a> -<li><a href=#ex:tab1>Example 4 (Aligning Data from a CSV file)</a> -<li><a href=#ex:tab2>Example 5 (Adding Lines)</a> -<li><a href=#ex:tab3>Example 6 (Added Complexity)</a> -<li><a href=#ex:longtab>Example 7 (Using a longtable environment)</a> -<li><a href=#ex:stripy>Example 8 (Stripy Table)</a> -<li><a href=#ex:mail2>Example 9 (More Mail Merging)</a> -<li><a href=#ex:ref1>Example 10 (Labelling within <tt>\applyCSVfile</tt>)</a> -<li><a href=#ex:ref2>Example 11 (Labelling within <tt>\applyCSVfile</tt>)</a> -<li><a href=#ex:timetogrowth>Example 12 (Labelling within <tt>\CSVtotabular</tt>)</a> -<li><a href=#ex:t2g2>Example 13 (Labelling within <tt>\CSVtotabular</tt>)</a> -<li><a href=#ex:index>Example 14 (Saving Entries)</a> -<li><a href=#ex:perl>Example 15 (csvtools.pl - Aligning Data)</a> -</ul> -<hr> - -<h2><a name=intro>Introduction</a></h2> - The <tt>csvtools</tt> package allows you to repeatedly perform - a set of LaTeX commands on data in each row - of a comma separated variable (CSV) file. - This can be used for mail merging, generating - tables etc. - -<h2><a name=mailmerge>Mail Merging and Similar Applications</a></h2> - -<tt>\applyCSVfile[</tt><em>n</em><tt>]{</tt><em>filename</em><tt>}{</tt><em>text</em><tt>}</tt> -<p> - Letters can be generated using data given in - each line from <em>filename</em>. - If the CSV file contains a header row, the - unstarred version of <tt>\applyCSVfile</tt> should - be used, otherwise the starred version <tt>\applyCSVfile*</tt> - should be used. The optional argument <em>n</em> - specifies on which line the actual data (not header line) - starts. The unstarred version defaults to line 2 - (the header row is always assumed to be on line 1) - and the starred version defaults to 1. -<p> -With the unstarred version, the entries in the header row - are used to generate commands of the form - <tt>\insert</tt><em>identifier</em> (See <a href=#itm:insert>Note 1</a>) - to access corresponding elements - in the row currently being processed. For example, - suppose the first line of the CSV file looks like: -<pre> -Name,Address,Time,Date -</pre> - then the commands <tt>\insertName</tt>, <tt>\insertAddress</tt>, - <tt>\insertTime</tt> and <tt>\insertDate</tt> are - created, allowing you to use the entries in the first, - second, third and fourth columns of the current row. - If the header text contains non-alphabetical characters, - e.g. <tt>Full Name</tt>, then you will need to use - <tt>\insertbyname{</tt><em>text</em><tt>}</tt>, - e.g. <tt>\insertbyname{Full Name}</tt>. - -<h3><a name=ex:mail>Example 1 (Mail Merging)</a></h3> - Suppose there is a file called <tt>details.csv</tt> that has the - following contents: -<pre> -Name,Address,Time,Date -Miss A. Person,1 The Road\\The Town\\AB1 2XY,15.00,4th May 2004 -Mr A. N. Other,2 The Road\\The Town\\AB1 2XY,15.30,11th May 2004 -</pre> - then the following code can be used to generate a letter for each person - in the CSV file: -<pre> -\applyCSVfile{details.csv}{% -\begin{letter}{\insertName\\\insertAddress} -\opening{Dear \insertName} - -You are invited to an interview at \insertTime\ on the \insertDate. - -\closing{Yours Sincerely} -\end{letter}} -</pre> - Note that you could also use <tt>\insertbyname{Name}</tt> etc instead - of <tt>\insertName</tt> etc. Also note that you need to specify the - file extension when specifying the filename. - -<h3><a name=ex:ps>Example 2 (Multiple Figures)</a></h3> - -Suppose <tt>details.csv</tt> looks like: -<pre> -File,Caption -circle.ps,A Circle -rectangle.ps,A Rectangle -triangle.ps,A Triangle -</pre> - - Assuming that the files <tt>circle.ps</tt>, <tt>rectangle.ps</tt> - and <tt>triangle.ps</tt> exist, then the following code will - generate a figure for each graphics file (the - <tt>graphicx</tt> package will be needed): -<pre> -\applyCSVfile{sample3.csv}{ -\begin{figure} -\centerline{\includegraphics{\insertFile}} -\caption{\insertCaption} -\end{figure}} -</pre> - Note that in this example, you can't use <tt>\insertbyname{File}</tt>. - (See <a href=#itm:psbyname>Note 3</a>) -<p> -<tt>\applyCSVfile*[</tt><em>n</em><tt>]{</tt><em>filename</em><tt>}{</tt><em>text</em><tt>}</tt> -<p> -In this case the CSV file has no header row, so - there are no <tt>\insert</tt><em>identifier</em> or <tt>\insertbyname{</tt><em>label</em><tt>}</tt> commands available, - instead, the command <tt>\field{</tt><em>col</em><tt>}</tt> should be used, - where <em>col</em> is the column number. - -<h3><a name=ex:field>Example 3 (Mail Merging using <tt>\field</tt>)</a></h3> - - Suppose there is a file called <tt>details.csv</tt> that has the - following contents: -<pre> -Miss A. Person,1 The Road\\The Town\\AB1 2XY,15.00,4th May 2004 -Mr A. N. Other,2 The Road\\The Town\\AB1 2XY,15.30,11th May 2004 -</pre> - then the following code can be used to generate a letter for each person - in the CSV file: -<pre> -\applyCSVfile*{details.csv}{% -\begin{letter}{\field{1}\\\field{2}} -\opening{Dear \field{1}} - -You are invited to an interview at \field{3}\ on the \field{4}. - -\closing{Yours Sincerely} -\end{letter}} -</pre> - -<h2><a name=csv2tab>Converting CSV file into a tabular environment</a></h2> - -<tt>\CSVtotabular{</tt><em>filename</em><tt>}{</tt><em>col-align</em><tt>}{</tt><em>first</em><tt>}{</tt><em>middle</em><tt>}{</tt><em>last</em><tt>}</tt> -<p> -<em>filename</em> is the name of the CSV file which must have a header row on line 1, - <em>col-align</em> is the column alignment argument that gets passed - to the <tt>tabular</tt> environment, <em>first</em> - is the code for the first line, <em>middle</em> is the code - for the middle lines and <em>last</em> is the code for the last line. - This is best demonstrated with an example. - -<h3><a name=ex:tab1>Example 4 (Aligning Data from a CSV file)</a></h3> - -Suppose the file <tt>sample.csv</tt> looks like: -<pre> -Name,Assignment 1,Assignment 2,Total -A. Smith,80,70,150 -B. Jones,60,80,140 -J. Doe,85,75,160 -,75,75,150 -</pre> - then the following code can be used to align the data: -<pre> -\CSVtotabular{sample.csv}{lccc}{% -\bfseries Name & -\bfseries Assignment 1& -\bfseries Assignment 2& -\bfseries Total\\}{% -\insertName & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal\\}{% - & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal} -</pre> - The result of this code is shown in - <a href=#tab:ex1>Table 1</a>. (Note that <tt>\CSVtotabular</tt> only - puts the data in a <tt>tabular</tt> environment not in a table). -<p> -<table> -<a name=tab:ex1><caption align=top>Table 1 : Example 4</caption></a> -<tr><th>Name</th> -<th>Assignment 1</th> -<th>Assignment 2</th> -<th>Total</th></tr> -<tr><td>A. Smith</td><td>80</td><td>70</td><td>150</td></tr> -<tr><td>B. Jones</td><td>60</td><td>80</td><td>140</td><tr> -<tr><td>J. Doe</td><td>85</td><td>75</td><td>160</td></tr> -<tr><td> </td><td>75</td><td>75</td><td>150</td></tr> -</table> -<p> -<tt>\ifnextrowlast{</tt><em>last-code</em><tt>}{</tt><em>not-last-code</em><tt>}</tt> -<p> - The command <tt>\ifnextrowlast</tt> can be used to vary what happens - on the last but one row. The following example illustrates - this by placing <tt>\hline\hline</tt> after the penultimate row. - -<h3><a name=ex:tab2>Example 5 (Adding Lines)</a></h3> -<pre> -\CSVtotabular{sample.csv}{|l|ccc|}{% -\hline\bfseries Name & -\bfseries Assignment 1& -\bfseries Assignment 2& -\bfseries Total\\\hline\hline}{% -\insertName & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal -\ifnextrowlast{\\\hline\hline}{\\}}{% - & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal\\\hline} -</pre> - -<h3><a name=ex:tab3>Example 6 (Added Complexity)</a></h3> - - In this example, <tt>\multicolumn</tt> is used to override - the column specifier for the first column in the - last row. -<pre> -\CSVtotabular{sample2.csv}{|l|ccc|}{% -\hline\bfseries Name & -\bfseries Assignment 1 & -\bfseries Assignment 2 & -\bfseries Total\\\hline\hline -}{% -\insertName & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal -\ifnextrowlast{\\\hline\multicolumn{1}{l|}{}}{\\} -}{% - & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal\\\cline{2-4} -} -</pre> - Notice that instead of placing <tt>\multicolumn{1}{l|}{}</tt> - at the start of the final argument, it is instead - placed in the first argument to <tt>\ifnextrowlast</tt> (See - <a href=#itm:noalign>Note 4</a>). - -<h2><a name=longtable>Converting CSV file into longtable environment</a></h2> - -<tt>\CSVtolongtable{</tt><em>filename</em><tt>}{</tt><em>col-align</em><tt>}{</tt><em>first</em><tt>}{</tt><em>middle</em><tt>}{</tt><em>last</em><tt>}</tt> -<p> -The command <tt>\CSVtolongtable</tt> works in the same way as <tt>\CSVtotabular</tt> but - creates a <tt>longtable</tt> environment instead of a <tt>tabular</tt> environment. - -<h3><a name=ex:longtab>Example 7 (Using a longtable environment)</a></h3> -<p> -Suppose the CSV file in the previous example, contains, say, 100 entries. -This will no longer fit onto one page, so it would be better to use -<tt>\CSVtolongtable</tt> instead. For example: -<pre> -\CSVtolongtable{sample.csv}{|l|ccc|}{% -\caption{Student Marks}\label{tab:students}\\ -\hline -\bfseries Name & -\bfseries Assignment 1 & -\bfseries Assignment 2 & -\bfseries Total\\\hline -\endfirsthead -\caption[]{Student Marks}\\ -\hline -\bfseries Name & -\bfseries Assignment 1 & -\bfseries Assignment 2 & -\bfseries Total\\\hline -\endhead -\hline -\multicolumn{3}{r}{\em Continued on next page} -\endfoot -\hline -\endlastfoot}{% -\insertName & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal -\ifnextrowlast{\\\hline\hline}{\\}}{% - & \insertbyname{Assignment 1} & - \insertbyname{Assignment 2} & -\insertTotal\\} -</pre> - -<h2><a name=counters>Associated Counters</a></h2> - - Within the <tt>\CSVtotabular</tt>, <tt>\CSVtolongtable</tt> and <tt>\applyCSVfile</tt> commands, there are two - counters, <tt>csvlinenum</tt> and <tt>csvrownumber</tt>. - The former, <tt>csvlinenum</tt>, is the current line number in the CSV - file, whereas the latter, <tt>csvrownumber</tt>, is the current - data row. Of the two counters, <tt>csvrownumber</tt> is likely to be - the most useful. - -<h3><a name=ex:stripy>Example 8 (Stripy Table)</a></h3> - - The package <tt>colortbl</tt> defines the command <tt>\rowcolor</tt> - which enables you to specify the row colour. Suppose - you want a stripy table this can be achieved as follows (this is designed as an example - of how to use the package, not incouragement to produce garish tables): - -<pre> -\CSVtotabular{sample2.csv}{lccc}{% -\rowcolor{green}\bfseries Name & -\bfseries Assignment 1 & -\bfseries Assignment 2 & -\bfseries Total\\\rowcolor{blue} -}{% -\insertName & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal -\ifthenelse{\isodd{\value{csvrownumber}}}{% -\\\rowcolor{blue}}{\\\rowcolor{green}} -}{% - & -\insertbyname{Assignment 1} & -\insertbyname{Assignment 2} & -\insertTotal -} -</pre> - -<h3><a name=ex:mail2>Example 9 (More Mail Merging)</a></h3> - - This is an example of mail merging where the letter reference - is generated from <tt>csvrownumber</tt>. The CSV file is - as used in the <a href=#ex:mail>earlier example</a>. -<pre> -\applyCSVfile{details.csv}{% -\begin{letter}{\insertName\\\insertAddress} -\opening{Dear \insertName} - -\textbf{Ref : } interview.\thecsvrownumber - -You are invited to an interview at \insertTime\ on the \insertDate. - -\closing{Yours Sincerely} -\end{letter}} -</pre> - - <h2><a name=crossref>Cross-Referencing</a></h2> - - Labels can be generated using the standard - <tt>\label</tt> command, but you will need some way - to make each label unique. <a href=#ex:ref1>Example 10</a> - does this by using <tt>\thecsvrownumber</tt>, - whereas <a href=#ex:ref2>Example 11</a> uses <tt>\insert</tt><em>identifier</em>. - -<h3><a name=ex:ref1>Example 10 (Labelling within <tt>\applyCSVfile</tt>)</a></h3> - - <a href=#ex:ps>Example 2</a> can be modified to - label each figure: -<pre> -\applyCSVfile{sample3.csv}{ -\begin{figure} -\centerline{\includegraphics{\insertFile}} -\caption{\insertCaption} -\label{fig:pic\thecsvrownumber} -\end{figure}} -</pre> - This example uses - <tt>\label{fig:pic\thecsvrownumber}</tt>, so the first figure generated - by this <tt>\applyCSVfile</tt> command will have the label <tt>fig:pic1</tt>, - the second <tt>fig:pic2</tt> etc. - -<h3><a name=ex:ref2>Example 11 (Labelling within <tt>\applyCSVfile</tt>)</a></h3> - - Modifying the previous example, we now have: -<pre> -\applyCSVfile{sample3.csv}{ -\begin{figure} -\centerline{\includegraphics{\insertFile}} -\caption{\insertCaption} -\label{fig:\insertFile} -\end{figure}} -</pre> - The labels for each figure are now: - <tt>fig:circle.ps</tt>, <tt>fig:rectangle.ps</tt> - and <tt>fig:triangle.ps</tt>, respectively. - -<h3><a name=ex:timetogrowth>Example 12 (Labelling within <tt>\CSVtotabular</tt>)</a></h3> - - This example is slightly more complicated. - The CSV file, <tt>data.csv</tt> looks like: -<pre> -Incubation Temperature,Incubation Time,Time to Growth -40,120,40 -40,90,60 -35,180,20 -</pre> -The following code generates a table using the data - with an additional column that generates the experiment - number. (See <a href=#itm:csvrownumber>Note 9</a>.) -<pre> -\begin{table} -\caption{Time to Growth Experiments} -\label{tab:exp} -\vspace{10pt} -\centering -\CSVtotabular{data.csv}{cccc}{% -% Header Row -\bfseries Experiment & -\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & -\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & -\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\}{% -% Middle Rows -\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} -\thecsvrownumber & -\insertbyname{Incubation Temperature} & -\insertbyname{Incubation Time} & -\insertbyname{Time to Growth} \\}{% -% Final Row -\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} -\thecsvrownumber & -\insertbyname{Incubation Temperature} & -\insertbyname{Incubation Time} & -\insertbyname{Time to Growth}} -\par -\end{table} - -It can be seen from Table~\ref{tab:exp}, that -Experiment~\ref{exp:35:180} had the shortest time to growth. -</pre> - - In this example, each experiment has the corresponding label - <tt>exp:</tt><em>Incubation Temperature</em><tt>:</tt><em>Incubation Time</em> - so the first experiment has label <tt>exp:40:120</tt>, the - second experiment has the label <tt>exp:40:90</tt> and the - third experiment has the label <tt>exp:35:180</tt>. - - <a href=#tab:t2g>Table 2</a> shows the resulting table for - this example. -<p> -<table> -<caption align=top><a name=tab:t2g>Time to Growth Experiments</a></caption> -<tr><th align=center>Experiment </th> -<th align=center>Incubation<br> Temperature </th> -<th align=center>Incubation<br> Time </th> -<th align=center>Time<br> to<br> Growth</th></tr> -<tr><td align=center> 1 </td><td align=center> 40 </td><td align=center> 120 </td><td align=center> 40 </td></tr> -<tr><td align=center> 2 </td><td align=center> 40 </td><td align=center> 90 </td><td align=center> 60 </td></tr> -<tr><td align=center> 3 </td><td align=center> 35 </td><td align=center> 180 </td><td align=center> 20 </td></tr> -</table> - -<p> - The following example is more refined in that it - takes advantage of the fact that the time to growth data consists - of integers only, so the experiment with the maximum growth can be - determined by LaTeX. - -<h3><a name=ex:t2g2>Example 13 (Labelling within <tt>\CSVtotabular</tt>)</a></h3> - -<pre> -\newcounter{maxgrowth} -\newcounter{incT} % incubation temperature -\newcounter{inct} % incubation time - -\begin{table} -\caption{Time to Growth Experiments} -\label{tab:exp} -\vspace{10pt} -\centering -\CSVtotabular{data.csv}{cccc}{% -% Header row -\bfseries Experiment & -\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & -\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & -\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\}{% -% Middle rows -\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} -\thecsvrownumber & -\insertbyname{Incubation Temperature} & -\insertbyname{Incubation Time} & -\insertbyname{Time to Growth}% -\ifthenelse{\value{maxgrowth}<\insertbyname{Time to Growth}}{% -\setcounter{maxgrowth}{\insertbyname{Time to Growth}}% -\setcounter{incT}{\insertbyname{Incubation Temperature}}% -\setcounter{inct}{\insertbyname{Incubation Time}}}{}% -\\}{% -% Last row -\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} -\thecsvrownumber & -\insertbyname{Incubation Temperature} & -\insertbyname{Incubation Time} & -\insertbyname{Time to Growth}% -\ifthenelse{\value{maxgrowth}<\insertbyname{Time to Growth}}{% -\setcounter{maxgrowth}{\insertbyname{Time to Growth}}% -\setcounter{incT}{\insertbyname{Incubation Temperature}}% -\setcounter{inct}{\insertbyname{Incubation Time}}}{}% -} -\par -\end{table} - -As can be seen from Table~\ref{tab:exp}, -Experiment~\ref{exp:\theincT:\theinct} -had the maximum time to growth, with -incubation time \theinct, -incubation temperature \theincT\ and -time to growth, \themaxgrowth. -</pre> - -<h2><a name=save>Saving Entries</a></h2> - - Entries can be saved using the command: -<p> - <tt>\csvSaveEntry[</tt><em>counter</em><tt>]{</tt><em>identifier</em><tt>}</tt> -<p> - where <em>counter</em> is a LaTeX counter, by default <tt>csvrownumber</tt>, - and <em>identifier</em> is the header entry. The entry - can then be used with the command:<p> - <tt>\csvGetEntry{</tt><em>counter</em><tt>}{</tt><em>identifier</em><tt>}</tt><p> - The following example illustrates the use of these commands. - -<h3><a name=ex:index>Example 14 (Saving Entries)</a></h3> - - This example illustrates how you can use one CSV - file to access data in other CSV files. - This example has several CSV files: -<p> - File <tt>index.csv</tt>: -<pre> -File,Temperature,NaCl,pH -exp25a.csv,25,4.7,0.5 -exp25b.csv,25,4.8,1.5 -exp30a.csv,30,5.12,4.5 -</pre> - File <tt>exp25a.csv</tt>: -<pre> -Time,Logcount -0,3.75 -23,3.9 -45,4.0 -</pre> - File <tt>exp25b.csv</tt>: -<pre> -Time,Logcount -0,3.6 -60,3.8 -120,4.0 -</pre> - File <tt>exp30a.csv</tt>: -<pre> -Time,Logcount -0,3.73 -23,3.67 -60,4.9 -</pre> - - It is not possible to nest <tt>\CSVtotabular</tt>, <tt>\CSVtolongtable</tt> and <tt>\applyCSVfile</tt>, - so if you need to go through <tt>index.csv</tt> and use each file - named in there, you can first go through <tt>index.csv</tt> storing - the information using <tt>\csvSaveEntry</tt> as follows: -<pre> -\newcounter{maxexperiments} -\applyCSVfile{sample5.csv}{% -\stepcounter{maxexperiments} -\csvSaveEntry{File} -\csvSaveEntry{Temperature} -\csvSaveEntry{NaCl} -\csvSaveEntry{pH} -} -</pre> - The counter <tt>maxexperiments</tt> simply counts the number of - entries in <tt>index.csv</tt>. - The entries can now be used to generate a table for each - file listed in <tt>index.csv</tt> (the <tt>\whiledo</tt> command is - defined in the <tt>ifthen</tt> package): -<pre> -\newcounter{experiment} - -\whiledo{\value{experiment}<\value{maxexperiments}}{% -\stepcounter{experiment} -\begin{table} -\caption{Temperature = \protect\csvGetEntry{experiment}{Temperature}, -NaCl = \protect\csvGetEntry{experiment}{NaCl}, -pH = \protect\csvGetEntry{experiment}{pH}} -\vspace{10pt} -\centering -\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{% -Time & Log Count\\}{% -\insertTime & \insertLogcount\\}{% -\insertTime & \insertLogcount} - -\end{table} -} -</pre> - Note that <tt>\csvGetEntry</tt> needs to be <tt>\protect</tt>ed within - the <tt>\caption</tt> command. - - This example can be modified if, say, you only want the - tables where the temperature is 25: -<pre> -\setcounter{experiment}{0} -\whiledo{\value{experiment}<\value{maxexperiments}}{% -\stepcounter{experiment} -\ifthenelse{\equal{\csvGetEntry{experiment}{Temperature}}{25}}{% -\begin{table} -\caption{Temperature = \protect\csvGetEntry{experiment}{Temperature}, -NaCl = \protect\csvGetEntry{experiment}{NaCl}, -pH = \protect\csvGetEntry{experiment}{pH}} -\vspace{10pt} -\centering -\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{% -Time & Log Count\\}{% -\insertTime & \insertLogcount\\}{% -\insertTime & \insertLogcount}\par -\end{table}}{} -} -</pre> - -<h2><a name=perl>The csvtools.pl Perl Script</a></h2> - - Suppose you have several large CSV files, and you have included the information into - your document using <tt>\applyCSVfile</tt>, <tt>\CSVtolongtable</tt> or <tt>\CSVtotabular</tt>, which has made life so much easier for - you, but you are now required by a journal to submit your source code in a single <tt>.tex</tt> file. - They don't want all your CSV files, so what do you do? If you have Perl installed on your system - you can use the <tt>csvtools.pl</tt> Perl script. This has the following syntax:<p> - <tt>csvtools.pl</tt> <em>in-file</em> <em>out-file</em><p> - where <em>in-file</em> is the name of your file that contains the <tt>\applyCSVfile</tt>, <tt>\CSVtotabular</tt> etc - commands, and <em>out-file</em> is a new file which will be created by <tt>csvtools.pl</tt>. This new - file will be the same as <em>in-file</em> except that all occurances of <tt>\applyCSVfile</tt>, <tt>\CSVtolongtable</tt> and - <tt>\CSVtotabular</tt> will be replaced by the relevant data extracted from the named CSV files. - -<h3><a name=ex:perl>Example 15 (csvtools.pl - Aligning Data)</a></h3> - - Suppose the file <tt>mydoc.tex</tt> contains the code given in <a href=#ex:tab1>Example 4</a>, with the associated - CSV file <tt>sample.csv</tt> also given in that example. Then if you do: -<pre> -csvtools.pl mydoc.tex mydocnew.tex -</pre> -the file <tt>mydocnew.tex</tt> will be created which will be identical to <tt>mydoc.tex</tt> except the lines - containing the code <tt>\CSVtotabular{sample.csv}{lccc}{</tt>...<tt>}{</tt>...<tt>}{</tt>...<tt>}</tt> will be replaced -with the lines: -<pre> - % \CSVtotabular{sample.csv}... converted using csvtools.pl - %>> START INSERT - \begin{tabular}{lccc} - \bfseries Name & - \bfseries Assignment 1 & - \bfseries Assignment 2 & - \bfseries Total\\ - A. Smith&80&70&150\\ - B. Jones&60&80&140\\ - J. Doe&85&75&160\\ - &75&75&150 - \end{tabular}%<< END INSERT -</pre> - -Similarly, <tt>csvtools.pl</tt> will substitute all occurrances of <tt>\CSVtolongtable</tt> and <tt>\applyCSVfile</tt>. - -<h3>Notes</h3> -<ol> -<li> The <tt>csvtools.pl</tt> file is bundled up with the code and documentation in the file - <tt>csvtools.dtx</tt>. It will be extracted along with the code when you LaTeX the - installation script <tt>csvtools.ins</tt>. If you are using UNIX or Linux etc, you will need - to set the permissions so that the file can be executed: -<pre> -chmod u+x csvtools.pl -</pre> -If perl is located in a directory other than <tt>/usr/bin/</tt> you will need to edit the -first line of <tt>csvtools.pl</tt> as appropriate. You can find the location using the command: -<pre> -which perl -</pre> - -<li>If you can't directly execute a Perl script, - you can do:<p> - <tt>perl csvtools.pl</tt> <em>in-file</em> <em>out-file</em> -<p> -<li> You must first LaTeX your document before using <tt>csvtools.pl</tt> as it checks the - log file for any counters that have been defined. -<p> -<li> <tt>csvtools.pl</tt> only knows about a very limited set of LaTeX commands. It should - be able to understand: -<pre> -\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{... -</pre> -(see <a href=#ex:index>Example 14</a>), but it won't be able to understand, say, -<pre> -\newcommand{\filename}{\csvGetEntry{experiment}{File}} -\CSVtotabular{\filename}{ll}{... -</pre> -It can pick up on <tt>\addtocounter</tt>, <tt>\stepcounter</tt>, <tt>\refstepcounter</tt> and <tt>\setcounter</tt> - but only if they are used explicitly in the named <tt>.tex</tt> file. (It ignores any files - that have been included using <tt>\input</tt>, <tt>\include</tt> etc.) -<p> -<li> This Perl script has only been tested under Linux, but it ought to work under other - systems. -</ol> - -<h2><a name=drawbacks>Bugs/Drawbacks/``Features''</a></h2> - -<ol> -<li><a name=itm:insert></a> - The package doesn't check to see whether <tt>\insert</tt><em>identifier</em> - exists, otherwise you would not be able to use multiple CSV - files with the same headers, as in <a href=#ex:index>Example 14</a>. Therefore it is recommended that - you check to make sure that the command does not already exist. - For example, the TeX commands <tt>\insert</tt> and <tt>\insertpenalties</tt> - already exist, so a blank header or a header named <tt>penalties</tt> - would cause problems. (These two will now cause an error as from version 1.1, but it's something bear in mind.) -<p> - <li> Note also that <tt>\insertbyname</tt> doesn't check - if you've given a valid label, so if no text appears, - check you've spelt it correctly, checking punctuation, spaces and case. -<p> - <li><a name=itm:psbyname></a> - Note that in <a href=#ex:ps>Example 2</a>, replacing line 3 with: -<pre> -\centerline{\includegraphics{\insertbyname{File}}} -</pre> - will cause an error, as <tt>\insertbyname{File}</tt> doesn't get - fully expanded by the time it gets passed to - <tt>\includegraphics</tt>, and will prevent <tt>\includegraphics</tt> from - finding the file. It is possible to get around this using - TeX's <tt>\edef</tt> command: -<pre> -\edef\psfilename{\insertbyname{File}} -\centerline{\includegraphics{\psfilename}} -</pre> - - <li><a name=itm:noalign></a> You can't have commands like <tt>\hline</tt>, <tt>\cline</tt> - and <tt>\multicolumn</tt> in the first column of the - <em>middle</em> or <em>last</em> code of <tt>\CSVtotabular</tt> or <tt>\CSVtolongtable</tt>. If you do, it will generate - a <tt>misplaced \noalign</tt> error, instead you need to put it - at the end of the <em>first</em> or <em>middle</em> code. - (See <a href=#ex:tab3>Example 6</a>.) -<p> - <li>You can't have nested <tt>\applyCSVfile</tt>, <tt>\CSVtolongtable</tt> and <tt>\CSVtotabular</tt> - commands. (See <a href=#ex:index>Example 14</a>) -<p> - <li> If the CSV file has a header row, it must be on the first line. -<p> - <li> It is possible for TeX to run out of memory if you use - <tt>\csvSaveEntry</tt> on a large file. -<p> -<li> Commas within an entry in a CSV file may cause problems. You will need to -enclose the entry in braces, e.g. <code>{Joe Smith, Jr}</code>. -<p> -<li><a name=itm:csvrownumber</a> In version 1.0, there was an inconsistency -with <tt>csvrownumber</tt> within <code>\applyCSVfile</code> and <code>\CSVtotabular</code>. In the former it excluded the header row, whereas the latter included it. This has been changed in version 1.1 so that with <code>\applyCSVfile</code>, <code>\CSVtotabular</code> and <code>\CSVtolongtable</code>, <tt>csvrownumber</tt> refers to the data row (excluding header row.) I hope this doesn't cause problems, but it makes more sense that they should be consistent. So if you have no blank lines in your CSV file, <tt>csvrownumber</tt> should always be 1 more than <tt>csvlinenumber</tt>. -</ol> - -<hr> -<h2>Contents</h2> -<ul> -<li><a href=#intro>Introduction</a> -<li><a href=#mailmerge>Mail Merging and Similar Applications</a> -<li><a href=#csv2tab>Converting CSV file into a tabular environment</a> -<li><a href=#longtable>Converting CSV file into a longtable environment</a> -<li><a href=#counters>Associated Counters</a> -<li><a href=#crossref>Cross-Referencing</a> -<li><a href=#save>Saving Entries</a> -<li><a href=#perl>The csvtools.pl Perl Script</a> -<li><a href=#drawbacks>Bugs/Drawbacks/``Features''</a> -</ul> - -<h2>Examples</h2> -<ul> -<li><a href=#ex:mail>Example 1 (Mail Merging)</a> -<li><a href=#ex:ps>Example 2 (Multiple Figures)</a> -<li><a href=#ex:field>Example 3 (Mail Merging using <tt>\field</tt>)</a> -<li><a href=#ex:tab1>Example 4 (Aligning Data from a CSV file)</a> -<li><a href=#ex:tab2>Example 5 (Adding Lines)</a> -<li><a href=#ex:tab3>Example 6 (Added Complexity)</a> -<li><a href=#ex:longtab>Example 7</a> -<li><a href=#ex:stripy>Example 8 (Stripy Table)</a> -<li><a href=#ex:mail2>Example 9 (More Mail Merging)</a> -<li><a href=#ex:ref1>Example 10 (Labelling within <tt>\applyCSVfile</tt>)</a> -<li><a href=#ex:ref2>Example 11 (Labelling within <tt>\applyCSVfile</tt>)</a> -<li><a href=#ex:timetogrowth>Example 12 (Labelling within <tt>\CSVtotabular</tt>)</a> -<li><a href=#ex:t2g2>Example 13 (Labelling within <tt>\CSVtotabular</tt>)</a> -<li><a href=#ex:index>Example 14 (Saving Entries)</a> -<li><a href=#ex:perl>Example 15 (csvtools.pl - Aligning Data)</a> -</ul> -<hr> - -<a href=http://theoval.cmp.uea.ac.uk/~nlct>Dr Nicola Talbot</a> | -<a href=http://www.cmp.uea.ac.uk/>School of Computing Sciences</a> | -<a href=http://www.uea.ac.uk/>University of East Anglia</a> - -<h5>N.L.C. Talbot. School of Computing Sciences. University of East Anglia. Last Modified: 19 Oct 2004.</h5> -</html> diff --git a/Master/texmf-dist/doc/latex/csvtools/csvtools.pdf b/Master/texmf-dist/doc/latex/csvtools/csvtools.pdf Binary files differdeleted file mode 100644 index db205023e1e..00000000000 --- a/Master/texmf-dist/doc/latex/csvtools/csvtools.pdf +++ /dev/null diff --git a/Master/texmf-dist/doc/latex/csvtools/csvtools.pl b/Master/texmf-dist/doc/latex/csvtools/csvtools.pl deleted file mode 100644 index 2cc4df9a073..00000000000 --- a/Master/texmf-dist/doc/latex/csvtools/csvtools.pl +++ /dev/null @@ -1,1305 +0,0 @@ -#!/usr/bin/perl - -# File : csvtools.pl -# Author : Dr Nicola Talbot -# Date : 14 Oct 2004 -# Description : Perl script to accompany csvtools.sty -# : Allows you to substitute \CSVtotabular, \CSVtolongtable and \applyCSVfile commands with the appropriate LaTeX code -# Version : 0.5b (18 October 2004). - -# usage : csvtools <in-file> <out-file> - -if ($#ARGV != 1) -{ - die "Syntax : $0 <in-file> <out-file>\n"; -} - -($FILENAME,$OUTPUT) = @ARGV; - -open FILENAME or die "Can't open '$FILENAME'\n"; - -$ext = substr($FILENAME, -4); - -if (($ext eq ".tex") or ($ext eq ".dtx") or ($ext eq ".ltx")) -{ - $LOGFILE = substr($FILENAME,0,length($FILENAME)-4) . ".log"; -} -else -{ - $LOGFILE = $FILENAME . ".log"; -} - -open LOGFILE or die "Can't open log file '$LOGFILE'. Make sure you run LaTeX before using $0\n"; - - -while (<LOGFILE>) -{ - if (/\\c@([a-zA-Z]+)=\\count/) - { - $counter{$1} = 0; - } -} - -$counter{csvrownumber} = 0; - -close LOGFILE; - -open OUTPUT, ">$OUTPUT" or die; - - -while (<FILENAME>) -{ - $restofline = $_; - - while ($restofline=~/\\stepcounter(.*)/) - { - $line = $_; - - ($ctr,$restofline,$done) = getnextgroup($1); - - $startline=$.; - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - $restofline = $restofline . $nextline; - - ($ctr,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; - } - } - - $counter{$ctr}++; - - $_ = $line; - } - - $restofline = $_; - - while ($restofline=~/\refstepcounter(.*)/) - { - $line = $_; - - ($ctr,$restofline,$done) = getnextgroup($1); - - $startline=$.; - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - $restofline = $restofline . $nextline; - - ($ctr,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; - } - } - - $counter{$ctr}++; - - $_ = $line; - } - - $restofline = $_; - - while ($restofline=~/\\setcounter(.*)/) - { - $line = $_; - - ($ctr,$restofline,$done) = getnextgroup($1); - - $startline=$.; - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - $restofline = $restofline . $nextline; - - ($ctr,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; - } - } - - ($num,$restofline,$done) = getnextgroup($restofline); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - $restofline = $restofline . $nextline; - - ($num,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning second argument to \\stepcounter on line $startline\n"; - } - } - - $num=~s/\\value{(.+)}/$counter{$1}/; - - $counter{$ctr} = $num; - - $_ = $line; - } - - $restofline = $_; - - while ($restofline=~/\\addtocounter(.*)/) - { - $line = $_; - - ($ctr,$restofline,$done) = getnextgroup($1); - - $startline=$.; - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - $restofline = $restofline . $nextline; - - ($ctr,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; - } - } - - ($num,$restofline,$done) = getnextgroup($restofline); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - $restofline = $restofline . $nextline; - - ($num,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning second argument to \\stepcounter on line $startline\n"; - } - } - - $num=~s/\\value{(.+)}/$counter{$1}/; - - $counter{$ctr} = $counter{$ctr} + $num; - - $_ = $line; - } - - $restofline = $_; - - while ($restofline=~/^(.*)\\csvGetEntry(.*)$/) - { - $start = $1; - $restofline = $2; - - ($ctr,$restofline,$done) = getnextgroup($restofline); - - $startline=$.; - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $restofline = $restofline . $nextline; - - ($ctr,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning first argument to \\csvGetEntry on line $startline\n"; - } - } - - ($entry,$restofline,$done) = getnextgroup($restofline); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $restofline = $restofline . $nextline; - - ($entry,$restofline,$done) = getnextgroup($restofline); - } - else - { - die "EOF found whilst scanning first argument to \\csvGetEntry on line $startline\n"; - } - } - $_ = $start . "\\csname $entry\\roman{$ctr}\\endcsname" . $restofline; - #$_ = $start. $data{$entry}[$counter{$ctr}] . $restofline; - } - - if (/^(.*)\\CSVtotabular(.*)$/) - { - print OUTPUT "$1\n"; - - $line = $2; - - ($csvname,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - ($csvname,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for CVS filename on line $.\n"; - } - } - - $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; - - $line = $restofline; - - ($alignment,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($alignment,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for CVS column alignment on line $.\n"; - } - } - - $line = $restofline; - - ($FIRST,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($FIRST,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\CSVtotabular third argument on line $.\n"; - } - } - - $line = $restofline; - - ($MIDDLE,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($MIDDLE,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\CSVtotabular fourth argument on line $.\n"; - } - } - - $line = $restofline; - - ($LAST,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($LAST,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\CSVtotabular fifth argument on line $.\n"; - } - } - - csvtotabular($csvname, $alignment, $FIRST, $MIDDLE, $LAST); - - print OUTPUT "$restofline\n"; - } - elsif (/^(.*)\\CSVtolongtable(.*)$/) - { - print OUTPUT "$1\n"; - - $line = $2; - - ($csvname,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $line . $nextline; - - ($csvname,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for CVS filename on line $.\n"; - } - } - - $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; - - $line = $restofline; - - ($alignment,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($alignment,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for CVS column alignment on line $.\n"; - } - } - - $line = $restofline; - - ($FIRST,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($FIRST,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\CSVtolongtable third argument on line $.\n"; - } - } - - $line = $restofline; - - ($MIDDLE,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($MIDDLE,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\CSVtolongtable fourth argument on line $.\n"; - } - } - - $line = $restofline; - - ($LAST,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline = <FILENAME>) - { - $line = $restofline . $nextline; - - ($LAST,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\CSVtolongtable fifth argument on line $.\n"; - } - } - - csvtolongtable($csvname, $alignment, $FIRST, $MIDDLE, $LAST); - - print OUTPUT "$restofline\n"; - } - elsif (/^(.*)\\applyCSVfile\*(.*)$/) - { - print OUTPUT $1; - - $restofline = $2; - - $restofline = eatinitialspaces($restofline); - $restofline = eatcomments($restofline); - - $startrow=1; - - if (/^\[([0-9]+)\](.*)/) - { - $startrow = $1; - - $restofline = $2; - } - - $line=$restofline; - - ($csvname,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline= <FILENAME>) - { - $line = $restofline . $nextline; - - ($csvname,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\applyCSVfile*[$startrow] first argument on line $.\n"; - } - } - - $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; - - $line=$restofline; - - ($body,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline= <FILENAME>) - { - $line = $restofline . $nextline; - - ($body,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\applyCSVfile*[$startrow] second argument on line $.\n"; - } - } - - applyCSVfilestar($csvname, $body, $startrow); - - print OUTPUT "$restofline\n"; - } - elsif (/^(.*)\\applyCSVfile(.*)$/) - { - print OUTPUT $1; - - $restofline = $2; - - $restofline = eatinitialspaces($restofline); - $restofline = eatcomments($restofline); - - $startrow=2; - - if ($restofline=~/^\[(\d+)\](.*)/) - { - $startrow = $1; - - $restofline = $2; - } - - $line=$restofline; - - ($csvname,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline= <FILENAME>) - { - $line = $restofline . $nextline; - - ($csvname,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\applyCSVfile[$startrow] first argument on line $.\n"; - } - } - - $line=$restofline; - - ($body,$restofline,$done) = getnextgroup($line); - - while (!$done) - { - if ($nextline= <FILENAME>) - { - $line = $restofline . $nextline; - - ($body,$restofline,$done) = getnextgroup($line); - } - else - { - die "EOF found whilst scanning for \\applyCSVfile[$startrow] second argument on line $.\n"; - } - } - - applyCSVfile($csvname, $body, $startrow); - - print OUTPUT "$restofline\n"; - } - else - { - print OUTPUT; - } -} - -sub applyCSVfile -{ - my ($CSVFILE,$body,$startrow) = @_; - - print "Converting \\applyCSVfile{$CSVFILE}"; - print OUTPUT "\% \\applyCSVfile{$CSVFILE}... converted using $0\n"; - print OUTPUT "\%>> START INSERT\n"; - print OUTPUT "\\setcounter{csvrownumber}{0}"; - $counter{csvrownumber} = 0; - - open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n"; - - $csvrow=0; - - while (<FH>) - { - if ($. == 1) - { - # get header row - - chop; - - @fields = split /,/; - - $numcols = 1; - - foreach $field (@fields) - { - $idx{$field} = $numcols; - - $numcols++; - } - } - elsif ($. >= $startrow) - { - next unless /,/; - - chop; - - $csvrow++; - $rec = {}; - - $HoH[$csvrow] = $rec; - - @entries = split /,/; - - $i = 0; - - foreach $e (@entries) - { - $rec->{$fields[$i]} = $e; - $i++; - } - } - } - - close FH; - - foreach ($row=1; $row <= $csvrow; $row++) - { - print "."; - - $THISROW = $body; - - $THISROW = csvSaveEntry($THISROW,$row,%HoH); - - foreach $entry ( keys %{$HoH[$row]}) - { - $replacementval=$HoH[$row]{$entry}; - - $THISROW =~ s/\\insertbyname{$entry}/$replacementval/g; - - $THISROW =~ s/\\insert$entry/$replacementval/g; - - $column = $idx{$entry}; - - $THISROW =~ s/\\field{$column}/$replacementval/g; - - $THISROW = ifnextrowlast($THISROW, ($row==$csvrow-1)); - } - - print OUTPUT "\\stepcounter{csvrownumber}$THISROW"; - $counter{csvrownumber}++; - } - - print "\n"; - - print OUTPUT "\%<< END INSERT\n"; -} - -sub csvSaveEntry -{ - my ($STR,$row,%HoH) = @_; - - $rowctr = "csvrownumber"; - - while (($pos = index($STR, "\\csvSaveEntry")) > -1) - { - $start = substr($STR,0,$pos); - $restofline = substr($STR,$pos+13); - - $restofline = eatcomments($restofline); - $restofline = eatinitialspaces($restofline); - - if ($restofline[0] eq "[") - { - if (($i = index($restofline,"]")) > -1) - { - $rowctr = substr($restofline, 1, $i-1); - - $restofline = substr($restofline, $i+1); - } - else - { - die "unmatched [ in \\csvSaveEntry\n"; - } - - $row = $counter{$rowctr}; - } - - ($group,$restofline,$done) = getnextgroup($restofline); - - if (!$done) - { - die "argument to \\csvSaveEntry[$rowctr] not found in >>$restofline<<\n"; - } - - $val = $HoH[$row]{$group}; - - $STR = $start . "\\expandafter\\gdef\\csname $group\\roman{$rowctr}\\endcsname{$val}" . $restofline; - - $data{$group}[$row] = $HoH[$row]{$group}; - } - - return $STR; -} - -sub applyCSVfilestar -{ - my ($CSVFILE,$body,$startrow) = @_; - - print "Converting \\applyCSVfile*{$CSVFILE}"; - print OUTPUT "\\setcounter{csvrownumber}{0}"; - $counter{csvrownumber} = 0; - - open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n"; - - $csvrow=0; - - while (<FH>) - { - if ($. >= $startrow) - { - $csvrow++; - - chop; - - @fields = split /,/; - - $numcols = 1; - - foreach $field (@fields) - { - $entry[$csvrow][$numcols-1] = $field; - - $numcols++; - } - } - } - - close FH; - - for ($row=0; $row < $csvrow; $row++) - { - print "."; - - $THISROW = $body; - - for ($column=0; $column < $numcols; $column++) - { - $replacementval=$entry[$row][$column]; - - $THISROW =~ s/\\field{$column}/$replacementval/g; - - $THISROW = ifnextrowlast($THISROW, ($row==$csvrow-1)); - } - - print OUTPUT "\\stepcounter{csvrownumber}$THISROW"; - $counter{csvrownumber}++; - } - - print "\n"; - - print OUTPUT "\%<< END INSERT\n"; -} - -sub csvtotabular -{ - my ($CSVFILE,$ALIGN,$START,$MID,$END) = @_; - - print "Converting \\CSVtotabular{$CSVFILE}"; - - print OUTPUT "\% \\CSVtotabular{$CSVFILE}... converted using $0\n"; - print OUTPUT "\%>> START INSERT\n"; - - print OUTPUT "\\setcounter{csvrownumber}{0}\n"; - $counter{csvrownumber} = 0; - print OUTPUT "\\begin{tabular}{$ALIGN}\n"; - - open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n"; - - $csvrow=0; - - while (<FH>) - { - if ($. == 1) - { - # get header row - - chop; - - @fields = split /,/; - - $numcols = 1; - - foreach $field (@fields) - { - $idx{$field} = $numcols; - - $numcols++; - } - - $csvrow++; - $rec = {}; - - $HoH[$csvrow] = $rec; - - @entries = split /,/; - - $i = 0; - - foreach $e (@entries) - { - $rec->{$fields[$i]} = $e; - $i++; - } - } - elsif ($. > 1) - { - next unless /,/; - - chop; - - $csvrow++; - $rec = {}; - - $HoH[$csvrow] = $rec; - - @entries = split /,/; - - $i = 0; - - foreach $e (@entries) - { - $rec->{$fields[$i]} = $e; - $i++; - } - } - } - - close FH; - - foreach ($row=1; $row <= $csvrow; $row++ ) - { - print "."; - - if ($row == 1) - { - $THISROW=$START; - } - elsif ($row == $csvrow) - { - $THISROW=$END; - } - else - { - $THISROW=$MID; - } - - foreach $entry ( keys %{$HoH[$row]}) - { - $replacementval=$HoH[$row]{$entry}; - - $THISROW =~ s/\\insertbyname{$entry}/$replacementval/g; - - $THISROW =~ s/\\insert$entry/$replacementval/g; - - $column = $idx{$entry}; - - $THISROW =~ s/\\field{$column}/$replacementval/g; - - $THISROW = ifnextrowlast($THISROW, ($row==$csvrow-1)); - } - - if ($row==1) - { - print OUTPUT "$THISROW"; - } - else - { - print OUTPUT "\\refstepcounter{csvrownumber}$THISROW"; - $counter{csvrownumber}++; - } - } - - print OUTPUT "\\end{tabular}"; - print OUTPUT "\%<< END INSERT\n"; - - print "\n"; -} - -sub csvtolongtable -{ - my ($CSVFILE,$ALIGN,$START,$MID,$END) = @_; - - print "Converting \\CSVtolongtable{$CSVFILE}"; - - print OUTPUT "\% \\CSVtolongtable{$CSVFILE}... converted using $0\n"; - print OUTPUT "\%>> START INSERT\n"; - - print OUTPUT "\\setcounter{csvrownumber}{0}\n"; - $counter{csvrownumber} = 0; - print OUTPUT "\\begin{longtable}{$ALIGN}\n"; - - open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n"; - - $csvrow=0; - - while (<FH>) - { - if ($. == 1) - { - # get header row - - chop; - - @fields = split /,/; - - $numcols = 1; - - foreach $field (@fields) - { - $idx{$field} = $numcols; - - $numcols++; - } - - $csvrow++; - $rec = {}; - - $HoH[$csvrow] = $rec; - - @entries = split /,/; - - $i = 0; - - foreach $e (@entries) - { - $rec->{$fields[$i]} = $e; - $i++; - } - } - elsif ($. > 1) - { - next unless /,/; - - chop; - - $csvrow++; - $rec = {}; - - $HoH[$csvrow] = $rec; - - @entries = split /,/; - - $i = 0; - - foreach $e (@entries) - { - $rec->{$fields[$i]} = $e; - $i++; - } - } - } - - close FH; - - print "csvrow = $csvrow\n"; - - for ($row=1; $row <= $csvrow; $row++) - { - print "."; - - if ($row == 1) - { - $THISROW=$START; - } - elsif ($row == $csvrow) - { - $THISROW=$END; - } - else - { - $THISROW=$MID; - } - - foreach $entry ( keys %{$HoH[$row]}) - { - $replacementval=$HoH[$row]{$entry}; - - $THISROW =~ s/\\insertbyname{$entry}/$replacementval/g; - - $THISROW =~ s/\\insert$entry/$replacementval/g; - - $column = $idx{$entry}; - - $THISROW =~ s/\\field{$column}/$replacementval/g; - - $THISROW = ifnextrowlast($THISROW, ($row==$csvrow-1)); - } - - if ($row==1) - { - print OUTPUT "$THISROW"; - } - else - { - print OUTPUT "\\refstepcounter{csvrownumber}$THISROW"; - $counter{csvrownumber}++; - } - } - - print OUTPUT "\\end{longtable}"; - print OUTPUT "\%<< END INSERT\n"; - - print "\n"; -} - -sub ifnextrowlast -{ - my ($STR, $nextislast) = @_; - - if (($pos = index($STR, "\\ifnextrowlast")) > -1) - { - $strbegin = substr($STR,0,$pos); - $strend = substr($STR,$pos+14); - - ($firstarg,$strend,$done) = getnextgroup($strend); - - if (!$done) - { - die "Can't find first argument to \\ifnextrowlast\n"; - } - - ($secondarg,$strend,$done) = getnextgroup($strend); - - if (!$done) - { - die "Can't find second argument to \\ifnextrowlast\n"; - } - - if ($nextislast) - { - $STR = $strbegin . $firstarg . $strend; - } - else - { - $STR = $strbegin . $secondarg . $strend; - } - } - - return $STR; -} - -sub eatcomments -{ - my ($STR) = @_; - - if (substr($STR,0,1) eq "%") - { - return ""; - } - - my $pos=1; - - if (($pos = index($STR, "%", 1)) > -1) - { - if (not (substr($STR, $pos-1,1) eq "\\")) - { - return substr($STR,0,$pos); - } - - while ((substr($STR, $pos-1,1) eq "\\") and ($pos > 0)) - { - # count how many backlashes come before it. - - $i = $pos-1; - - $numbs = 1; - - while ((substr($STR, $i-1,1) eq "\\") and ($i > 0)) - { - $numbs++; - $i--; - } - - # is $numbs is odd, we have a \%, otherwise we have \\% - - if ($numbs%2 == 0) - { - # it's a comment - - return substr($STR,0,$pos); - } - else - { - # it's not a comment, carry on looking - - $pos = index($STR, "%", $pos+1); - } - } - } - - return $STR; -} - -sub eatinitialspaces -{ - my ($STR) = @_; - - while (substr($STR,0,1) eq "\s") - { - $STR = substr($STR,1); - } - - return $STR; -} - -sub getnextgroup -{ - my($curline) = @_; - - $curline = eatcomments($curline); - - $curline = eatinitialspaces($curline); - - # check to see if current string is blank - - if ($curline!~/[^\s]+/m) - { - return ("","",0); - } - - if (($group = substr($curline,0,1)) ne "{") - { - # next group hasn't been delimited with braces - # return first non-whitespace character - - $curline = substr($curline,1); - - # unless it's a backslash, in which case get command name - - if ($group eq "\\") - { - if ($curline=~/([a-zA-Z]+)(^[a-zA-Z].*)/m) - { - $group = $1; - - $curline = $2; - } - else - { - # command is made up of backslash followed by symbol - - $curline=~/([\W_0-9\s\\])(.*)/m; - - $group = $1; - - $curline = $2; - } - } - - return ($group,$curline,1); - } - - my $pos=index($curline, "{"); - my $startpos=$pos; - my $posopen=0; - my $posclose=0; - - my $bracelevel = 1; - - my $done=0; - - while (!$done) - { - $pos++; - - $posopen = index($curline, "{", $pos); - - # check to make sure it's not a \{ - - while ((substr($curline, $posopen-1,1) eq "\\") and ($posopen > 0)) - { - # count how many backlashes come before it. - - $i = $posopen-1; - - $numbs = 1; - - while ((substr($curline, $i-1,1) eq "\\") and ($i > 0)) - { - $numbs++; - $i--; - } - - # is $numbs is odd, we have a \{, otherwise we have \\{ - - if ($numbs%2 == 0) - { - last; - } - else - { - $posopen = index($curline, "{", $posopen+1); - } - } - - $posclose= index($curline, "}", $pos); - - # check to make sure it's not a \} - - while ((substr($curline, $posclose-1,1) eq "\\") and ($posclose > 0)) - { - # count how many backlashes come before it. - - $i = $posclose-1; - - $numbs = 1; - - while ((substr($curline, $i-1,1) eq "\\") and ($i > 0)) - { - $numbs++; - $i--; - } - - # is $numbs is odd, we have a \}, otherwise we have \\} - - if ($numbs%2 == 0) - { - last; - } - else - { - $posclose = index($curline, "}", $posclose+1); - } - } - - if (($posopen==-1) and ($posclose==-1)) - { - $done=1; - } - elsif ($posopen==-1) - { - $pos=$posclose; - - $bracelevel--; - - if ($bracelevel==0) - { - $group = substr($curline, $startpos+1, $pos-$startpos-1); - - $curline = substr($curline, $pos+1); - - return ($group,$curline,1); - } - } - elsif ($posclose==-1) - { - $pos=$posopen; - - $bracelevel++; - } - elsif ($posopen<$posclose) - { - $pos=$posopen; - - $bracelevel++; - } - elsif ($posclose<$posopen) - { - $pos=$posclose; - - $bracelevel--; - - if ($bracelevel==0) - { - $group = substr($curline, $startpos+1, $pos-$startpos-1); - - $curline = substr($curline, $pos+1); - - return ($group,$curline,1); - } - } - } - - # closing brace must be on another line - - return ("", $curline, 0); -} - -1; diff --git a/Master/texmf-dist/doc/latex/csvtools/doc/CHANGES b/Master/texmf-dist/doc/latex/csvtools/doc/CHANGES new file mode 100644 index 00000000000..9e3d1a52846 --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/doc/CHANGES @@ -0,0 +1,29 @@ +Version 1.24: +Added csvsort.sty (requires xfor package and \'Eamonn McManus' +compare.tex) + +Version 1.23: +\par can now be used in entries (but all entries for a given +row must be on the same line, so you can't use a blank line +to indicate a paragraph break.) + +Version 1.22: +\applyCSVfile now resets each field to nothing before scanning each +row so that if a column is missing for a given row, that entry will +be blank. (Note that this does not apply to the starred version, as +the header row is used to determine the maximum number of columns.) +\csvSaveEntry has an additional optional argument to supply text if +that entry is omitted. + +Version 1.21: + Fixed problem caused when first field starts with repeated +character + +Version 1.2: + added csvpie.sty + data separator can now be user defined + entries enclosed within double quotes are now parsed correctly + +Version 1.1 has the new command \CSVtolongtable (analogous to \CSVtotabular) +and a Perl script. See documentation for details. + diff --git a/Master/texmf-dist/doc/latex/csvtools/doc/csvtools.pdf b/Master/texmf-dist/doc/latex/csvtools/doc/csvtools.pdf Binary files differnew file mode 100644 index 00000000000..3e05495d31e --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/doc/csvtools.pdf diff --git a/Master/texmf-dist/doc/latex/csvtools/doc/manual.html b/Master/texmf-dist/doc/latex/csvtools/doc/manual.html new file mode 100644 index 00000000000..ad8a6fe9396 --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/doc/manual.html @@ -0,0 +1,1615 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> + +<!--Converted with LaTeX2HTML 2002 (1.67) +original version by: Nikos Drakos, CBLU, University of Leeds +* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan +* with significant contributions from: + Jens Lippmann, Marek Rouchal, Martin Wilck and others --> +<HTML> +<HEAD> +<TITLE>csvtools v1.24 : A LaTeX2e Package Providing Access to Data Saved in a CSV File</TITLE> +<META NAME="description" CONTENT="csvtools v1.24 : A LaTeX2e Package Providing Access to Data Saved in a CSV File"> +<META NAME="keywords" CONTENT="manual"> +<META NAME="resource-type" CONTENT="document"> +<META NAME="distribution" CONTENT="global"> + +<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> +<META NAME="Generator" CONTENT="LaTeX2HTML v2002"> +<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> + + +</HEAD> + +<BODY > + + + <H1 ALIGN="CENTER">csvtools v1.24 : A LaTeX2e Package Providing Access to Data Saved in a CSV File</H1> +<P ALIGN="CENTER"><STRONG>Nicola Talbot</STRONG></P> +<P ALIGN="CENTER"><STRONG>26th June 2007</STRONG></P> + <BR> + +<H2><A NAME="SECTION00010000000000000000"> +Contents</A> +</H2> +<!--Table of Contents--> + +<UL> +<LI><A NAME="tex2html49" + HREF="manual.html#SECTION00030000000000000000">Introduction</A> +<LI><A NAME="tex2html50" + HREF="manual.html#SECTION00040000000000000000">Mail Merging and Similar Applications</A> +<LI><A NAME="tex2html51" + HREF="manual.html#SECTION00050000000000000000">Converting data in a CSV file into a tabular environment</A> +<LI><A NAME="tex2html52" + HREF="manual.html#SECTION00060000000000000000">Converting CSV file into longtable environment</A> +<LI><A NAME="tex2html53" + HREF="manual.html#SECTION00070000000000000000">Associated Counters</A> +<LI><A NAME="tex2html54" + HREF="manual.html#SECTION00080000000000000000">Cross-Referencing</A> +<LI><A NAME="tex2html55" + HREF="manual.html#SECTION00090000000000000000">Saving Entries</A> +<LI><A NAME="tex2html56" + HREF="manual.html#SECTION000100000000000000000">Pie Charts (csvpie.sty)</A> +<LI><A NAME="tex2html57" + HREF="manual.html#SECTION000110000000000000000">Sorting Data (csvsort.sty)</A> +<LI><A NAME="tex2html58" + HREF="manual.html#SECTION000120000000000000000">The csvtools.pl Perl Script</A> +<UL> +<LI><A NAME="tex2html59" + HREF="manual.html#SECTION000122000000000000000">Notes</A> +</UL> +<BR> +<LI><A NAME="tex2html60" + HREF="manual.html#SECTION000130000000000000000">Bugs/Drawbacks/``Features''</A> +<LI><A NAME="tex2html61" + HREF="manual.html#SECTION000140000000000000000">Contact Details</A> +</UL> +<!--End of Table of Contents--> +<P> + +<H1><A NAME="SECTION00020000000000000000"> +List of Examples</A> +</H1> + +<P> + + +<OL> +<LI><A HREF="manual.html#ex:mail">Mail Merging</A> +</LI> +<LI><A HREF="manual.html#ex:ps">Multiple Figures</A> +</LI> +<LI><A HREF="manual.html#ex:field">Mail Merging using <TT>\field</TT></A> +</LI> +<LI><A HREF="manual.html#ex:tab1">Aligning Data from a CSV file</A> +</LI> +<LI><A HREF="manual.html#ex:tab2">Adding Lines</A> +</LI> +<LI><A HREF="manual.html#ex:tab3">Added Complexity</A> +</LI> +<LI><A HREF="manual.html#ex:long">Using a longtable environment</A> +</LI> +<LI><A HREF="manual.html#ex:stripy">Stripy Table</A> +</LI> +<LI><A HREF="manual.html#ex:mailref">More Mail Merging</A> +</LI> +<LI><A HREF="manual.html#ex:ref1">Labelling within <TT>\applyCSVfile</TT></A> +</LI> +<LI><A HREF="manual.html#ex:ref2">Labelling within <TT>\applyCSVfile</TT></A> +</LI> +<LI><A HREF="manual.html#ex:timetogrowth">Labelling within <TT>\CSVtotabular</TT></A> +</LI> +<LI><A HREF="manual.html#ex:tablabel">Labelling within <TT>\CSVtotabular</TT></A> +</LI> +<LI><A HREF="manual.html#ex:index">Saving Entries</A> +</LI> +<LI><A HREF="manual.html#ex:piechart">A Pie Chart</A> +</LI> +<LI><A HREF="manual.html#ex:perl">csvtools.pl -- Aligning Data</A> +</LI> +</OL> + +<P> + +<H1><A NAME="SECTION00030000000000000000"> +Introduction</A> +</H1> + The <TT>csvtools</TT> package allows you to repeatedly perform + a set of LaTeX commands on data in each row + of a comma separated variable (CSV) file. + This can be used for mail merging, generating + tables etc. + +<P> +As from version 1.2, you can specify a different separator. +To change the separator, use the command: +<BR> +<BR><TT>\setcsvseparator</TT>{<I>separator</I>} +<BR> +<BR> +For example, if your data is separated by colons instead of +commas, do: +<PRE> +\setcsvseparator{:} +</PRE> +If your separator occurs within an entry, the entry must be +enclosed in double quotes, for example: +<PRE> +Name,Address,Telephone +A.N. Other,"1 The Street,The Town",0123456789 +</PRE> +Be careful of T<SMALL>E</SMALL>X special characters occuring within a CSV +file, for example: +<PRE> +Name,Address,Telephone +Jack \& Jill,"2 The Street,The Town",0123456789 +</PRE> + +<P> + +<H1><A NAME="SECTION00040000000000000000"> +Mail Merging and Similar Applications</A> +</H1> + +<P> + + <TT>\applyCSVfile</TT>[<I>n</I>]{<I>filename</I>}{<I>text</I>} +<BR> <TT>\applyCSVfile*</TT>[<I>n</I>]{<I>filename</I>}{<I>text</I>} +<BR> +<BR> +Letters can be generated using data given in + each line from <I>filename</I>. + If the CSV file contains a header row, the + unstarred version of <TT>\applyCSVfile</TT> should + be used, otherwise the starred version <TT>\applyCSVfile*</TT> + should be used. The optional argument <I>n</I> + specifies on which line the actual data (not header line) + starts. The unstarred version defaults to line 2 + (the header row is always assumed to be on line 1) + and the starred version defaults to 1. + +<P> +With the unstarred version, the entries in the header row + are used to generate commands of the form + <TT>\insert</TT><I>identifier</I><A NAME="tex2html1" + HREF="#foot869"><SUP>1</SUP></A> to access corresponding elements + in the row currently being processed. For example, + suppose the first line of the CSV file looks like: +<PRE> +Name,Address,Time,Date +</PRE> + then the commands <TT>\insertName</TT>, <TT>\insertAddress</TT>, + <TT>\insertTime</TT> and <TT>\insertDate</TT> are + created, allowing you to use the entries in the first, + second, third and fourth columns of the current row. + If the header text contains non-alphabetical characters, + e.g. <TT>Full Name</TT>, then you will need to use + <TT>\insertbyname{</TT><I>text</I><TT>}</TT>, + e.g. <code>\insertbyname{Full Name}</code>. + +<P> +Alternatively, you can use the +<TT>\field</TT>{<I>col</I>} command, where +<I>col</I> is the column number of the entry, so <code>\field{1}</code> +indicates the first entry in the current row and <code>\field{2}</code> +indicates the second entry in the current row. + +<P> +<A NAME="ex:mail"></A> +<H2><A NAME="SECTION00041000000000000000"> +Example 1 (Mail Merging)</A> +</H2> + Suppose there is a file called <TT>details.csv</TT> that has the + following contents: +<PRE> +Name,Address,Time,Date +Miss A. Person,1 The Road\\The Town\\AB1 2XY,15.00,4th May 2004 +Mr A. N. Other,2 The Road\\The Town\\AB1 2XY,15.30,11th May 2004 +</PRE> +then the following code can be used to generate a letter for each +person in the CSV file<A NAME="tex2html2" + HREF="#foot150"><SUP>2</SUP></A>: +<PRE> +\applyCSVfile{details.csv}{% +\begin{letter}{\insertName\\\insertAddress} +\opening{Dear \insertName} + +You are invited to an interview at \insertTime\ on the \insertDate. + +\closing{Yours Sincerely} +\end{letter}} +</PRE> + Note that you could also use <code>\insertbyname{Name}</code> etc instead + of <TT>\insertName</TT> etc. Also note that you need to specify the + file extension when specifying the filename. +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<A NAME="ex:ps"></A> +<H2><A NAME="SECTION00042000000000000000"> +Example 2 (Multiple Figures)</A> +</H2> + Suppose <TT>sample3.csv</TT> looks like: +<PRE> +File,Caption +circle.ps,A Circle +rectangle.ps,A Rectangle +triangle.ps,A Triangle +</PRE> + Assuming that the files <TT>circle.ps</TT>, <TT>rectangle.ps</TT> + and <TT>triangle.ps</TT> exist, then the following code will + generate a figure for each graphics file<A NAME="tex2html3" + HREF="#foot870"><SUP>3</SUP></A>: +<PRE> +\applyCSVfile{sample3.csv}{ +\begin{figure} +\centerline{\includegraphics{\insertFile}} +\caption{\insertCaption} +\end{figure}} +</PRE> + Note that in this example, you can't use <code>\insertbyname{File}</code>. + (See Note <A HREF="manual.html#itm:psbyname">3</A> in Section <A HREF="manual.html#sec:drawbacks">11</A>.) +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<A NAME="ex:field"></A> +<H2><A NAME="SECTION00043000000000000000"> +Example 3 (Mail Merging using <TT>\field</TT>)</A> +</H2> + Suppose there is a file called <TT>details.csv</TT> that has the + following contents: +<PRE> +Miss A. Person,1 The Road\\The Town\\AB1 2XY,15.00,4th May 2004 +Mr A. N. Other,2 The Road\\The Town\\AB1 2XY,15.30,11th May 2004 +</PRE> +In this case the data has no header file, so the starred version +of <TT>\applyCSVfile</TT> must be used. Since there is no header +file, you must use <TT>\field</TT> to access the entries: +<PRE> +\applyCSVfile*{details.csv}{% +\begin{letter}{\field{1}\\\field{2}} +\opening{Dear \field{1}} + +You are invited to an interview at \field{3}\ on the \field{4}. + +\closing{Yours Sincerely} +\end{letter}} +</PRE> +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION00050000000000000000"> +Converting data in a CSV file into a tabular environment</A> +</H1> + + <TT>\CSVtotabular</TT>{<I>filename</I>}{<I>col-align</I>}{<I>first</I>}{<I>middle</I>}{<I>last</I>} +<BR> +<BR> <I>filename</I> is the name of the CSV file which must have a header row on line 1, + <I>col-align</I> is the column alignment argument that gets passed + to the <TT>tabular</TT> environment, <I>first</I> + is the code for the first line, <I>middle</I> is the code + for the middle lines and <I>last</I> is the code for the last line. + This is best demonstrated with an example. + +<P> +<A NAME="ex:tab1"></A> +<H2><A NAME="SECTION00051000000000000000"> +Example 4 (Aligning Data from a CSV file)</A> +</H2> + Suppose the file <TT>sample.csv</TT> looks like: +<PRE> +Name,Assignment 1,Assignment 2,Total +A. Smith,80,70,150 +B. Jones,60,80,140 +J. Doe,85,75,160 +,75,75,150 +</PRE> + then the following code can be used to align the data: +<PRE> +\CSVtotabular{sample.csv}{lccc}{% +\bfseries Name & +\bfseries Assignment 1& +\bfseries Assignment 2& +\bfseries Total\\}{% +\insertName & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal\\}{% + & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal} +</PRE> + The result of this code is shown in + Table <A HREF="manual.html#tab:ex1">1</A><A NAME="tex2html4" + HREF="#foot872"><SUP>4</SUP></A>. +<BR><P></P> +<DIV ALIGN="CENTER"> + +<A NAME="tab:ex1"></A> +<BR> +<BR> +<DIV ALIGN="CENTER"> +<A NAME="873"></A> +<TABLE CELLPADDING=3> +<CAPTION><STRONG>Table 1:</STRONG> +Example <A HREF="manual.html#ex:tab1">4</A></CAPTION> +<TR><TH ALIGN="LEFT"><B>Name </B></TH> +<TH ALIGN="CENTER"><B>Assignment 1 </B></TH> +<TH ALIGN="CENTER"><B>Assignment 2 </B></TH> +<TH ALIGN="CENTER"><B>Total</B></TH> +</TR> +<TR><TD ALIGN="LEFT">A. Smith</TD> +<TD ALIGN="CENTER">80</TD> +<TD ALIGN="CENTER">70</TD> +<TD ALIGN="CENTER">150</TD> +</TR> +<TR><TD ALIGN="LEFT">B. Jones</TD> +<TD ALIGN="CENTER">60</TD> +<TD ALIGN="CENTER">80</TD> +<TD ALIGN="CENTER">140</TD> +</TR> +<TR><TD ALIGN="LEFT">J. Doe</TD> +<TD ALIGN="CENTER">85</TD> +<TD ALIGN="CENTER">75</TD> +<TD ALIGN="CENTER">160</TD> +</TR> +<TR><TD ALIGN="LEFT"> </TD> +<TD ALIGN="CENTER">75</TD> +<TD ALIGN="CENTER">75</TD> +<TD ALIGN="CENTER">150</TD> +</TR> +</TABLE></DIV> + +</DIV> +<BR> +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<BR> +<BR> + + <TT>\ifnextrowlast</TT>{<I>last-code</I>}{<I>not-last-code</I>} +<BR> +<BR> +The command <TT>\ifnextrowlast</TT> can be used to vary what happens + on the last but one row. The following example illustrates + this by placing <TT>\hline\hline</TT> after the penultimate row. + +<P> +<A NAME="ex:tab2"></A> +<H2><A NAME="SECTION00052000000000000000"> +Example 5 (Adding Lines)</A> +</H2> +<PRE> +\CSVtotabular{sample.csv}{|l|ccc|}{% +\hline\bfseries Name & +\bfseries Assignment 1& +\bfseries Assignment 2& +\bfseries Total\\\hline\hline}{% +\insertName & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal +\ifnextrowlast{\\\hline\hline}{\\}}{% + & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal\\\hline} +</PRE> +See the PDF version (<TT><A NAME="tex2html7" + HREF="csvtools.pdf">csvtools.pdf</A></TT>) of this +documentation for an illustration of the results. +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<A NAME="ex:tab3"></A> +<H2><A NAME="SECTION00053000000000000000"> +Example 6 (Added Complexity)</A> +</H2> + In this example, <TT>\multicolumn</TT> is used to override + the column specifier for the first column in the + last row. +<PRE> +\CSVtotabular{sample2.csv}{|l|ccc|}{% +\hline\bfseries Name & +\bfseries Assignment 1 & +\bfseries Assignment 2 & +\bfseries Total\\\hline\hline +}{% +\insertName & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal +\ifnextrowlast{\\\hline\multicolumn{1}{l|}{}}{\\} +}{% + & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal\\\cline{2-4} +} +</PRE> + Notice that instead of placing <code>\multicolumn{1}{l|}{}</code> + at the start of the final argument, it is instead + placed in the first argument to <TT>\ifnextrowlast</TT><A NAME="tex2html8" + HREF="#foot877"><SUP>5</SUP></A>. +See the PDF version (<TT><A NAME="tex2html10" + HREF="csvtools.pdf">csvtools.pdf</A></TT>) of this +manual for an illustration of the results. +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION00060000000000000000"> +Converting CSV file into longtable environment</A> +</H1> + +The command <TT>\CSVtolongtable</TT> works in the same way as <TT>\CSVtotabular</TT> but + creates a <TT>longtable</TT> environment instead of a <TT>tabular</TT> environment. + +<P> +<A NAME="ex:long"></A> +<H2><A NAME="SECTION00061000000000000000"> +Example 7 (Using a longtable environment)</A> +</H2> +Suppose the CSV file in the previous example, contains, say, 100 entries. +This will no longer fit onto one page, so it would be better to use +<TT>CSVtolongtable</TT> instead. For example: +<PRE> +\CSVtolongtable{sample.csv}{|l|ccc|}{% +\caption{Student Marks}\label{tab:students}\\ +\hline +\bfseries Name & +\bfseries Assignment 1 & +\bfseries Assignment 2 & +\bfseries Total\\\hline +\endfirsthead +\caption[]{Student Marks}\\ +\hline +\bfseries Name & +\bfseries Assignment 1 & +\bfseries Assignment 2 & +\bfseries Total\\\hline +\endhead +\hline +\multicolumn{3}{r}{\em Continued on next page} +\endfoot +\hline +\endlastfoot}{% +\insertName & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal +\ifnextrowlast{\\\hline\hline}{\\}}{% + & \insertbyname{Assignment 1} & + \insertbyname{Assignment 2} & +\insertTotal\\} +</PRE> +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION00070000000000000000"> +Associated Counters</A> +</H1> + +<P> +Within the <TT>\CSVtotabular</TT>, <TT>\CSVtolongtable</TT> and +<TT>\applyCSVfile</TT> commands, there are two + counters, <TT>csvlinenum</TT> and <TT>csvrownumber</TT>. + The former, <TT>csvlinenum</TT>, is the current line number in the CSV + file, whereas the latter, <TT>csvrownumber</TT>, is the current + data row. Of the two counters, <TT>csvrownumber</TT> is likely to be + the most useful. + +<P> +<A NAME="ex:stripy"></A> +<H2><A NAME="SECTION00071000000000000000"> +Example 8 (Stripy Table)</A> +</H2> +David Carlisle's <TT>colortbl</TT> package defines the command +<TT>\rowcolor</TT> which enables you to specify the row colour. +Suppose you want a stripy table<A NAME="tex2html11" + HREF="#foot297"><SUP>6</SUP></A>, + this can be achieved as follows: +<PRE> +\CSVtotabular{sample2.csv}{lccc}{% +\rowcolor{green}\bfseries Name & +\bfseries Assignment 1 & +\bfseries Assignment 2 & +\bfseries Total\\\rowcolor{blue} +}{% +\insertName & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal +\ifthenelse{\isodd{\value{csvrownumber}}}{% +\\\rowcolor{green}}{\\\rowcolor{blue}} +}{% + & +\insertbyname{Assignment 1} & +\insertbyname{Assignment 2} & +\insertTotal +} +</PRE> +See the PDF version (<TT><A NAME="tex2html13" + HREF="csvtools.pdf">csvtools.pdf</A></TT>) +for an illustration of the resulting table. +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<A NAME="ex:mailref"></A> +<H2><A NAME="SECTION00072000000000000000"> +Example 9 (More Mail Merging)</A> +</H2> +This is an example of mail merging where the letter reference +is generated from the value of <TT>csvrownumber</TT>. The CSV file +is as used in Example <A HREF="manual.html#ex:mail">1</A>. +<PRE> +\applyCSVfile{details.csv}{% +\begin{letter}{\insertName\\\insertAddress} +\opening{Dear \insertName} + +\textbf{Ref : } interview.\thecsvrownumber + +You are invited to an interview at \insertTime\ on the \insertDate. + +\closing{Yours Sincerely} +\end{letter}} +</PRE> +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION00080000000000000000"> +Cross-Referencing</A> +</H1> + +<P> +Labels can be generated using the standard + <TT>\label</TT> command, but you will need some way + to make each label unique. Example <A HREF="manual.html#ex:ref1">10</A> + does this by using <TT>\thecsvrownumber</TT>, + whereas Example <A HREF="manual.html#ex:ref2">11</A> uses <TT>\insert</TT><I>identifier</I>. + +<P> +<A NAME="ex:ref1"></A> +<H2><A NAME="SECTION00081000000000000000"> +Example 10 (Labelling within <TT>\applyCSVfile</TT>)</A> +</H2> + Example <A HREF="manual.html#ex:ps">2</A> can be modified to + label each figure: +<PRE> +\applyCSVfile{sample3.csv}{ +\begin{figure} +\centerline{\includegraphics{\insertFile}} +\caption{\insertCaption} +\label{fig:pic\thecsvrownumber} +\end{figure}} +</PRE> + This example uses + <code>\label{fig:pic\thecsvrownumber}</code>, so the first figure +generated by this <TT>\applyCSVfile</TT> command will have the +label <TT>fig:pic1</TT>, the second <TT>fig:pic2</TT> etc. +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<A NAME="ex:ref2"></A> +<H2><A NAME="SECTION00082000000000000000"> +Example 11 (Labelling within <TT>\applyCSVfile</TT>)</A> +</H2> + Modifying the previous example, we now have: +<PRE> +\applyCSVfile{sample3.csv}{ +\begin{figure} +\centerline{\includegraphics{\insertFile}} +\caption{\insertCaption} +\label{fig:\insertFile} +\end{figure}} +</PRE> + The labels for each figure are now: + <TT>fig:circle.ps</TT>, <TT>fig:rectangle.ps</TT> + and <TT>fig:triangle.ps</TT>, respectively. +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +<A NAME="ex:timetogrowth"></A> +<H2><A NAME="SECTION00083000000000000000"> +Example 12 (Labelling within <TT>\CSVtotabular</TT>)</A> +</H2> + This example is slightly more complicated. + The CSV file, <TT>data.csv</TT> looks like: +<PRE> +Incubation Temperature,Incubation Time,Time to Growth +40,120,40 +40,90,60 +35,180,20 +</PRE> +The following code generates a table using the data + with an additional column that generates the experiment + number. (See note <A HREF="manual.html#itm:csvrownumber">8</A>.) +<PRE> +\begin{table} +\caption{Time to Growth Experiments} +\label{tab:exp} +\vspace{10pt} +\centering +\CSVtotabular{data.csv}{cccc}{% + % Header Row +\bfseries Experiment & +\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & +\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & +\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\}{% + % Middle Rows +\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +\thecsvrownumber & +\insertbyname{Incubation Temperature} & +\insertbyname{Incubation Time} & +\insertbyname{Time to Growth} \\}{% + % Final Row +\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +\thecsvrownumber & +\insertbyname{Incubation Temperature} & +\insertbyname{Incubation Time} & +\insertbyname{Time to Growth}} +\par +\end{table} + +It can be seen from Table~\ref{tab:exp}, that +Experiment~\ref{exp:35:180} had the shortest time to growth. +</PRE> + In this example, each experiment has the corresponding label + <TT>exp:</TT><I>Incubation Temperature</I><TT>:</TT><I>Incubation Time</I> + so the first experiment has label <TT>exp:40:120</TT>, the + second experiment has the label <TT>exp:40:90</TT> and the + third experiment has the label <TT>exp:35:180</TT>. + +<P> +Table <A HREF="manual.html#tab:timetogrowth">2</A> shows the resulting table for + this example. + <BR><P></P> +<DIV ALIGN="CENTER"> + +<A NAME="tab:timetogrowth"></A> +<BR> +<BR> +<DIV ALIGN="CENTER"><A NAME="384"></A> +<TABLE CELLPADDING=3> +<CAPTION><STRONG>Table 2:</STRONG> +Time to Growth Experiments</CAPTION> +<TR><TH ALIGN="CENTER"><B>Experiment </B></TH> +<TH ALIGN="CENTER"><B><TABLE CELLPADDING=3> +<TR><TH ALIGN="CENTER">Incubation</TH> +</TR> +<TR><TH ALIGN="CENTER">Temperature</TH> +</TR> +</TABLE> </B></TH> +<TH ALIGN="CENTER"><B><TABLE CELLPADDING=3> +<TR><TH ALIGN="CENTER">Incubation</TH> +</TR> +<TR><TH ALIGN="CENTER">Time</TH> +</TR> +</TABLE> </B></TH> +<TH ALIGN="CENTER"><B><TABLE CELLPADDING=3> +<TR><TH ALIGN="CENTER">Time</TH> +</TR> +<TR><TH ALIGN="CENTER">to</TH> +</TR> +<TR><TH ALIGN="CENTER">Growth</TH> +</TR> +</TABLE></B></TH> +</TR> +<TR><TD ALIGN="CENTER">1</TD> +<TD ALIGN="CENTER">40</TD> +<TD ALIGN="CENTER">120</TD> +<TD ALIGN="CENTER">40</TD> +</TR> +<TR><TD ALIGN="CENTER">2</TD> +<TD ALIGN="CENTER">40</TD> +<TD ALIGN="CENTER">90</TD> +<TD ALIGN="CENTER">60</TD> +</TR> +<TR><TD ALIGN="CENTER">3</TD> +<TD ALIGN="CENTER">35</TD> +<TD ALIGN="CENTER">180</TD> +<TD ALIGN="CENTER">20</TD> +</TR> +</TABLE> +</DIV> +<P> +<DIV ALIGN="CENTER"></DIV> +</DIV> +<BR> +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +The following example is more refined in that it + takes advantage of the fact that the time to growth data consists + of integers only, so the experiment with the maximum growth can be + determined by LaTeX. + +<P> +<A NAME="ex:tablabel"></A> +<H2><A NAME="SECTION00084000000000000000"> +Example 13 (Labelling within <TT>\CSVtotabular</TT>)</A> +</H2> +<PRE> +\newcounter{maxgrowth} +\newcounter{incT} % incubation temperature +\newcounter{inct} % incubation time + +\begin{table} +\caption{Time to Growth Experiments} +\label{tab:exp} +\vspace{10pt} +\centering +\CSVtotabular{data.csv}{cccc}{% + % Header row +\bfseries Experiment & +\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & +\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & +\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\}{% + % Middle rows +\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +\thecsvrownumber & +\insertbyname{Incubation Temperature} & +\insertbyname{Incubation Time} & +\insertbyname{Time to Growth}% +\ifthenelse{\value{maxgrowth}<\insertbyname{Time to Growth}}{% +\setcounter{maxgrowth}{\insertbyname{Time to Growth}}% +\setcounter{incT}{\insertbyname{Incubation Temperature}}% +\setcounter{inct}{\insertbyname{Incubation Time}}}{}% +\\}{% + % Last row +\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +\thecsvrownumber & +\insertbyname{Incubation Temperature} & +\insertbyname{Incubation Time} & +\insertbyname{Time to Growth}% +\ifthenelse{\value{maxgrowth}<\insertbyname{Time to Growth}}{% +\setcounter{maxgrowth}{\insertbyname{Time to Growth}}% +\setcounter{incT}{\insertbyname{Incubation Temperature}}% +\setcounter{inct}{\insertbyname{Incubation Time}}}{}% +} +\par +\end{table} + +As can be seen from Table~\ref{tab:exp}, +Experiment~\ref{exp:\theincT:\theinct} +had the maximum time to growth, with +incubation time \theinct, +incubation temperature \theincT\ and +time to growth, \themaxgrowth. +</PRE> + +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION00090000000000000000"> +Saving Entries</A> +</H1> + Entries can be saved using the command: +<BR> +<BR> + + <TT>\csvSaveEntry</TT>[<I>counter</I>]{<I>identifier</I>}[<I>empty text</I>] +<BR> +<BR> +where <I>counter</I> is a LaTeX counter, by default +<TT>csvrownumber</TT>, + and <I>identifier</I> is the header entry. The entry + can then be used with the command: +<BR> +<BR> + <TT>\csvGetEntry</TT>{<I>counter</I>}{<I>identifier</I>} +<BR> +<BR> +The final optional argument <I>empty text</I> to +<TT>\csvSaveEntry</TT> is the text to use if the entry is blank. +For example, <code>\csvSaveEntry{Time}[MISSING DATA]</code> will +print MISSING DATA if the Time field is blank. + +<P> +The following example illustrates the use of these commands. + +<P> +<A NAME="ex:index"></A> +<H2><A NAME="SECTION00091000000000000000"> +Example 14 (Saving Entries)</A> +</H2> + This example illustrates how you can use one CSV + file to access data in other CSV files. + This example has several CSV files: +<BR> +<BR> +File <TT>index.csv</TT>: +<PRE> +File,Temperature,NaCl,pH +exp25a.csv,25,4.7,0.5 +exp25b.csv,25,4.8,1.5 +exp30a.csv,30,5.12,4.5 +</PRE> + File <TT>exp25a.csv</TT>: +<PRE> +Time,Logcount +0,3.75 +23,3.9 +45,4.0 +</PRE> + File <TT>exp25b.csv</TT>: +<PRE> +Time,Logcount +0,3.6 +60,3.8 +120,4.0 +</PRE> + File <TT>exp30a.csv</TT>: +<PRE> +Time,Logcount +0,3.73 +23,3.67 +60,4.9 +</PRE> + +<P> +It is not possible to nest <TT>\CSVtotabular</TT>, +<TT>\CSVtolongtable</TT> and <TT>\applyCSVfile</TT>, + so if you need to go through <TT>index.csv</TT> and use each file + named in there, you can first go through <TT>index.csv</TT> +storing the information using <TT>\csvSaveEntry</TT> as follows: +<PRE> +\newcounter{maxexperiments} +\applyCSVfile{sample5.csv}{% +\stepcounter{maxexperiments} +\csvSaveEntry{File} +\csvSaveEntry{Temperature} +\csvSaveEntry{NaCl} +\csvSaveEntry{pH} +} +</PRE> + The counter <TT>maxexperiments</TT> simply counts the number of + entries in <TT>index.csv</TT>. + The entries can now be used to generate a table for each + file listed in <TT>index.csv</TT> (the <TT>\whiledo</TT> command +is defined in the <TT>ifthen</TT> package): +<PRE> +\newcounter{experiment} +\whiledo{\value{experiment}<\value{maxexperiments}}{% +\stepcounter{experiment} +\begin{table} +\caption{Temperature = \protect\csvGetEntry{experiment}{Temperature}, +NaCl = \protect\csvGetEntry{experiment}{NaCl}, +pH = \protect\csvGetEntry{experiment}{pH}} +\vspace{10pt} +\centering +\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{% +Time & Log Count\\}{% +\insertTime & \insertLogcount\\}{% +\insertTime & \insertLogcount} + +\end{table} +} +</PRE> + Note that <TT>\csvGetEntry</TT> needs to be <TT>\protect</TT>ed +within the <TT>\caption</TT> command. + +<P> +This example can be modified if, say, you only want the + tables where the temperature is 25: +<PRE> +\setcounter{experiment}{0} +\whiledo{\value{experiment}<\value{maxexperiments}}{% +\stepcounter{experiment} +\ifthenelse{\equal{\csvGetEntry{experiment}{Temperature}}{25}}{% +\begin{table} +\caption{Temperature = \protect\csvGetEntry{experiment}{Temperature}, +NaCl = \protect\csvGetEntry{experiment}{NaCl}, +pH = \protect\csvGetEntry{experiment}{pH}} +\vspace{10pt} +\centering +\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{% +Time & Log Count\\}{% +\insertTime & \insertLogcount\\}{% +\insertTime & \insertLogcount}\par +\end{table}}{} +} +</PRE> + +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION000100000000000000000"> +Pie Charts (csvpie.sty)</A> +</H1> + +<P> +If you want to create a pie chart from data stored in a CSV file, +you can use the <TT>csvpie</TT> package, distributed with the +<TT>csvtools</TT> package. A basic pie chart can be created +using the command: +<BR> +<BR> +<TT>\csvpiechart</TT>[<I>options</I>]{<I>variable</I>}{<I>filename</I>} +<BR> +<BR> +where <I>filename</I> is the name of the CSV file containing the +data, and <I>variable</I> is the command indicating the entry that +contains the value for the given segment. +The starred version of <TT>\csvpiechart</TT> should be used if +the CSV file has no header row. + +<P> +The pie charts have ``inner'' labels on the segment, and +``outer'' labels outside the chart. The labels are given by the +commands <TT>\csvpieinnerlabel</TT> +and <TT>\csvpieouterlabel</TT>. +The default definitions are: +<PRE> +\newcommand{\csvpieouterlabel}{\field{1}} +\newcommand{\csvpieinnerlabel}{\field{2}\%} +</PRE> +This assumes that the second column contains the data, and the +first column contains a description, but can be redefined +as necessary. + +<P> +The pie chart display can be modified using the optional +argument to <TT>\csvpiechart</TT>. +This argument should be a <I>key</I>=<I>value</I> list. +The available keys are as follows: +<DL> +<DT><STRONG>start</STRONG></DT> +<DD>This should be an integer specifying the starting angle +of the first segment. This is 0 by default. + +<P> +</DD> +<DT><STRONG>total</STRONG></DT> +<DD>This should be an integer specifying the sum of all +the segment values. This is 100 by default. + +<P> +</DD> +<DT><STRONG>radius</STRONG></DT> +<DD>This should be a length specifying the radius of the +pie chart. (Default: 2cm) + +<P> +</DD> +<DT><STRONG>inner</STRONG></DT> +<DD>This should be a fraction specifying the relative distance +along the radius to start the inner label. (Default: 0.25) + +<P> +</DD> +<DT><STRONG>outer</STRONG></DT> +<DD>This should be a fraction specifying the relative distance +along the radius to start the outer label. (Default: 1.25) + +<P> +</DD> +<DT><STRONG>cutaway</STRONG></DT> +<DD>This should be a comma-separated list of numbers +corresponding to the segments that should be cut away from the +rest of the pie chart. Since the value may contain commas, the value +should always be enclosed in braces. Ranges may also be used. +If a range is used, all the segments in the given range are +kept together, so, for example, <code>cutaway={1,2}</code> will separate +the first two segments from the pie chart, and the two segments +will also be separated from each other, whereas <code>cutaway={1-2}</code> +will separate the first two segments from the pie chart, but will +keep the two segments together. + +<P> +</DD> +<DT><STRONG>offset</STRONG></DT> +<DD>This should be a fraction specifying the +relative distance along the radius to shift the cut away +segments. (Default: 0.1) + +<P> +</DD> +<DT><STRONG>firstrow</STRONG></DT> +<DD>This should be the number of the first row +containing the actual data. This is equivalent to the optional +argument of <TT>\applyCSVfile</TT> or <TT>\applyCSVfile*</TT>. +</DD> +</DL> + +<P> +Note that T<SMALL>E</SMALL>X performs integer arithmetic. Although the CSV +file may contain decimal numbers, rounding will occur when +constructing the pie charts. + +<P> +The colours for the pie chart segments can be set using the +command: +<BR> +<BR><TT>\csvpiesegmentcol</TT>{<I>n</I>}{<I>colour</I>} +<BR> +<BR> +where <I>n</I> is the segment number, and <I>colour</I> is a +defined colour name. For example, if you want the first segment +in the pie chart to be yellow, do: +<PRE> +\csvpiesegmentcol{1}{yellow} +</PRE> +There are 8 predefined segment colours, if your pie chart has +more than 8 segments, you will need to specify the remainder. + +<P> +You can obtain the colour name for a given segment +using: +<BR> +<BR><TT>\csvpiesegcolname</TT>{<I>n</I>} +<BR> +<BR> +where <I>n</I> is the segment number. The <TT>\csvpiechart</TT> +command uses <TT>\applyCSVfile</TT>, so the <TT>csvrownumber</TT> +counter can be used. This means that you can change the text +colour of the outer label to match the segment. For example: +<PRE> +\renewcommand{\csvpieouterlabel}{% +\color{\csvpiesegcolname{\value{csvrownumber}}}\field{2}} +</PRE> +Note that <TT>\value</TT> must be used since <I>n</I> has to be +a number. + +<P> +If you want grey pie charts, either use the <TT>monochrome</TT> +package option: +<PRE> +\usepackage[monochrome]{csvpie} +</PRE> +or use the command <TT>\colorpiechartfalse</TT> prior to using <TT>\csvpiechart</TT>. +To switch back to colour pie charts, use +<TT>\colorpiecharttrue</TT>. + +<P> +<A NAME="ex:piechart"></A> +<H2><A NAME="SECTION000101000000000000000"> +Example 15 (A Pie Chart)</A> +</H2> +Given a CSV file +(called <TT>fruit.csv</TT>) containing: +<PRE> +Name,Value +Apples,20 +Pears,15 +"lemons,limes",30.5 +Peaches,24.5 +Cherries,10 +</PRE> +Then the value for each segment is given by the second column, so +<I>variable</I> should be <code>\field{2}</code> or <code>\insertValue</code>. +The following code creates a figure containing two +pie charts from the above data (for an image, see the +PDF version of the manual, <TT><A NAME="tex2html15" + HREF="csvtools.pdf">csvtools.pdf</A></TT>): +<PRE> + % Change the way the labels are displayed +\renewcommand{\csvpieinnerlabel}{\sffamily\insertValue\%} +\renewcommand{\csvpieoutlabel}{% +\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily\insertName} + +\begin{figure} +\begin{center} +\begin{tabular}{cc} +\csvpiechart[start=45,cutaway={1,2}]{\insertValue}{fruit.csv} & +\csvpiechart[start=45,cutaway={1-2}]{\insertValue}{fruit.csv} \\ +(a) & (b) +\end{tabular} +\end{center} +\caption{Pie Chart Example (a) cutaway=\{1,2\} (b) cutaway=\{1-2\}} +\end{figure} +</PRE> +The inner and outer labels have been +redefined to use a sans-serif font, and the outer label is in +the same colour as its corresponding segment. +Both pie charts have a starting angle of 45 degrees, and they +have the first two segments cutaway, but in (a) +the first two segments are separated from each other, whereas in +(b), the first two segments are joined, although separated +from the rest of the pie chart. + +<P> +If the CSV file has no header row, the starred version should be +used, e.g.: +<PRE> +\csvpiechart*[cutaway={1-2}]{\field{2}}{fruit.csv} +</PRE> + +<P> + +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> + +<H1><A NAME="SECTION000110000000000000000"> +Sorting Data (csvsort.sty)</A> +</H1> + +<P> +The <TT>csvsort</TT> package (which forms part of the +<TT>csvtools</TT> bundle) provides analogous commands to +those provided by <TT>csvtools</TT>, but the data is first +sorted. The <TT>csvsort</TT> package needs to be loaded +separately in order to access the necessary commands. The package +options should be a list of key=value pairs, where the available +keys are: +<DL> +<DT><STRONG>verbose</STRONG></DT> +<DD>Verbose mode. This is a boolean key. If set, the +comparisons performed by the insertion sort code are printed to +the screen. (Default: <TT>verbose=true</TT>.) + +<P> +</DD> +<DT><STRONG>sort</STRONG></DT> +<DD>This key specifies how to sort the data. It may take +one of the following values: + +<UL> +<LI><TT>alphabetical ascending</TT> (or just <TT>alphabetical</TT>) +</LI> +<LI><TT>alphabetical descending</TT> +</LI> +<LI><TT>numerical ascending</TT> (or just <TT>numerical</TT>) +</LI> +<LI><TT>numerical descending</TT> +</LI> +</UL> +(Default: <TT>sort=alphabetical ascending</TT>) + +<P> +</DD> +<DT><STRONG>variable</STRONG></DT> +<DD>The sort variable. (Default: <code>sort=\field{1}</code>) + +<P> +</DD> +<DT><STRONG>sfirstdataline</STRONG></DT> +<DD>The line on which the data starts in a data +file without a header row. (Default: <TT>sfirstdataline=1</TT>.) + +<P> +</DD> +<DT><STRONG>firstdataline</STRONG></DT> +<DD>The line on which the data starts in a data +file with a header row. (Default: <TT>firstdataline=2</TT>.) +</DD> +</DL> + +<P> +Note that the <TT>csvsort</TT> package requires Éamonn McManus' +<TT>compare.tex</TT> file. The <TT>csvsort</TT> package uses +an insertion sort method to sort the data, so large amounts of data +may slow processing time. The following commands are provided +by <TT>csvsort</TT>: + +<P> + + <TT>\sortapplyCSVfile</TT>optionsfilenametext +<P> +<TT>\sortapplyCSVfile*</TT>optionsfilenametext +<BR> +<BR> +These commands are analogous to <TT>\applyCSVfile</TT> and +<TT>\applyCSVfile*</TT>, except that the data is first sorted. +The optional argument is a key=value list. The keys are the same +as those used in the package options, described above. These options +only apply to the given instance of the command, whereas the +package options apply to all <TT>csvsort</TT> commands, unless +overridden in <I>options</I>. Example, suppose you have a file +called <TT>unsorted.csv</TT> which looks like: +<PRE> +First Name,Surname,Age +Zephram,Lang,60 +Fred,Lang,10 +Barney,Langley,25 +Jane,Brown,5 +Adam,Smith,24 +Bert,Jones,18 +</PRE> +Then +<PRE> +\sortapplyCSVfile[sort=alphabetical,variable=\insertSurname]{unsorted.csv}{% +\insertSurname, \insertbyname{First Name}. Age: \insertAge\par} +</PRE> +will produce the following output: +<P> +Brown, Jane. Age:5 +<P> +Jones, Bart. Age:18 +<P> +Lang, Zephram. Age:60 +<P> +Lang, Fred. Age:10 +<P> +Langley, Barney. Age:25 +<P> +Smith, Adam. Age: 24 +<P> +Note that the data has only been sorted according to the surname. +To sort first by surname, then by first name, you can +do something like: +<PRE> +\sortapplyCSVfile[sort=alphabetical, +variable={\insertSurname,\insertbyname{First Name}}]{unsorted.csv}{% +\insertSurname, \insertbyname{First Name}. Age: \insertAge\par} +</PRE> +As with <TT>\applyCSVfile</TT>, you must use <TT>\field</TT> if +you use the starred version: +<PRE> +\sortapplyCSVfile*[sort=alphabetical, +variable={\field{2},\field{1}}]{unsorted.csv}{% +\field{2}, \field{1}. Age: \field{3}\par} +</PRE> + +<P> +The commands: +<BR> +<BR> +<TT>\sortCSVtotabular</TT>optionsfilenamecol-specfirst rowall but last rowlast row +<BR> +<TT>\sortCSVtolongtable</TT>optionsfilenamecol-specfirst rowall but last rowlast row +<BR> +Are analogous to <TT>\CSVtotabular</TT> and <TT>\CSVtolongtable</TT>, +where, again, <I>options</I> is a list of key=value pairs, the same +as <TT>\sortapplyCSVfile</TT>. Using the same example data as above, +the following command will sort the data according to age (in +numerical order) and place in a tabular environment: +<PRE> +\sortCSVtotabular[sort=numerical,variable=\insertAge]{unsorted.csv}{llr}{% +\bfseries Surname & \bfseries First Name & \bfseries Age\\}{% +\insertSurname & \insertbyname{First Name} & \insertAge\\}{% +\insertSurname & \insertbyname{First Name} & \insertAge} +</PRE> + +<P> +Note that the counter <TT>csvlinenum</TT> has no meaning in the +commands provided by the <TT>csvsort</TT> package. The +<TT>csvrownumber</TT> counter corresponds to the sorted data row. + +<P> + +<H1><A NAME="SECTION000120000000000000000"> +The csvtools.pl Perl Script</A> +</H1> + +<P> +Suppose you have several large CSV files, and you have included +the information into your document using <TT>\applyCSVfile</TT>, +<TT>\CSVtolongtable</TT>, <TT>\CSVtotabular</TT> or +<TT>\csvpiechart</TT>, which has +made life so much easier for you, but you are now required by a +journal to submit your source code in a single <TT>.tex</TT> file. + They don't want all your CSV files, so what do you do? If you +have Perl installed on your system you can use the +<TT>csvtools.pl</TT> Perl script. This has the following syntax: +<BR> +<BR> <TT>csvtools.pl</TT> <I>in-file</I> <I>out-file</I> +<BR> +<BR> +where <I>in-file</I> is the name of your file that contains the +<TT>\applyCSVfile</TT>, <TT>\CSVtotabular</TT> etc + commands, and <I>out-file</I> is a new file which will be created by <TT>csvtools.pl</TT>. This new + file will be the same as <I>in-file</I> except that all +occurances of <TT>\applyCSVfile</TT>, <TT>\CSVtolongtable</TT>, +<TT>\CSVtotabular</TT> and <TT>\csvpiechart</TT> will be replaced +by the relevant data extracted from the named CSV files. + +<P> +<A NAME="ex:perl"></A> +<H2><A NAME="SECTION000121000000000000000"> +Example 16 (csvtools.pl -- Aligning Data)</A> +</H2> + Suppose the file <TT>mydoc.tex</TT> contains the code given in +Example <A HREF="manual.html#ex:tab1">4</A>, with the associated CSV file +<TT>sample.csv</TT> also given in that example. Then if you do: +<PRE> +csvtools.pl mydoc.tex mydocnew.tex +</PRE> +the file <TT>mydocnew.tex</TT> will be created which will be +identical to <TT>mydoc.tex</TT> except the lines + containing the code <code>\CSVtotabular{sample.csv}{lccc}{</code>...<code>}{</code>...<code>}{</code>...<code>}</code> will be replaced +with the lines: +<PRE> + % \CSVtotabular{sample.csv}... converted using csvtools.pl + %>> START INSERT + \begin{tabular}{lccc} + \bfseries Name & + \bfseries Assignment 1 & + \bfseries Assignment 2 & + \bfseries Total\\ + A. Smith&80&70&150\\ + B. Jones&60&80&140\\ + J. Doe&85&75&160\\ + &75&75&150 + \end{tabular}%<< END INSERT +</PRE> +<P> +<DIV ALIGN="CENTER"> +</DIV> + +<P> + +<P> +Similarly, <TT>csvtools.pl</TT> will substitute all occurrances +of <TT>\CSVtolongtable</TT>, <TT>\applyCSVfile</TT> +and <TT>\csvpiechart</TT>. + +<P> + +<H2><A NAME="SECTION000122000000000000000"> +Notes</A> +</H2> + +<OL> +<LI>If perl is located in a directory other than <TT>/usr/bin/</TT> +you will need to edit the first line of <TT>csvtools.pl</TT> as +appropriate. You can find the location using the command: +<PRE> +which perl +</PRE> + +<P> +</LI> +<LI>If you can't directly execute a Perl script, + you can do: +<BR> +<BR> <TT>perl csvtools.pl</TT> <I>in-file</I> <I>out-file</I> + +<P> +</LI> +<LI>You must first LaTeX your document before using +<TT>csvtools.pl</TT> as it checks the log file for any counters +that have been defined. + +<P> +</LI> +<LI><TT>csvtools.pl</TT> only knows about a very limited set +of LaTeX commands. It should be able to understand: +<PRE> +\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{... +</PRE> +(see Example <A HREF="manual.html#ex:index">14</A>), but it won't be able to understand, +say, +<PRE> +\newcommand{\filename}{\csvGetEntry{experiment}{File}} +\CSVtotabular{\filename}{ll}{... +</PRE> +It can pick up on <TT>\addtocounter</TT>, <TT>\stepcounter</TT>, +<TT>\refstepcounter</TT> and <TT>\setcounter</TT> but only if +they are used explicitly in the named <TT>.tex</TT> file. (It +ignores any files that have been included using +<TT>\input</TT>, <TT>\include</TT> etc.) + +<P> +</LI> +<LI>This Perl script has only been tested under Linux, but it +ought to work under other systems. +</LI> +</OL> + +<P> + +<H1><A NAME="SECTION000130000000000000000"></A><A NAME="sec:drawbacks"></A> +<BR> +Bugs/Drawbacks/``Features'' +</H1> + +<OL> +<LI><A NAME="itm:insert"></A> The package doesn't check to see whether +<TT>\insert</TT><I>identifier</I> exists, otherwise you would not +be able to use multiple CSV files with the same headers, as in +Example <A HREF="manual.html#ex:index">14</A>. Therefore it is recommended that + you check to make sure that the command does not already exist. + For example, the T<SMALL>E</SMALL>X commands <TT>\insert</TT> and +<TT>\insertpenalties</TT> already exist, so a blank header or a +header named <TT>penalties</TT> would cause problems. (These two +will now cause an error as from version 1.1, but it's something +bear in mind.) + +<P> +</LI> +<LI>Note also that <TT>\insertbyname</TT> doesn't check + if you've given a valid label, so if no text appears, + check you've spelt it correctly, checking punctuation, spaces and case. + +<P> +</LI> +<LI><A NAME="itm:psbyname"></A> Note that in Example <A HREF="manual.html#ex:ps">2</A>, replacing line 3 with: +<PRE> +\centerline{\includegraphics{\insertbyname{File}}} +</PRE> + will cause an error, as <code>\insertbyname{File}</code> doesn't get + fully expanded by the time it gets passed to + <TT>\includegraphics</TT>, and will prevent +<TT>\includegraphics</TT> from + finding the file. It is possible to get around this using + T<SMALL>E</SMALL>X's <TT>\edef</TT> command: +<PRE> +\edef\psfilename{\insertbyname{File}} +\centerline{\includegraphics{\psfilename}} +</PRE> + +<P> +</LI> +<LI><A NAME="itm:noalign"></A> You can't have commands like +<TT>\hline</TT>, <TT>\cline</TT> and <TT>\multicolumn</TT> in the +first column of the <I>middle</I> or <I>last</I> code of +<TT>\CSVtotabular</TT> or <TT>\CSVtolongtable</TT>. If you do, +it will generate a <code>misplaced \noalign</code> error, instead you +need to put it at the end of the <I>first</I> or <I>middle</I> +code. (See Example <A HREF="manual.html#ex:tab3">6</A>.) + +<P> +</LI> +<LI>You can't have nested <TT>\applyCSVfile</TT>, +<TT>\CSVtolongtable</TT> and <TT>\CSVtotabular</TT> + commands. Nor can you have <TT>\csvpiechart</TT> within +one of these commands (See Example <A HREF="manual.html#ex:index">14</A>) + +<P> +</LI> +<LI>If the CSV file has a header row, it must be on the first +line. + +<P> +</LI> +<LI>It is possible for T<SMALL>E</SMALL>X to run out of memory if you use + <TT>\csvSaveEntry</TT> on a large file. + +<P> +</LI> +<LI><A NAME="itm:csvrownumber"></A> In version 1.0, there was an +inconsistency with <TT>csvrownumber</TT> within +<TT>\applyCSVfile</TT> and <TT>\CSVtotabular</TT>. In the +former it excluded the header row, whereas the latter +included it. This has been changed in version 1.1 so that within +<TT>\applyCSVfile</TT>, <TT>\CSVtotabular</TT> and +<TT>\CSVtolongtable</TT>, <TT>csvrownumber</TT> refers to the +data row (excluding header row.) I hope this doesn't cause +problems, but it makes more sense that they should be +consistent. So if you have no blank lines in your CSV file, +<TT>csvrownumber</TT> should always be 1 more than +<TT>csvlinenumber</TT>. + +<P> +</LI> +</OL> + +<P> + +<H1><A NAME="SECTION000140000000000000000"> +Contact Details</A> +</H1> + +<P> +Dr Nicola Talbot +<BR> +School of Computing Sciences +<BR> +University of East Anglia +<BR> +Norwich. NR4 7TJ. England. + <BR> +<BR> <TT><A NAME="tex2html17" + HREF="http://theoval.cmp.uea.ac.uk/~nlct/">http://theoval.cmp.uea.ac.uk/~nlct/</A></TT> +<P> + +<P> + +<BR><HR><H4>Footnotes</H4> +<DL> +<DT><A NAME="foot869">...identifier</A><A + HREF="manual.html#tex2html1"><SUP>1</SUP></A></DT> +<DD>See Note <A HREF="manual.html#itm:insert">1</A> in Section <A HREF="manual.html#sec:drawbacks">11</A> + +</DD> +<DT><A NAME="foot150">... file</A><A + HREF="manual.html#tex2html2"><SUP>2</SUP></A></DT> +<DD>Remeber to use a letter type of +class file + +</DD> +<DT><A NAME="foot870">... file</A><A + HREF="manual.html#tex2html3"><SUP>3</SUP></A></DT> +<DD>The + <TT>graphics</TT> or <TT>graphicx</TT> package will be +needed. + +</DD> +<DT><A NAME="foot872">...tab:ex1</A><A + HREF="manual.html#tex2html4"><SUP>4</SUP></A></DT> +<DD>Note that <TT>\CSVtotabular</TT> only + puts the data in a <TT>tabular</TT> environment not in a table + +</DD> +<DT><A NAME="foot877">...\ifnextrowlast</A><A + HREF="manual.html#tex2html8"><SUP>5</SUP></A></DT> +<DD>See + Note <A HREF="manual.html#itm:noalign">4</A> in Section <A HREF="manual.html#sec:drawbacks">11</A> + +</DD> +<DT><A NAME="foot297">... table</A><A + HREF="manual.html#tex2html11"><SUP>6</SUP></A></DT> +<DD>This is designed as an +example of how to use the package, not incouragement to produce +garish tables! + +</DD> +</DL> +<BR><HR> +<ADDRESS> +<A href=http://theoval.cmp.uea.ac.uk/~nlct/>Nicola L. C. Talbot</A>. +<A HREF=http://www.cmp.uea.ac.uk/>School of Computing Sciences</A>. +<A HREF=http://www.uea.ac.uk/>University of East Anglia.</A> +Last Modified: 2007-06-26 +</ADDRESS> +</BODY> +</HTML> diff --git a/Master/texmf-dist/doc/latex/csvtools/script/csvtools.pl b/Master/texmf-dist/doc/latex/csvtools/script/csvtools.pl new file mode 100755 index 00000000000..131134124e7 --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/script/csvtools.pl @@ -0,0 +1,1995 @@ +#!/usr/bin/perl -w + +# File : csvtools.pl +# Author : Dr Nicola Talbot +# Date : 26 June 2007 +# Description : Perl script to accompany csvtools.sty +# : Allows you to substitute \CSVtotabular, \CSVtolongtable and \applyCSVfile commands with the appropriate LaTeX code +# Version : 0.6b (1 September 2006). + +# usage : csvtools <in-file> <out-file> + +if ($#ARGV != 1) +{ + die "Syntax : $0 <in-file> <out-file>\n"; +} + +($FILENAME,$OUTPUT) = @ARGV; + +open FILENAME or die "Can't open '$FILENAME'\n"; + +$ext = substr($FILENAME, -4); + +if (($ext eq ".tex") or ($ext eq ".dtx") or ($ext eq ".ltx")) +{ + $LOGFILE = substr($FILENAME,0,length($FILENAME)-4) . ".log"; +} +else +{ + $LOGFILE = $FILENAME . ".log"; +} + +open LOGFILE or die "Can't open log file '$LOGFILE'. Make sure you run LaTeX before using $0\n"; + +while (<LOGFILE>) +{ + if (/\\c@([a-zA-Z]+)=\\count/) + { + $counter{$1} = 0; + } +} + +$counter{'csvrownumber'} = 0; + +close LOGFILE; + +open OUTPUT, ">$OUTPUT" or die; + +# global csvsort options + +$globalsort{'verbose'}=1; +$globalsort{'sort'}='alphabetical ascending'; +$globalsort{'variable'}='\field{1}'; +$globalsort{'sfirstdataline'}=1; +$globalsort{'firstdataline'}=2; + +$keyvaldefaults{'verbose'}='true'; + +$csvpieouterlabel="\\field{1}"; +$csvpieinnerlabel="\\field{2}\\%"; +$separator=","; + +while (<FILENAME>) +{ + $restofline = $_; + local($comment) = ""; + + if ($restofline=~m/(\\*)%/) + { + $n = length($1); + + if ($n%2 == 0) + { + $restofline = "$`$1"; + $comment = "%$'"; + $_ = $restofline; + } + } + + if ($restofline=~/\\setcsvseparator\s*{([^}]*)}/) + { + $separator=$1 if defined($1); + } + + if ($restofline=~/\\renewcommand\*?\s*{?\\csvpieinnerlabel}?/) + { + print OUTPUT $`; + + $restofline=$'; + $lineno=$.; + + ($csvpieinnerlabel,$restofline,$done)=&getnextgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $restofline .= $nextline; + ($csvpieinnerlabel,$restofline,$done)=&getnextgroup($restofline); + } + else + { + die "Unexpected EOF while parsing \\renewcommand on line $lineno\n"; + } + } + + $_ = $restofline; + } + + if ($restofline=~/\\renewcommand\*?\s*{?\\csvpieouterlabel}?/) + { + print OUTPUT $`; + + $restofline=$'; + $lineno=$.; + + ($csvpieouterlabel,$restofline,$done)=&getnextgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $restofline .= $nextline; + ($csvpieouterlabel,$restofline,$done)=&getnextgroup($restofline); + } + else + { + die "Unexpected EOF while parsing \\renewcommand on line $lineno\n"; + } + } + + $_ = $restofline; + } + + while ($restofline=~/\\stepcounter(.*)/) + { + $line = $_; + + ($ctr,$restofline,$done) = &getnextgroup($1); + + $startline=$.; + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($ctr,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; + } + } + + $counter{$ctr}++; + + $_ = $line; + } + + $restofline = $_; + + while ($restofline=~/\\refstepcounter(.*)/) + { + $line = $_; + + ($ctr,$restofline,$done) = &getnextgroup($1); + + $startline=$.; + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($ctr,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; + } + } + + $counter{$ctr}++; + + $_ = $line; + } + + $restofline = $_; + + while ($restofline=~/\\setcounter(.*)/) + { + $line = $_; + + ($ctr,$restofline,$done) = &getnextgroup($1); + + $startline=$.; + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($ctr,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; + } + } + + ($num,$restofline,$done) = &getnextgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($num,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning second argument to \\stepcounter on line $startline\n"; + } + } + + $num=~s/\\value{(.+)}/$counter{$1}/; + + $counter{$ctr} = $num; + + $_ = $line; + } + + $restofline = $_; + + while ($restofline=~/\\addtocounter(.*)/) + { + $line = $_; + + ($ctr,$restofline,$done) = &getnextgroup($1); + + $startline=$.; + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($ctr,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n"; + } + } + + ($num,$restofline,$done) = &getnextgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($num,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning second argument to \\stepcounter on line $startline\n"; + } + } + + $num=~s/\\value{(.+)}/$counter{$1}/; + + $counter{$ctr} = $counter{$ctr} + $num; + + $_ = $line; + } + + $restofline = $_; + + while ($restofline=~/^(.*)\\csvGetEntry(.*)$/) + { + $start = $1; + $restofline = $2; + + ($ctr,$restofline,$done) = &getnextgroup($restofline); + + $startline=$.; + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $restofline = $restofline . $nextline; + + ($ctr,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning first argument to \\csvGetEntry on line $startline\n"; + } + } + + ($entry,$restofline,$done) = &getnextgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $restofline = $restofline . $nextline; + + ($entry,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning first argument to \\csvGetEntry on line $startline\n"; + } + } + $_ = $start . "\\csname $entry\\roman{$ctr}\\endcsname" . $restofline; + #$_ = $start. $data{$entry}[$counter{$ctr}] . $restofline; + } + + $restofline = $_; + + while ($restofline=~/\\usepackage(.*)/) + { + $line = $_; + + $startline=$.; + + $restofline = $1; + + $options = ''; + + if ($restofline=~/^\s*\[/) + { + ($options,$restofline,$done) = &getnextoptionalgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($options,$restofline,$done) = &getnextoptionalgroup($restofline); + } + else + { + die "EOF found whilst scanning optional argument to \\usepackage on line $startline\n"; + } + } + } + + + ($package,$restofline,$done) = &getnextgroup($restofline); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + $restofline = $restofline . $nextline; + + ($package,$restofline,$done) = &getnextgroup($restofline); + } + else + { + die "EOF found whilst scanning argument to \\usepackage on line $startline\n"; + } + } + + if ($package eq 'csvsort' and $options) + { + %hash = &getKeyValues($options,%keyvaldefaults); + + foreach $key (keys(%hash)) + { + $globalsort{$key}=$hash{$key}; + } + } + + $_ = $line; + } + + $restofline = $_; + + if (/^(.*)\\CSVtotabular(.*)$/) + { + print OUTPUT "$1$comment"; + $comment=""; + + $line = $2; + $lineno = $.; + + ($csvname,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for CVS filename on line $lineno\n"; + } + } + + $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; + + $line = $restofline; + + ($alignment,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($alignment,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for CVS column alignment on line $lineno\n"; + } + } + + $line = $restofline; + + ($FIRST,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($FIRST,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\CSVtotabular third argument on line $lineno\n"; + } + } + + $line = $restofline; + + ($MIDDLE,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($MIDDLE,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\CSVtotabular fourth argument on line $lineno\n"; + } + } + + $line = $restofline; + + ($LAST,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($LAST,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\CSVtotabular fifth argument on line $lineno\n"; + } + } + + &csvtotabular($csvname, $alignment, $FIRST, $MIDDLE, $LAST, + "tabular"); + + print OUTPUT "$restofline\n"; + } + elsif (/^(.*)\\CSVtolongtable(.*)$/) + { + print OUTPUT "$1$comment"; + $comment=""; + + $line = $2; + $lineno = $.; + + ($csvname,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $line . $nextline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for CVS filename on line $lineno\n"; + } + } + + $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; + + $line = $restofline; + + ($alignment,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($alignment,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for CVS column alignment on line $.\n"; + } + } + + $line = $restofline; + + ($FIRST,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($FIRST,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\CSVtolongtable third argument on line $.\n"; + } + } + + $line = $restofline; + + ($MIDDLE,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($MIDDLE,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\CSVtolongtable fourth argument on line $.\n"; + } + } + + $line = $restofline; + + ($LAST,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline = <FILENAME>) + { + $line = $restofline . $nextline; + + ($LAST,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\CSVtolongtable fifth argument on line $.\n"; + } + } + + &csvtotabular($csvname, $alignment, $FIRST, $MIDDLE, $LAST, + "longtable"); + + print OUTPUT "$restofline\n"; + } + elsif (/^(.*)\\applyCSVfile(\*)?(.*)$/) + { + print OUTPUT "$1$comment"; + $comment=""; + + $starred = defined($2); + + $restofline = $3; + $lineno = $.; + + $restofline = &eatinitialspaces($restofline); + $restofline = &eatcomments($restofline); + + $startrow = $starred ? 1 : 2; + + if (/^\[([0-9]+)\](.*)/) + { + $startrow = $1; + + $restofline = $2; + } + + $line=$restofline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\applyCSVfile*[$startrow] first argument on line $lineno\n"; + } + } + + $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; + + $line=$restofline; + + ($body,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($body,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\applyCSVfile*[$startrow] second argument on line $lineno\n"; + } + } + + if ($starred) + { + &applyCSVfilestar($csvname, $body, $startrow); + } + else + { + &applyCSVfile($csvname, $body, $startrow); + } + + print OUTPUT "$restofline\n"; + } + elsif (/^(.*)\\sortapplyCSVfile(\*)?(.*)$/) + { + print OUTPUT "$1$comment"; + $comment=""; + + $starred = defined($2); + + $restofline = $3; + $lineno = $.; + + $restofline = &eatinitialspaces($restofline); + $restofline = &eatcomments($restofline); + + $line=$restofline; + + $options = ''; + + if ($restofline=~/^\s*\[/) + { + ($options,$restofline,$done) = &getnextoptionalgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($options,$restofline,$done) = &getnextoptionalgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortapplyCSVfile optional argument on line $lineno\n"; + } + } + } + + $line=$restofline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortapplyCSVfile argument on line $lineno\n"; + } + } + + $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; + + $line=$restofline; + + ($body,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($body,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortapplyCSVfile argument on line $lineno\n"; + } + } + + if ($starred) + { + &sortapplyCSVfilestar($csvname, $body, $options); + } + else + { + &sortapplyCSVfile($csvname, $body, $options); + } + + print OUTPUT "$restofline\n"; + } + elsif (/^(.*)\\sortCSVto(tabular|longtable)(.*)$/) + { + print OUTPUT "$1$comment"; + $comment=""; + + $envname = $2; + $restofline = $3; + $lineno = $.; + + $restofline = &eatinitialspaces($restofline); + $restofline = &eatcomments($restofline); + + $line=$restofline; + + $options = ''; + + if ($restofline=~/^\s*\[/) + { + ($options,$restofline,$done) = &getnextoptionalgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($options,$restofline,$done) = &getnextoptionalgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortCSVto$envname first argument on line $lineno\n"; + } + } + } + + $line=$restofline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n"; + } + } + + $csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/; + + $line=$restofline; + + ($align,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($align,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n"; + } + } + + $line=$restofline; + + ($headrow,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($headrow,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n"; + } + } + + $line=$restofline; + + ($midrows,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($midrows,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n"; + } + } + + $line=$restofline; + + ($lastrow,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($lastrow,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n"; + } + } + + &sortCSVtotabular($csvname,$align,$headrow,$midrows,$lastrow, + $envname,$options); + + print OUTPUT "$restofline\n"; + } + elsif (/^(.*)\\csvpiechart(\*)?(.*)$/) + { + print OUTPUT "$1$comment"; + $comment=""; + + $lineno = $.; + + $starred = defined($2); + + $restofline = $3; + + $restofline = &eatinitialspaces($restofline); + $restofline = &eatcomments($restofline); + + $startrow= $starred ? 1 : 2; + + $line=$restofline; + + ($options,$restofline,$done) = &getnextoptionalgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($options,$restofline,$done) = &getnextoptionalgroup($line); + } + else + { + die "EOF found whilst scanning for \\csvpiechart optional argument on line $lineno\n"; + } + } + + $line=$restofline; + + ($label,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($label,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\csvpiechart second argument on line $lineno\n"; + } + } + + $line=$restofline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + + while (!$done) + { + if ($nextline= <FILENAME>) + { + $line = $restofline . $nextline; + + ($csvname,$restofline,$done) = &getnextgroup($line); + } + else + { + die "EOF found whilst scanning for \\csvpiechart second argument on line $lineno\n"; + } + } + + print OUTPUT "\\csvpiesetkeys{$options}%\n"; + + if ($options=~m/firstrow\s*=\s*(\d+)/) + { + $startrow=$1; + } + + if ($starred) + { + &csvpiechartstar($label, $csvname, $startrow); + } + else + { + &csvpiechart($label, $csvname, $startrow); + } + + print OUTPUT "$restofline\n"; + } + else + { + print OUTPUT "$_$comment"; + } +} + +sub doapplyCSV{ + local($csvrow, $body, @idx, %HoH) = @_; + local($row, $entry); + + $counter{'csvrownumber'} = 0; + print OUTPUT "\\setcounter{csvrownumber}{0}\\relax\n"; + + foreach ($row=1; $row <= $csvrow; $row++) + { + print "."; + + local($THISROW) = $body; + + $THISROW = &csvSaveEntry($THISROW,$row,%HoH); + + foreach $entry ( keys %{$HoH[$row]}) + { + $replacementval=$HoH[$row]{$entry}; + + $THISROW =~ s/\\insertbyname{$entry}/$replacementval/g; + + $THISROW =~ s/\\insert$entry/$replacementval/g; + + local($column) = $idx{$entry}+1; + + $THISROW =~ s/\\field{(\d+)}/$1eq$column?$replacementval:$&/emg; + + $THISROW = &ifnextrowlast($THISROW, ($row==$csvrow-1)); + } + + print OUTPUT "\\refstepcounter{csvrownumber}\\relax\n$THISROW"; + $counter{'csvrownumber'}++; + } +} + +sub doapplyCSVstar{ + local($body, $csvrow, $numcols, @entry) = @_; + local($row,$column); + + print OUTPUT "\\setcounter{csvrownumber}{0}\\relax\n"; + $counter{'csvrownumber'} = 0; + + for ($row=0; $row < $csvrow; $row++) + { + print "."; + + $THISROW = $body; + + for ($column=0; $column < $numcols; $column++) + { + $replacementval=$entry[$row][$column]; + + $THISROW =~ s/\\field{(\d+)}/$1eq$column+1?$replacementval:$&/emg; + + $THISROW = &ifnextrowlast($THISROW, ($row==$csvrow-1)); + } + + print OUTPUT "\\refstepcounter{csvrownumber}$THISROW"; + $counter{'csvrownumber'}++; + } + +} + +sub getCSVvalues{ + local($CSVFILE, $startrow) = @_; + local(@idx, %HoH, @fields); + + open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n"; + + local ($csvrow)=0; + + while (<FH>) + { + if ($. == 1) + { + # get header row + + chop; + + @fields = &getEntries($_); + + local($numcols) = 0; + + foreach $field (@fields) + { + $idx{$field} = $numcols; + + $numcols++; + } + } + elsif ($. >= $startrow) + { + next unless /$separator/; + + chop; + + $csvrow++; + $rec = {}; + + $HoH[$csvrow] = $rec; + + local(@entries) = &getEntries($_); + + local ($i) = 0; + + foreach $e (@entries) + { + $rec->{$fields[$i]} = $e; + $i++; + } + } + } + + close FH; + + return ($csvrow, @idx, %HoH); +} + +sub getCSVvaluesstar +{ + local($CSVFILE, $startrow) = @_; + open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n"; + + $csvrow=0; + + while (<FH>) + { + if ($. >= $startrow) + { + chop; + + @fields = &getEntries($_); + + $numcols = 0; + + foreach $field (@fields) + { + $entry[$csvrow][$numcols] = $field; + + $numcols++; + } + + $csvrow++; + } + } + + close FH; + + return ($csvrow, $numcols, @entry); +} + +sub csvpiechart +{ + local($value, $CSVFILE, $startrow) = @_; + + print "Converting \\csvpiechart[$options]{$label}{$csvname}\n"; + print OUTPUT "% \\csvpiechart[$options]{$label}{$csvname} converted using csvtools.pl\n"; + print OUTPUT "%>> START INSERT\n"; + + # read in data from CSV file + local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow); + + # first compute parameters + + print OUTPUT "\\edef\\csvstartang{\\thecsvstartangle}\\relax\n"; + $body = "\\csvsetsegmentparams{\\thecsvrownumber}{$value}\\relax\n"; + + &doapplyCSV($csvrow, $body, @idx, %HoH); + + print OUTPUT "\\setcounter{csvstartangle}{\\csvstartang}\\relax\n"; + + # compute offsets for cutaway segments + + print OUTPUT "\\ifthenelse{\\equal{\\csvpiecutaways}{}}{}{\\csvcomputeoffsets}\\relax\n"; + + # now do the pie chart + + print OUTPUT "\\begin{tikzpicture}\n"; + + $body = "\\renewcommand*{\\csvpieinnerlabel}{$csvpieinnerlabel}\n"; + $body .= "\\renewcommand*{\\csvpieouterlabel}{$csvpieouterlabel}\n"; + $body .= "\\csvpiesegment{$value}\n"; + + &doapplyCSV($csvrow, $body, %HoH); + + print OUTPUT "\\end{tikzpicture}"; + print OUTPUT "%<< END INSERT\n"; + print "\n"; +} + +sub csvpiechartstar +{ + local($value, $CSVFILE, $startrow) = @_; + + print "Converting \\csvpiechart*[$options]{$label}{$csvname}\n"; + print OUTPUT "% \\csvpiechart*[$options]{$label}{$csvname} converted using csvtools.pl\n"; + print OUTPUT "%>> START INSERT\n"; + + local($csvrow, $numcols, @entry) = &getCSVvaluesstar($CSVFILE, $startrow); + + # first compute parameters + + print OUTPUT "\\edef\\csvstartang{\\thecsvstartangle}\\relax\n"; + $body = "\\csvsetsegmentparams{\\thecsvrownumber}{$value}\\relax\n"; + + &doapplyCSVstar($body, $csvrow, $numcols, @entry); + + print OUTPUT "\\setcounter{csvstartangle}{\\csvstartang}\\relax\n"; + + # compute offsets for cutaway segments + + print OUTPUT "\\ifthenelse{\\equal{\\csvpiecutaways}{}}{}{\\csvcomputeoffsets}\\relax\n"; + + $body = "\\renewcommand*{\\csvpieinnerlabel}{$csvpieinnerlabel}\\relax\n"; + $body .= "\\renewcommand*{\\csvpieouterlabel}{$csvpieouterlabel}\\relax\n"; + $body .= "\\csvpiesegment{$value}\\relax\n"; + + print OUTPUT "\\begin{tikzpicture}\n"; + + &doapplyCSVstar($body, $csvrow, $numcols, @entry); + + print OUTPUT "\\end{tikzpicture}"; + print OUTPUT "%<< END INSERT\n"; + print "\n"; +} + +sub applyCSVfile +{ + my ($CSVFILE,$body,$startrow) = @_; + + print "Converting \\applyCSVfile{$CSVFILE}"; + print OUTPUT "\% \\applyCSVfile{$CSVFILE}... converted using csvtools.pl\n"; + print OUTPUT "\%>> START INSERT\n"; + + # read in data from CSV file + local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow); + + # apply data + + &doapplyCSV($csvrow, $body, @idx, %HoH); + + print "\n"; + + print OUTPUT "\%<< END INSERT\n"; +} + +sub sortapplyCSVfile +{ + my ($CSVFILE,$body,$options) = @_; + + print "Converting \\sortapplyCSVfile{$CSVFILE}"; + print OUTPUT "\% \\sortapplyCSVfile{$CSVFILE}... converted using csvtools.pl\n"; + print OUTPUT "\%>> START INSERT\n"; + + # get options + %hash = &getKeyValues($options) if $options; + + local($startrow) = defined($hash{'firstdataline'}) + ? $hash{'firstdataline'} + : $globalsort{'firstdataline'}; + + local ($sortorder) = $hash{'sort'}; + + # read in data from CSV file + local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow); + + # get sort variable + + local($variable) = defined($hash{'variable'}) + ? $hash{'variable'} + : $globalsort{'variable'}; + + local(@rowdata)=(); + + print OUTPUT "\\bgroup\n"; + + # set field labels + + foreach $entry (keys %{$HoH[1]}) + { + print OUTPUT "\\setcsvfieldlabel{"; + print OUTPUT ($idx{$entry}+1).'}{'; + print OUTPUT "$entry}%\n"; + } + + print OUTPUT "\\def\\csvsortlist{%\n"; + + # construct list + + foreach ($row=1; $row <= $csvrow; $row++) + { + print "."; + + local($sortkey) = $variable; + + $sortkey = &csvSaveEntry($sortkey,$row,%HoH); + + foreach $entry ( keys %{$HoH[$row]}) + { + $replacementval=$HoH[$row]{$entry}; + + $sortkey =~ s/\\insertbyname{$entry}/$replacementval/g; + + $sortkey =~ s/\\insert$entry/$replacementval/g; + + local($column) = $idx{$entry}+1; + + $rowdata[$idx{$entry}] = $replacementval; + + $sortkey =~ s/\\field{(\d+)}/$1eq$column?$replacementval:$&/emg; + } + + print OUTPUT "{$sortkey}{".join($separator,@rowdata)."}"; + + print OUTPUT ($row == $csvrow ? "%\n" : ",%\n"); + } + + print OUTPUT "}%\n"; + + print OUTPUT "\\sortapplyCSVdata"; + + if (defined($sortorder)) + { + print OUTPUT "[$sortorder]"; + } + + print OUTPUT "{\\csvsortlist}{%\n"; + + print OUTPUT "$body}%\n"; + + print OUTPUT "\\egroup\n"; + print OUTPUT "\%<< END INSERT\n"; + + print "\n"; +} + +sub sortapplyCSVfilestar +{ + my ($CSVFILE,$body,$options) = @_; + + print "Converting \\sortapplyCSVfile*{$CSVFILE}"; + print OUTPUT "\% \\sortapplyCSVfile*{$CSVFILE}... converted using csvtools.pl\n"; + print OUTPUT "\%>> START INSERT\n"; + + # get options + %hash = &getKeyValues($options) if $options; + + local($startrow) = defined($hash{'sfirstdataline'}) + ? $hash{'sfirstdataline'} + : $globalsort{'sfirstdataline'}; + + local ($sortorder) = $hash{'sort'}; + + local($csvrow, $numcols, @entry) = &getCSVvaluesstar($CSVFILE, $startrow); + + # get sort variable + + local($variable) = defined($hash{'variable'}) + ? $hash{'variable'} + : $globalsort{'variable'}; + + local(@rowdata)=(); + + print OUTPUT "\\bgroup\n"; + + print OUTPUT "\\def\\csvsortlist{%\n"; + + # construct list + + for ($row=0; $row < $csvrow; $row++) + { + print "."; + + local($sortkey) = $variable; + + for ($column=0; $column < $numcols; $column++) + { + $replacementval=$entry[$row][$column]; + + $sortkey =~ s/\\field{(\d+)}/$1eq$column+1?$replacementval:$&/emg; + $rowdata[$column] = $replacementval; + } + + print OUTPUT "{$sortkey}{".join($separator,@rowdata)."}"; + + print OUTPUT ($row == $csvrow-1 ? "%\n" : ",%\n"); + } + + print OUTPUT "}%\n"; + + print OUTPUT "\\sortapplyCSVdata*"; + + if (defined($sortorder)) + { + print OUTPUT "[$sortorder]"; + } + + print OUTPUT "{\\csvsortlist}{%\n"; + + print OUTPUT "$body}%\n"; + + print OUTPUT "\\egroup\n"; + + print "\n"; + + print OUTPUT "\%<< END INSERT\n"; +} + +sub sortCSVtotabular +{ + my ($CSVFILE,$align,$headrow,$midrows,$lastrow,$envname,$options) = @_; + + print "Converting \\sortCSVto${envname}{$CSVFILE}"; + print OUTPUT "\% \\sortCSVto${envname}{$CSVFILE}... converted using csvtools.pl\n"; + print OUTPUT "\%>> START INSERT\n"; + + # get options + %hash = &getKeyValues($options) if $options; + + local($startrow) = defined($hash{'firstdataline'}) + ? $hash{'firstdataline'} + : $globalsort{'firstdataline'}; + + local ($sortorder) = $hash{'sort'}; + + # read in data from CSV file + local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow); + + # get sort variable + + local($variable) = defined($hash{'variable'}) + ? $hash{'variable'} + : $globalsort{'variable'}; + + local(@rowdata)=(); + + print OUTPUT "\\bgroup\n"; + + # set field labels + + foreach $entry (keys %{$HoH[1]}) + { + print OUTPUT "\\setcsvfieldlabel{"; + print OUTPUT ($idx{$entry}+1).'}{'; + print OUTPUT "$entry}%\n"; + } + + print OUTPUT "\\def\\csvsortlist{%\n"; + + # construct list + + foreach ($row=1; $row <= $csvrow; $row++) + { + print "."; + + local($sortkey) = $variable; + + $sortkey = &csvSaveEntry($sortkey,$row,%HoH); + + foreach $entry ( keys %{$HoH[$row]}) + { + $replacementval=$HoH[$row]{$entry}; + + $sortkey =~ s/\\insertbyname{$entry}/$replacementval/g; + + $sortkey =~ s/\\insert$entry/$replacementval/g; + + local($column) = $idx{$entry}+1; + + $rowdata[$idx{$entry}] = $replacementval; + + $sortkey =~ s/\\field{(\d+)}/$1eq$column?$replacementval:$&/emg; + } + + print OUTPUT "{$sortkey}{".join($separator,@rowdata)."}"; + + print OUTPUT ($row == $csvrow ? "%\n" : ",%\n"); + } + + print OUTPUT "}%\n"; + + if (defined($sortorder)) + { + print OUTPUT "\\setkeys{csvsort.sty}{sort=$sortorder}"; + } + + print OUTPUT "\\sortCSVdatatotabular"; + + print OUTPUT "{$csvrow}{\\csvsortlist}{$align}%\n"; + print OUTPUT "{$headrow}%\n"; + print OUTPUT "{$midrows}%\n"; + print OUTPUT "{$lastrow}%\n"; + print OUTPUT "{$envname}%\n"; + + print OUTPUT "\\egroup\n"; + print OUTPUT "\%<< END INSERT\n"; + + print "\n"; +} + +sub csvSaveEntry +{ + my ($STR,$row,%HoH) = @_; + + $rowctr = "csvrownumber"; + + while (($pos = index($STR, "\\csvSaveEntry")) > -1) + { + $start = substr($STR,0,$pos); + $restofline = substr($STR,$pos+13); + + $restofline = &eatcomments($restofline); + $restofline = &eatinitialspaces($restofline); + + if (substr($restofline,0,1) eq "[") + { + if (($i = index($restofline,"]")) > -1) + { + $rowctr = substr($restofline, 1, $i-1); + + $restofline = substr($restofline, $i+1); + } + else + { + die "unmatched [ in \\csvSaveEntry\n"; + } + + $row = $counter{$rowctr}; + } + + ($group,$restofline,$done) = &getnextgroup($restofline); + + if (!$done) + { + die "argument to \\csvSaveEntry[$rowctr] not found in >>$restofline<<\n"; + } + + $val = $HoH[$row]{$group}; + + $STR = $start . "\\expandafter\\gdef\\csname $group\\roman{$rowctr}\\endcsname{$val}" . $restofline; + + $data{$group}[$row] = $HoH[$row]{$group}; + } + + return $STR; +} + +sub applyCSVfilestar +{ + my ($CSVFILE,$body,$startrow) = @_; + + print "Converting \\applyCSVfile*{$CSVFILE}"; + + $counter{'csvrownumber'} = 0; + local($csvrow, $numcols, @entry) = &getCSVvaluesstar($CSVFILE, $startrow); + + &doapplyCSVstar($body, $csvrow, $numcols, @entry); + + print "\n"; + + print OUTPUT "\%<< END INSERT\n"; +} + +sub csvtotabular +{ + my ($CSVFILE,$ALIGN,$START,$MID,$END,$environment) = @_; + + print "Converting \\CSVtotabular{$CSVFILE}"; + + print OUTPUT "\% \\CSVtotabular{$CSVFILE}... converted using $0\n"; + print OUTPUT "\%>> START INSERT\n"; + + # read in data from CSV file + local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,2); + + print OUTPUT "\\setcounter{csvrownumber}{0}%\n"; + $counter{csvrownumber} = 0; + print OUTPUT "\\begin{$environment}{$ALIGN}\n"; + + print OUTPUT "$START"; + + foreach ($row=1; $row <= $csvrow; $row++ ) + { + print "."; + + if ($row == $csvrow) + { + $THISROW=$END; + } + else + { + $THISROW=$MID; + } + + foreach $entry ( keys %{$HoH[$row]}) + { + $replacementval=$HoH[$row]{$entry}; + + $THISROW =~ s/\\insertbyname{$entry}/$replacementval/g; + + $THISROW =~ s/\\insert$entry/$replacementval/g; + + $column = $idx{$entry}; + + $THISROW =~ s/\\field{$column}/$replacementval/g; + + $THISROW = &ifnextrowlast($THISROW, ($row==$csvrow-1)); + } + + print OUTPUT "\\refstepcounter{csvrownumber}$THISROW"; + $counter{csvrownumber}++; + } + + print OUTPUT "\\end{$environment}"; + print OUTPUT "\%<< END INSERT\n"; + + print "\n"; +} + +sub ifnextrowlast +{ + my ($STR, $nextislast) = @_; + + if (($pos = index($STR, "\\ifnextrowlast")) > -1) + { + $strbegin = substr($STR,0,$pos); + $strend = substr($STR,$pos+14); + + ($firstarg,$strend,$done) = &getnextgroup($strend); + + if (!$done) + { + die "Can't find first argument to \\ifnextrowlast\n"; + } + + ($secondarg,$strend,$done) = &getnextgroup($strend); + + if (!$done) + { + die "Can't find second argument to \\ifnextrowlast\n"; + } + + if ($nextislast) + { + $STR = $strbegin . $firstarg . $strend; + } + else + { + $STR = $strbegin . $secondarg . $strend; + } + } + + return $STR; +} + +sub eatcomments +{ + local ($_) = @_; + + if (m/(\\{1}%[^%]*)*(\\*)%/) + { + $pre = $`; + $pre .= $1 if defined($1); + $pre .= $2; + + local($n) = length($2); + + if ($n%2 == 0) + { + $_ = $pre; + } + } + + return $_; +} + +sub eatinitialspaces +{ + local ($_) = @_; + +# while (substr($STR,0,1) eq " " or substr($STR,0,1) eq "\n" +# or substr($STR,0,1) eq "\r" or substr($STR,0,1) eq "\t") +# { +# $STR = substr($STR,1); +# } + + s/^(\s)*//sg; + + return $_; +} + +sub getnextgroup +{ + my($curline) = @_; + + $curline = &eatcomments($curline); + + $curline = &eatinitialspaces($curline); + + # check to see if current string is blank + + if ($curline!~/[^\s]+/m) + { + return ("",$curline,0); + } + + if (($group = substr($curline,0,1)) ne "{") + { + # next group hasn't been delimited with braces + # return first non-whitespace character + + $curline = substr($curline,1); + + # unless it's a backslash, in which case get command name + + if ($group eq "\\") + { + if ($curline=~/([a-zA-Z]+)(^[a-zA-Z].*)/m) + { + $group = $1; + + $curline = $2; + } + else + { + # command is made up of backslash followed by symbol + + $curline=~/([\W_0-9\s\\])(.*)/m; + + $group = $1; + + $curline = $2; + } + } + + return ($group,$curline,1); + } + + my $pos=index($curline, "{"); + my $startpos=$pos; + my $posopen=0; + my $posclose=0; + + my $bracelevel = 1; + + my $done=0; + + while (!$done) + { + $pos++; + + $posopen = index($curline, "{", $pos); + + # check to make sure it's not a \{ + + while ((substr($curline, $posopen-1,1) eq "\\") and ($posopen > 0)) + { + # count how many backlashes come before it. + + $i = $posopen-1; + + $numbs = 1; + + while ((substr($curline, $i-1,1) eq "\\") and ($i > 0)) + { + $numbs++; + $i--; + } + + # is $numbs is odd, we have a \{, otherwise we have \\{ + + if ($numbs%2 == 0) + { + last; + } + else + { + $posopen = index($curline, "{", $posopen+1); + } + } + + $posclose= index($curline, "}", $pos); + + # check to make sure it's not a \} + + while ((substr($curline, $posclose-1,1) eq "\\") and ($posclose > 0)) + { + # count how many backlashes come before it. + + $i = $posclose-1; + + $numbs = 1; + + while ((substr($curline, $i-1,1) eq "\\") and ($i > 0)) + { + $numbs++; + $i--; + } + + # is $numbs is odd, we have a \}, otherwise we have \\} + + if ($numbs%2 == 0) + { + last; + } + else + { + $posclose = index($curline, "}", $posclose+1); + } + } + + if (($posopen==-1) and ($posclose==-1)) + { + $done=1; + } + elsif ($posopen==-1) + { + $pos=$posclose; + + $bracelevel--; + + if ($bracelevel==0) + { + $group = substr($curline, $startpos+1, $pos-$startpos-1); + + $curline = substr($curline, $pos+1); + + return ($group,$curline,1); + } + } + elsif ($posclose==-1) + { + $pos=$posopen; + + $bracelevel++; + } + elsif ($posopen<$posclose) + { + $pos=$posopen; + + $bracelevel++; + } + elsif ($posclose<$posopen) + { + $pos=$posclose; + + $bracelevel--; + + if ($bracelevel==0) + { + $group = substr($curline, $startpos+1, $pos-$startpos-1); + + $curline = substr($curline, $pos+1); + + return ($group,$curline,1); + } + } + } + + # closing brace must be on another line + + return ("", $curline, 0); +} + +sub getnextoptionalgroup +{ + my($curline) = @_; + + $curline = &eatcomments($curline); + + $curline = &eatinitialspaces($curline); + + # check to see if current string is blank + + if ($curline!~/[^\s]+/m) + { + return ("","",0); + } + + if (($group = substr($curline,0,1)) ne "[") + { + # no optional argument present + return ("", $curline, 1); + } + + $posopen = index($curline, "["); + + # search for first occurance of ] + + $posclose = index($curline, "]"); + + if ($posclose < 0) + { + # closing bracket not on this line + return ("", $curline, 0); + } + + # is there a { in the substring? + + $group = substr($curline, $posopen, $posclose+1); + $contents = $group; + $restofline = substr($curline, $posclose+$posopen+1); + + while (($idx=index($group, "{")) > 0) + { + $post = substr($group, $idx); + + $subgroup=""; + ($subgroup,$remainder,$done) = &getnextgroup($post); + + if ($done) + { + $group = $remainder; + } + else + { + # ] is in a group, so look for next one + $posclose = index($restofline, "]"); + + if ($posclose < 0) + { + # closing bracket not on this line + return ("", $curline, 0); + } + else + { + $contents .= substr($restofline,0,$posclose); + $group = $contents; + } + } + } + + $contents=~s/^\[(.*)\]$/$1/; + + return ($contents, $restofline, 1); +} + +# get all entries in a row +# modified version of code given in Perl FAQ + +sub getEntries{ + local($row)=@_; + + @entries = (); + push(@entries, $+) while $row =~ m{ + "([^\"\\]*(?:\\.[^\"\\]*)*)"$separator? # groups the phrase inside the quotes + | ([^$separator]+)$separator? + | $separator + }gx; + push(@entries, undef) if substr($row,-1,1) eq $separator; + + @entries; +} + +# extract key=value pairs from list + +sub getKeyValues{ + local($list,%defaults)=@_; + local(%hash)=(); + + # remove leading commas and spaces + + $list=~s/^[\s,]*//; + + while ($list=~/^\s*([^,=]+)\s*/) + { + $key=$1; + + $value = ''; + + if ($list=~s/^\s*$key\s*=\s*{/{/) + { + ($value,$list,$done) = &getnextgroup($list); + } + elsif ($list=~s/^\s*$key\s*=\s*([^,]*)\s*//) + { + $value = $1; + } + elsif ($list=~s/^\s*$key\s*(,|$)//) + { + if (defined($defaults{$key})) + { + $value = $defaults{$key}; + } + else + { + print "don't know default value for $key key\n"; + } + } + + $hash{$key} = $value; + + # remove trailing commas + + $list=~s/^[\s,]*//; + } + + %hash; +} + +1; diff --git a/Master/texmf-dist/doc/latex/csvtools/source/csvtools.dtx b/Master/texmf-dist/doc/latex/csvtools/source/csvtools.dtx new file mode 100644 index 00000000000..f11d5e4452c --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/source/csvtools.dtx @@ -0,0 +1,2536 @@ +%\iffalse +% csvtools.dtx generated using makedtx version 0.91b (c) Nicola Talbot +% Command line args: +% -src "csvtools\.sty\Z=>csvtools.sty" +% -src "csvpie\.sty\Z=>csvpie.sty" +% -src "csvsort\.sty\Z=>csvsort.sty" +% -doc "manual.tex" +% -author "Nicola Talbot" +% -dir "source" +% csvtools +% Created on 2007/7/3 10:24 +%\fi +%\iffalse +%<*package> +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%</package> +%\fi +% \iffalse +% Doc-Source file to use with LaTeX2e +% Copyright (C) 2007 Nicola Talbot, all rights reserved. +% \fi +% \iffalse +%<*driver> +\documentclass{ltxdoc} +\usepackage[colorlinks, + bookmarks, + hyperindex=false, + pdfauthor={Nicola Talbot}, + pdftitle={csvtools: A LaTeX2e Package Providing Access to Data Saved in a CSV File}, + pdfkeywords={LaTeX,package,csv}]{hyperref} +\usepackage{csvpie} +\usepackage{colortbl} + + +\renewcommand{\usage}[1]{\hyperpage{#1}} +\renewcommand{\main}[1]{\hyperpage{#1}} +\newcommand{\see}[2]{\emph{see} #1} +\makeatletter +\def\index@prologue{\section*{Index}} +\makeatother +\RecordChanges +\PageIndex +\CheckSum{1878} +\OnlyDescription +\newcommand{\stynamefmt}[1]{\textsf{#1}} +\newcommand{\envname}[1]{\textsf{#1}} + + +\newcommand{\cmdname}[1]{\texttt{\symbol{92}#1}} + +\iffalse + Doc-Source file to use with LaTeX2e + Copyright (C) 2003 Nicola Talbot, all rights reserved. +\fi + + + \newcounter{example} + \newenvironment{example}[2]{\refstepcounter{example}\label{#2}% +\subsection*{Example \theexample\ (#1)}% +\addcontentsline{loe}{section}{\protect\numberline{\theexample}#1}}{\par\centerline{\rule{2in}{1pt}}\par} + +\begin{document} +\DocInput{csvtools.dtx} +\end{document} +%</driver> +%\fi +% \DeleteShortVerb{\|} +% \MakeShortVerb{"} +% \title{csvtools v1.24 : A \LaTeXe\ Package Providing Access to Data Saved in a CSV File} +% \author{Nicola Talbot} +% \date{3rd July 2007} +% \maketitle +% \tableofcontents +% +%\section*{List of Examples} +% +%\makeatletter\@starttoc{loe}\makeatother +% +% \section{Introduction} +% The \stynamefmt{csvtools} package allows you to repeatedly perform +% a set of \LaTeX\ commands on data in each row +% of a comma separated variable (CSV) file. +% This can be used for mail merging, generating +% tables etc. +% +%\changes{1.2}{2006 Sept 1}{separator can now be changed}% +%As from version 1.2, you can specify a different separator. +%To change the separator, use the command:\\[10pt] +%\DescribeMacro{\setcsvseparator}\cmdname{setcsvseparator}\{\meta{separator}\}\\[10pt] +%For example, if your data is separated by colons instead of +%commas, do: +%\begin{verbatim} +%\setcsvseparator{:} +%\end{verbatim} +%\changes{1.2}{2006 Sept 1}{entries can be delimited with double quotes}% +%If your separator occurs within an entry, the entry must be +%enclosed in double quotes, for example: +%\begin{verbatim} +%Name,Address,Telephone +%A.N. Other,"1 The Street,The Town",0123456789 +%\end{verbatim} +%Be careful of \TeX\ special characters occuring within a CSV +%file, for example: +%\begin{verbatim} +%Name,Address,Telephone +%Jack \& Jill,"2 The Street,The Town",0123456789 +%\end{verbatim} +% +% \section{Mail Merging and Similar Applications} +% +%\DescribeMacro{\applyCSVfile}\noindent +% \cmdname{applyCSVfile}[\meta{n}]\{\meta{filename}\}\{\meta{text}\}\\ +% \cmdname{applyCSVfile*}[\meta{n}]\{\meta{filename}\}\{\meta{text}\}\\[10pt] +% Letters can be generated using data given in +% each line from \meta{filename}. +% If the CSV file contains a header row, the +% unstarred version of \cmdname{applyCSVfile} should +% be used, otherwise the starred version \cmdname{applyCSVfile*} +% should be used. The optional argument \meta{n} +% specifies on which line the actual data (not header line) +% starts. The unstarred version defaults to line 2 +% (the header row is always assumed to be on line 1) +% and the starred version defaults to 1. +% +% With the unstarred version, the entries in the header row +% are used to generate commands of the form +% \DescribeMacro{\insert...}\cmdname{insert}\meta{identifier}\footnote{See Note~\ref{itm:insert} in Section~\ref{sec:drawbacks}} +% to access corresponding elements +% in the row currently being processed. For example, +% suppose the first line of the CSV file looks like: +%\begin{verbatim} +%Name,Address,Time,Date +%\end{verbatim} +% then the commands \cmdname{insertName}, \cmdname{insertAddress}, +% \cmdname{insertTime} and \cmdname{insertDate} are +% created, allowing you to use the entries in the first, +% second, third and fourth columns of the current row. +% If the header text contains non-alphabetical characters, +% e.g.\ \texttt{Full Name}, then you will need to use +% \DescribeMacro{\insertbyname}\cmdname{insertbyname}\texttt{\{}\meta{text}\texttt{\}}, +% e.g.\ \verb'\insertbyname{Full Name}'. +% +%Alternatively, you can use the +%\DescribeMacro{\field}\cmdname{field}\{\meta{col}\} command, where +%\meta{col} is the column number of the entry, so \verb"\field{1}" +%indicates the first entry in the current row and \verb"\field{2}" +%indicates the second entry in the current row. +% +% \begin{example}{Mail Merging}{ex:mail} +% Suppose there is a file called \texttt{details.csv} that has the +% following contents: +%\begin{verbatim} +%Name,Address,Time,Date +%Miss A. Person,1 The Road\\The Town\\AB1 2XY,15.00,4th May 2004 +%Mr A. N. Other,2 The Road\\The Town\\AB1 2XY,15.30,11th May 2004 +%\end{verbatim} +%then the following code can be used to generate a letter for each +%person in the CSV file\footnote{Remeber to use a letter type of +%class file}: +%\begin{verbatim} +%\applyCSVfile{details.csv}{% +%\begin{letter}{\insertName\\\insertAddress} +%\opening{Dear \insertName} +% +%You are invited to an interview at \insertTime\ on the \insertDate. +% +%\closing{Yours Sincerely} +%\end{letter}} +%\end{verbatim} +% Note that you could also use \verb'\insertbyname{Name}' etc instead +% of \cmdname{insertName} etc. Also note that you need to specify the +% file extension when specifying the filename. +%\end{example} +% +% \begin{example}{Multiple Figures}{ex:ps} +% Suppose \texttt{sample3.csv} looks like: +%\begin{verbatim} +%File,Caption +%circle.ps,A Circle +%rectangle.ps,A Rectangle +%triangle.ps,A Triangle +%\end{verbatim} +% Assuming that the files \texttt{circle.ps}, \texttt{rectangle.ps} +% and \texttt{triangle.ps} exist, then the following code will +% generate a figure for each graphics file\footnote{The +% \stynamefmt{graphics} or \stynamefmt{graphicx} package will be +%needed.}: +%\begin{verbatim} +%\applyCSVfile{sample3.csv}{ +%\begin{figure} +%\centerline{\includegraphics{\insertFile}} +%\caption{\insertCaption} +%\end{figure}} +%\end{verbatim} +% Note that in this example, you can't use \verb'\insertbyname{File}'. +% (See Note~\ref{itm:psbyname} in Section~\ref{sec:drawbacks}.) +%\end{example} +% +% \begin{example}{Mail Merging using \cmdname{field}}{ex:field} +% Suppose there is a file called \texttt{details.csv} that has the +% following contents: +%\begin{verbatim} +%Miss A. Person,1 The Road\\The Town\\AB1 2XY,15.00,4th May 2004 +%Mr A. N. Other,2 The Road\\The Town\\AB1 2XY,15.30,11th May 2004 +%\end{verbatim} +%In this case the data has no header file, so the starred version +%of \cmdname{applyCSVfile} must be used. Since there is no header +%file, you must use \cmdname{field} to access the entries: +%\begin{verbatim} +%\applyCSVfile*{details.csv}{% +%\begin{letter}{\field{1}\\\field{2}} +%\opening{Dear \field{1}} +% +%You are invited to an interview at \field{3}\ on the \field{4}. +% +%\closing{Yours Sincerely} +%\end{letter}} +%\end{verbatim} +%\end{example} +% +% \section{Converting data in a CSV file into a tabular environment} +% \DescribeMacro{\CSVtotabular} +% \cmdname{CSVtotabular}\{\meta{filename}\}\{\meta{col-align}\}\{\meta{first}\}\{\meta{middle}\}\{\meta{last}\}\\[10pt] +% \meta{filename} is the name of the CSV file which must have a header row on line~1, +% \meta{col-align} is the column alignment argument that gets passed +% to the \envname{tabular} environment, \meta{first} +% is the code for the first line, \meta{middle} is the code +% for the middle lines and \meta{last} is the code for the last line. +% This is best demonstrated with an example. +% +% \begin{example}{Aligning Data from a CSV file}{ex:tab1} +% Suppose the file \texttt{sample.csv} looks like: +%\begin{verbatim} +%Name,Assignment 1,Assignment 2,Total +%A. Smith,80,70,150 +%B. Jones,60,80,140 +%J. Doe,85,75,160 +%,75,75,150 +%\end{verbatim} +% then the following code can be used to align the data: +%\begin{verbatim} +%\CSVtotabular{sample.csv}{lccc}{% +%\bfseries Name & +%\bfseries Assignment 1& +%\bfseries Assignment 2& +%\bfseries Total\\}{% +%\insertName & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal\\}{% +% & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal} +%\end{verbatim} +% The result of this code is shown in +% Table~\ref{tab:ex1}\footnote{Note that \cmdname{CSVtotabular} only +% puts the data in a \envname{tabular} environment not in a table}. +%\begin{table} +%\caption{Example~\ref{ex:tab1}} +%\label{tab:ex1} +%\vspace{10pt} +%\centerline{% +%\begin{tabular}{lccc} +%\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\ +%A. Smith&80&70&150\\ +%B. Jones&60&80&140\\ +%J. Doe&85&75&160\\ +% &75&75&150 +%\end{tabular}} +%\end{table} +%\end{example} +% +% \vspace{10pt} +% \DescribeMacro{\ifnextrowlast} +% \cmdname{ifnextrowlast}\{\meta{last-code}\}\{\meta{not-last-code}\}\\[10pt] +% The command \cmdname{ifnextrowlast} can be used to vary what happens +% on the last but one row. The following example illustrates +% this by placing \cmdname{hline}\cmdname{hline} after the penultimate row. +% +% \begin{example}{Adding Lines}{ex:tab2} +%\begin{verbatim} +%\CSVtotabular{sample.csv}{|l|ccc|}{% +%\hline\bfseries Name & +%\bfseries Assignment 1& +%\bfseries Assignment 2& +%\bfseries Total\\\hline\hline}{% +%\insertName & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal +%\ifnextrowlast{\\\hline\hline}{\\}}{% +% & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal\\\hline} +%\end{verbatim} +%This result of this code is shown in Table~\ref{tab:ex2}.\begin{table} +%\caption{Example~\ref{ex:tab2}} +%\label{tab:ex2} +%\vspace{10pt} +%\begin{center} +%\begin{tabular}{|l|ccc|} +%\hline\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\hline\hline +%A. Smith&80&70&150\\ +%B. Jones&60&80&140\\ +%J. Doe&85&75&160\\\hline\hline +% &75&75&150\\\hline +%\end{tabular} +%\end{center} +%\end{table} +%\end{example} +% +% \begin{example}{Added Complexity}{ex:tab3} +% In this example, \cmdname{multicolumn} is used to override +% the column specifier for the first column in the +% last row. +%\begin{verbatim} +%\CSVtotabular{sample2.csv}{|l|ccc|}{% +%\hline\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\hline\hline +%}{% +%\insertName & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal +%\ifnextrowlast{\\\hline\multicolumn{1}{l|}{}}{\\} +%}{% +% & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal\\\cline{2-4} +%} +%\end{verbatim} +% Notice that instead of placing \verb'\multicolumn{1}{l|}{}' +% at the start of the final argument, it is instead +% placed in the first argument to \cmdname{ifnextrowlast}\footnote{See +% Note~\ref{itm:noalign} in Section~\ref{sec:drawbacks}}. +%The result of this code is shown in Table~\ref{tab:ex3}.\begin{table} +%\caption{Example~\ref{ex:tab3}} +%\label{tab:ex3} +%\vspace{10pt} +%\begin{center} +%\begin{tabular}{|l|ccc|} +%\hline\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\hline\hline +%A. Smith&80&70&150\\ +%B. Jones&60&80&140\\ +%J. Doe&85&75&160\\\hline +% \multicolumn{1}{l|}{}&75&75&150\\\cline{2-4} +%\end{tabular} +%\end{center} +%\end{table} +%\end{example} +% +% \section{Converting CSV file into longtable environment} +%\DescribeMacro{\CSVtolongtable} +%The command \cmdname{CSVtolongtable} works in the same way as \cmdname{CSVtotabular} but +% creates a \envname{longtable} environment instead of a \envname{tabular} environment. +% +%\begin{example}{Using a longtable environment}{ex:long} +%Suppose the CSV file in the previous example, contains, say, 100 entries. +%This will no longer fit onto one page, so it would be better to use +%\envname{CSVtolongtable} instead. For example: +%\begin{verbatim} +%\CSVtolongtable{sample.csv}{|l|ccc|}{% +%\caption{Student Marks}\label{tab:students}\\ +%\hline +%\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\hline +%\endfirsthead +%\caption[]{Student Marks}\\ +%\hline +%\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\hline +%\endhead +%\hline +%\multicolumn{3}{r}{\em Continued on next page} +%\endfoot +%\hline +%\endlastfoot}{% +%\insertName & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal +%\ifnextrowlast{\\\hline\hline}{\\}}{% +% & \insertbyname{Assignment 1} & +% \insertbyname{Assignment 2} & +%\insertTotal\\} +%\end{verbatim} +%\end{example} +% +% \section{Associated Counters} +% +% Within the \cmdname{CSVtotabular}, \cmdname{CSVtolongtable} and +%\cmdname{applyCSVfile} commands, there are two +% counters, \DescribeMacro{csvlinenum}\DescribeMacro{csvrownumber}% +% \texttt{csvlinenum} and \texttt{csvrownumber}. +% The former, \texttt{csvlinenum}, is the current line number in the CSV +% file, whereas the latter, \texttt{csvrownumber}, is the current +% data row. Of the two counters, \texttt{csvrownumber} is likely to be +% the most useful. +% +% \begin{example}{Stripy Table}{ex:stripy} +%David~Carlisle's \stynamefmt{colortbl} package defines the command +%\cmdname{rowcolor} which enables you to specify the row colour. +%Suppose you want a stripy table\footnote{This is designed as an +%example of how to use the package, not incouragement to produce +%garish tables!}, +% this can be achieved as follows: +%\begin{verbatim} +%\CSVtotabular{sample2.csv}{lccc}{% +%\rowcolor{green}\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\rowcolor{blue} +%}{% +%\insertName & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal +%\ifthenelse{\isodd{\value{csvrownumber}}}{% +%\\\rowcolor{green}}{\\\rowcolor{blue}} +%}{% +% & +%\insertbyname{Assignment 1} & +%\insertbyname{Assignment 2} & +%\insertTotal +%} +%\end{verbatim} +%The resulting table is illustrated in Table~\ref{tab:stripy}. +%\begin{table}[htb] +%\caption{Stripy Table Example} +%\label{tab:stripy} +%\vspace{10pt} +%\setcounter{csvrownumber}{0} +%\begin{tabular}{lccc} +%\rowcolor{green}\bfseries Name & +%\bfseries Assignment 1 & +%\bfseries Assignment 2 & +%\bfseries Total\\\rowcolor{blue} +%\refstepcounter{csvrownumber}A. Smith & +%80 & +%70 & +%150 +%\ifthenelse{\isodd{\value{csvrownumber}}}{\\\rowcolor{green}}{\\\rowcolor{blue}} +%\refstepcounter{csvrownumber}B. Jones & +%60 & +%80 & +%140 +%\ifthenelse{\isodd{\value{csvrownumber}}}{\\\rowcolor{green}}{\\\rowcolor{blue}} +%\refstepcounter{csvrownumber}J. Doe & +%85 & +%75 & +%160 +%\ifthenelse{\isodd{\value{csvrownumber}}}{\\\rowcolor{green}}{\\\rowcolor{blue}} +%\refstepcounter{csvrownumber} & +%75 & +%75 & +%150 +%\end{tabular} +%\end{table} +%\end{example} +% +%\begin{example}{More Mail Merging}{ex:mailref} +%This is an example of mail merging where the letter reference +%is generated from the value of \texttt{csvrownumber}. The CSV file +%is as used in Example~\ref{ex:mail} on page~\pageref{ex:mail}.\begin{verbatim} +%\applyCSVfile{details.csv}{% +%\begin{letter}{\insertName\\\insertAddress} +%\opening{Dear \insertName} +% +%\textbf{Ref : } interview.\thecsvrownumber +% +%You are invited to an interview at \insertTime\ on the \insertDate. +% +%\closing{Yours Sincerely} +%\end{letter}} +%\end{verbatim} +%\end{example} +% +% \section{Cross-Referencing} +% +% Labels can be generated using the standard +% \cmdname{label} command, but you will need some way +% to make each label unique. Example~\ref{ex:ref1} +% does this by using \cmdname{thecsvrownumber}, +% whereas Example~\ref{ex:ref2} uses \cmdname{insert}\meta{identifier}. +% +% \begin{example}{Labelling within \cmdname{applyCSVfile}}{ex:ref1} +% Example~\ref{ex:ps} on page~\pageref{ex:ps} can be modified to label each figure: +%\begin{verbatim} +%\applyCSVfile{sample3.csv}{ +%\begin{figure} +%\centerline{\includegraphics{\insertFile}} +%\caption{\insertCaption} +%\label{fig:pic\thecsvrownumber} +%\end{figure}} +%\end{verbatim} +% This example uses +% \verb'\label{fig:pic\thecsvrownumber}', so the first figure +%generated by this \cmdname{applyCSVfile} command will have the +%label \texttt{fig:pic1}, the second \texttt{fig:pic2} etc. +%\end{example} +% +% \begin{example}{Labelling within \cmdname{applyCSVfile}}{ex:ref2} +% Modifying the previous example, we now have: +%\begin{verbatim} +%\applyCSVfile{sample3.csv}{ +%\begin{figure} +%\centerline{\includegraphics{\insertFile}} +%\caption{\insertCaption} +%\label{fig:\insertFile} +%\end{figure}} +%\end{verbatim} +% The labels for each figure are now: +% \texttt{fig:circle.ps}, \texttt{fig:rectangle.ps} +% and \texttt{fig:triangle.ps}, respectively. +%\end{example} +% +%\begin{example}{Labelling within \cmdname{CSVtotabular}}{ex:timetogrowth} +% This example is slightly more complicated. +% The CSV file, \texttt{data.csv} looks like: +%\begin{verbatim} +%Incubation Temperature,Incubation Time,Time to Growth +%40,120,40 +%40,90,60 +%35,180,20 +%\end{verbatim} +%The following code generates a table using the data +% with an additional column that generates the experiment +% number. (See note~\ref{itm:csvrownumber}.) +%\begin{verbatim} +%\begin{table} +%\caption{Time to Growth Experiments} +%\label{tab:exp} +%\vspace{10pt} +%\centering +%\CSVtotabular{data.csv}{cccc}{% +% % Header Row +%\bfseries Experiment & +%\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & +%\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & +%\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\}{% +% % Middle Rows +%\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +%\thecsvrownumber & +%\insertbyname{Incubation Temperature} & +%\insertbyname{Incubation Time} & +%\insertbyname{Time to Growth} \\}{% +% % Final Row +%\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +%\thecsvrownumber & +%\insertbyname{Incubation Temperature} & +%\insertbyname{Incubation Time} & +%\insertbyname{Time to Growth}} +%\par +%\end{table} +% +%It can be seen from Table~\ref{tab:exp}, that +%Experiment~\ref{exp:35:180} had the shortest time to growth. +%\end{verbatim} +% In this example, each experiment has the corresponding label +% \texttt{exp:}\meta{Incubation Temperature}\texttt{:}\meta{Incubation Time} +% so the first experiment has label \texttt{exp:40:120}, the +% second experiment has the label \texttt{exp:40:90} and the +% third experiment has the label \texttt{exp:35:180}. +% +% Table~\ref{tab:timetogrowth} shows the resulting table for +% this example. +% \begin{table} +%\caption{Time to Growth Experiments} +%\label{tab:timetogrowth} +%\vspace{10pt} +%\centering +%\begin{tabular}{cccc} +%\bfseries Experiment & +%\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & +%\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & +%\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\ +% 1 & 40 & 120 & 40\\ +% 2 & 40 & 90 & 60\\ +% 3 & 35 & 180 & 20 +%\end{tabular} +%\par +% \end{table} +%\end{example} +% +% The following example is more refined in that it +% takes advantage of the fact that the time to growth data consists +% of integers only, so the experiment with the maximum growth can be +% determined by \LaTeX. +% +% \begin{example}{Labelling within \cmdname{CSVtotabular}}{ex:tablabel} +%\begin{verbatim} +%\newcounter{maxgrowth} +%\newcounter{incT} % incubation temperature +%\newcounter{inct} % incubation time +% +%\begin{table} +%\caption{Time to Growth Experiments} +%\label{tab:exp} +%\vspace{10pt} +%\centering +%\CSVtotabular{data.csv}{cccc}{% +% % Header row +%\bfseries Experiment & +%\bfseries \begin{tabular}{c}Incubation\\Temperature\end{tabular} & +%\bfseries \begin{tabular}{c}Incubation\\Time\end{tabular} & +%\bfseries \begin{tabular}{c}Time\\to\\Growth\end{tabular}\\}{% +% % Middle rows +%\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +%\thecsvrownumber & +%\insertbyname{Incubation Temperature} & +%\insertbyname{Incubation Time} & +%\insertbyname{Time to Growth}% +%\ifthenelse{\value{maxgrowth}<\insertbyname{Time to Growth}}{% +%\setcounter{maxgrowth}{\insertbyname{Time to Growth}}% +%\setcounter{incT}{\insertbyname{Incubation Temperature}}% +%\setcounter{inct}{\insertbyname{Incubation Time}}}{}% +%\\}{% +% % Last row +%\label{exp:\insertbyname{Incubation Temperature}:\insertbyname{Incubation Time}} +%\thecsvrownumber & +%\insertbyname{Incubation Temperature} & +%\insertbyname{Incubation Time} & +%\insertbyname{Time to Growth}% +%\ifthenelse{\value{maxgrowth}<\insertbyname{Time to Growth}}{% +%\setcounter{maxgrowth}{\insertbyname{Time to Growth}}% +%\setcounter{incT}{\insertbyname{Incubation Temperature}}% +%\setcounter{inct}{\insertbyname{Incubation Time}}}{}% +%} +%\par +%\end{table} +% +%As can be seen from Table~\ref{tab:exp}, +%Experiment~\ref{exp:\theincT:\theinct} +%had the maximum time to growth, with +%incubation time \theinct, +%incubation temperature \theincT\ and +%time to growth, \themaxgrowth. +%\end{verbatim} +% \end{example} +% +% \section{Saving Entries} +% Entries can be saved using the command:\\[10pt] +% \DescribeMacro{\csvSaveEntry} +%\changes{1.22}{2007 January 3}{added final optional argument to 'csvSaveEntry} +% \cmdname{csvSaveEntry}[\meta{counter}]\{\meta{identifier}\}[\meta{empty text}]\\[10pt] +% where \meta{counter} is a \LaTeX\ counter, by default +%\texttt{csvrownumber}, +% and \meta{identifier} is the header entry. The entry +% can then be used with the command:\\[10pt] +% \DescribeMacro{\csvGetEntry} +% \cmdname{csvGetEntry}\{\meta{counter}\}\{\meta{identifier}\}\\[10pt] +%The final optional argument \meta{empty text} to +%\cmdname{csvSaveEntry} is the text to use if the entry is blank. +%For example, \verb|\csvSaveEntry{Time}[MISSING DATA]| will +%print MISSING DATA if the Time field is blank. +% +%The following example illustrates the use of these commands. +% +% \begin{example}{Saving Entries}{ex:index} +% This example illustrates how you can use one CSV +% file to access data in other CSV files. +% This example has several CSV files: +%\\[10pt] +% File \texttt{index.csv}: +%\begin{verbatim} +%File,Temperature,NaCl,pH +%exp25a.csv,25,4.7,0.5 +%exp25b.csv,25,4.8,1.5 +%exp30a.csv,30,5.12,4.5 +%\end{verbatim} +% File \texttt{exp25a.csv}: +%\begin{verbatim} +%Time,Logcount +%0,3.75 +%23,3.9 +%45,4.0 +%\end{verbatim} +% File \texttt{exp25b.csv}: +%\begin{verbatim} +%Time,Logcount +%0,3.6 +%60,3.8 +%120,4.0 +%\end{verbatim} +% File \texttt{exp30a.csv}: +%\begin{verbatim} +%Time,Logcount +%0,3.73 +%23,3.67 +%60,4.9 +%\end{verbatim} +% +% It is not possible to nest \cmdname{CSVtotabular}, +%\cmdname{CSVtolongtable} and \cmdname{applyCSVfile}, +% so if you need to go through \texttt{index.csv} and use each file +% named in there, you can first go through \texttt{index.csv} +%storing the information using \cmdname{csvSaveEntry} as follows: +%\begin{verbatim} +%\newcounter{maxexperiments} +%\applyCSVfile{sample5.csv}{% +%\stepcounter{maxexperiments} +%\csvSaveEntry{File} +%\csvSaveEntry{Temperature} +%\csvSaveEntry{NaCl} +%\csvSaveEntry{pH} +%} +%\end{verbatim} +% The counter \texttt{maxexperiments} simply counts the number of +% entries in \texttt{index.csv}. +% The entries can now be used to generate a table for each +% file listed in \texttt{index.csv} (the \cmdname{whiledo} command +%is defined in the \stynamefmt{ifthen} package): +%\begin{verbatim} +%\newcounter{experiment} +%\whiledo{\value{experiment}<\value{maxexperiments}}{% +%\stepcounter{experiment} +%\begin{table} +%\caption{Temperature = \protect\csvGetEntry{experiment}{Temperature}, +%NaCl = \protect\csvGetEntry{experiment}{NaCl}, +%pH = \protect\csvGetEntry{experiment}{pH}} +%\vspace{10pt} +%\centering +%\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{% +%Time & Log Count\\}{% +%\insertTime & \insertLogcount\\}{% +%\insertTime & \insertLogcount} +% +%\end{table} +%} +%\end{verbatim} +% Note that \cmdname{csvGetEntry} needs to be \cmdname{protect}ed +%within the \cmdname{caption} command. +% +% This example can be modified if, say, you only want the +% tables where the temperature is 25: +%\begin{verbatim} +%\setcounter{experiment}{0} +%\whiledo{\value{experiment}<\value{maxexperiments}}{% +%\stepcounter{experiment} +%\ifthenelse{\equal{\csvGetEntry{experiment}{Temperature}}{25}}{% +%\begin{table} +%\caption{Temperature = \protect\csvGetEntry{experiment}{Temperature}, +%NaCl = \protect\csvGetEntry{experiment}{NaCl}, +%pH = \protect\csvGetEntry{experiment}{pH}} +%\vspace{10pt} +%\centering +%\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{% +%Time & Log Count\\}{% +%\insertTime & \insertLogcount\\}{% +%\insertTime & \insertLogcount}\par +%\end{table}}{} +%} +%\end{verbatim} +% \end{example} +% +%\section{Pie Charts (csvpie.sty)} +% +%\changes{1.2}{2006 Sept 1}{csvpie.sty added} +%If you want to create a pie chart from data stored in a CSV file, +%you can use the \stynamefmt{csvpie} package, distributed with the +%\stynamefmt{csvtools} package. A basic pie chart can be created +%using the command:\\[10pt] +%\DescribeMacro{\csvpiechart}\noindent +%\cmdname{csvpiechart}[\meta{options}]\{\meta{variable}\}\{\meta{filename}\}\\[10pt] +%where \meta{filename} is the name of the CSV file containing the +%data, and \meta{variable} is the command indicating the entry that +%contains the value for the given segment. +%The starred version of \cmdname{csvpiechart} should be used if +%the CSV file has no header row. +% +%The pie charts have ``inner'' labels on the segment, and +%``outer'' labels outside the chart. The labels are given by the +%commands \DescribeMacro{\csvpieinnerlabel}\cmdname{csvpieinnerlabel} +%and \DescribeMacro{\csvpieouterlabel}\cmdname{csvpieouterlabel}. +%The default definitions are: +%\begin{verbatim} +%\newcommand{\csvpieouterlabel}{\field{1}} +%\newcommand{\csvpieinnerlabel}{\field{2}\%} +%\end{verbatim} +%This assumes that the second column contains the data, and the +%first column contains a description, but can be redefined +%as necessary. +% +%The pie chart display can be modified using the optional +%argument to \cmdname{csvpiechart}. +%This argument should be a \meta{key}=\meta{value} list. +%The available keys are as follows: +%\begin{description} +%\item[start] This should be an integer specifying the starting angle +%of the first segment. This is 0 by default. +% +%\item[total] This should be an integer specifying the sum of all +%the segment values. This is 100 by default. +% +%\item[radius] This should be a length specifying the radius of the +%pie chart. (Default: 2cm) +% +%\item[inner] This should be a fraction specifying the relative distance +%along the radius to start the inner label. (Default: 0.25) +% +%\item[outer] This should be a fraction specifying the relative distance +%along the radius to start the outer label. (Default: 1.25) +% +%\item[cutaway] This should be a comma-separated list of numbers +%corresponding to the segments that should be cut away from the +%rest of the pie chart. Since the value may contain commas, the value +%should always be enclosed in braces. Ranges may also be used. +%If a range is used, all the segments in the given range are +%kept together, so, for example, \verb"cutaway={1,2}" will separate +%the first two segments from the pie chart, and the two segments +%will also be separated from each other, whereas \verb"cutaway={1-2}" +%will separate the first two segments from the pie chart, but will +%keep the two segments together. +% +%\item[offset] This should be a fraction specifying the +%relative distance along the radius to shift the cut away +%segments. (Default: 0.1) +% +%\item[firstrow] This should be the number of the first row +%containing the actual data. This is equivalent to the optional +%argument of \cmdname{applyCSVfile} or \cmdname{applyCSVfile*}. +%\end{description} +% +%Note that \TeX\ performs integer arithmetic. Although the CSV +%file may contain decimal numbers, rounding will occur when +%constructing the pie charts. +% +%The colours for the pie chart segments can be set using the +%command\DescribeMacro{\csvpiesegmentcol}:\\[10pt] +%\cmdname{csvpiesegmentcol}\{\meta{n}\}\{\meta{colour}\}\\[10pt] +%where \meta{n} is the segment number, and \meta{colour} is a +%defined colour name. For example, if you want the first segment +%in the pie chart to be yellow, do: +%\begin{verbatim} +%\csvpiesegmentcol{1}{yellow} +%\end{verbatim} +%There are 8 predefined segment colours, if your pie chart has +%more than 8 segments, you will need to specify the remainder. +% +%You can obtain the colour name for a given segment +%using\DescribeMacro{\csvpiesegcolname}:\\[10pt] +%\cmdname{csvpiesegcolname}\{\meta{n}\}\\[10pt] +%where \meta{n} is the segment number. The \cmdname{csvpiechart} +%command uses \cmdname{applyCSVfile}, so the \texttt{csvrownumber} +%counter can be used. This means that you can change the text +%colour of the outer label to match the segment. For example: +%\begin{verbatim} +%\renewcommand{\csvpieouterlabel}{% +%\color{\csvpiesegcolname{\value{csvrownumber}}}\field{2}} +%\end{verbatim} +%Note that \cmdname{value} must be used since \meta{n} has to be +%a number. +% +%If you want grey pie charts, either use the \texttt{monochrome} +%package option: +%\begin{verbatim} +%\usepackage[monochrome]{csvpie} +%\end{verbatim} +%or use the command \DescribeMacro{\colorpiechartfalse}\cmdname{colorpiechartfalse} prior to using \cmdname{csvpiechart}. +%To switch back to colour pie charts, use +%\DescribeMacro{\colorpiecharttrue}\cmdname{colorpiecharttrue}. +% +%\begin{example}{A Pie Chart}{ex:piechart} +%Given a CSV file +%(called \texttt{fruit.csv}) containing: +%\begin{verbatim} +%Name,Value +%Apples,20 +%Pears,15 +%"lemons,limes",30.5 +%Peaches,24.5 +%Cherries,10 +%\end{verbatim} +%Then the value for each segment is given by the second column, so +%\meta{variable} should be \verb"\field{2}" or \verb|\insertValue|. +%The pie charts shown in Figure~\ref{fig:piechart} can be created +%using: +%\begin{verbatim} +% % Change the way the labels are displayed +%\renewcommand{\csvpieinnerlabel}{\sffamily\insertValue\%} +%\renewcommand{\csvpieoutlabel}{% +%\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily\insertName} +% +%\begin{figure} +%\begin{center} +%\begin{tabular}{cc} +%\csvpiechart[start=45,cutaway={1,2}]{\insertValue}{fruit.csv} & +%\csvpiechart[start=45,cutaway={1-2}]{\insertValue}{fruit.csv} \\ +%(a) & (b) +%\end{tabular} +%\end{center} +%\caption{Pie Chart Example (a) cutaway=\{1,2\} (b) cutaway=\{1-2\}} +%\end{figure} +%\end{verbatim} +%The inner and outer labels have been +%redefined to use a sans-serif font, and the outer label is in +%the same colour as its corresponding segment. +%Both pie charts have a starting angle of $45^\circ$, and theyhave the first two segments cutaway, but in (a) +%the first two segments are separated from each other, whereas in +%(b), the first two segments are joined, although separated +%from the rest of the pie chart. +% +%If the CSV file has no header row, the starred version should be +%used, e.g.: +%\begin{verbatim} +%\csvpiechart*[cutaway={1-2}]{\field{2}}{fruit.csv} +%\end{verbatim} +% +%\begin{figure}[htbp] +%\begin{center} +%\begin{tabular}{cc} +%\csvpiesetkeys{start=45,cutaway={1,2}}% +%\edef\csvstartang{\thecsvstartangle}\relax +%\setcounter{csvrownumber}{0}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{20}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{15}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{30.5}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{24.5}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{10}\relax +%\setcounter{csvstartangle}{\csvstartang}\relax +%\ifthenelse{\equal{\csvpiecutaways}{}}{}{\csvcomputeoffsets}\relax +%\begin{tikzpicture} +%\setcounter{csvrownumber}{0}\relax +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily20\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Apples} +%\csvpiesegment{20} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily15\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Pears} +%\csvpiesegment{15} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily30.5\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%lemons,limes} +%\csvpiesegment{30.5} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily24.5\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Peaches} +%\csvpiesegment{24.5} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily10\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Cherries} +%\csvpiesegment{10} +%\end{tikzpicture} +% & +%\csvpiesetkeys{start=45,cutaway={1-2}}% +%\edef\csvstartang{\thecsvstartangle}\relax +%\setcounter{csvrownumber}{0}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{20}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{15}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{30.5}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{24.5}\relax +%\stepcounter{csvrownumber}\relax +%\csvsetsegmentparams{\thecsvrownumber}{10}\relax +%\setcounter{csvstartangle}{\csvstartang}\relax +%\ifthenelse{\equal{\csvpiecutaways}{}}{}{\csvcomputeoffsets}\relax +%\begin{tikzpicture} +%\setcounter{csvrownumber}{0}\relax +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily20\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Apples} +%\csvpiesegment{20} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily15\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Pears} +%\csvpiesegment{15} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily30.5\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%lemons,limes} +%\csvpiesegment{30.5} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily24.5\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Peaches} +%\csvpiesegment{24.5} +%\stepcounter{csvrownumber}\relax +%\renewcommand*{\csvpieinnerlabel}{\sffamily10\%} +%\renewcommand*{\csvpieouterlabel}{\color{\csvpiesegcolname{\value{csvrownumber}}}\sffamily +%Cherries} +%\csvpiesegment{10} +%\end{tikzpicture} +% \\ +%(a) & (b) +%\end{tabular} +%\end{center} +%\caption{Pie Chart Example (a) cutaway=\{1,2\} +%(b) cutaway=\{1-2\}} +%\label{fig:piechart} +%\end{figure} +%\end{example} +% +%\section{Sorting Data (csvsort.sty)} +% +%The \stynamefmt{csvsort} package (which forms part of the +%\stynamefmt{csvtools} bundle) provides analogous commands to +%those provided by \stynamefmt{csvtools}, but the data is first +%sorted. The \stynamefmt{csvsort} package needs to be loaded +%separately in order to access the necessary commands. The package +%options should be a list of key=value pairs, where the available +%keys are: +%\begin{description} +%\item[verbose] Verbose mode. This is a boolean key. If set, the +%comparisons performed by the insertion sort code are printed to +%the screen. (Default: \texttt{verbose=true}.) +% +%\item[sort] This key specifies how to sort the data. It may take +%one of the following values: +%\begin{itemize} +%\item \texttt{alphabetical ascending} (or just \texttt{alphabetical}) +%\item \texttt{alphabetical descending} +%\item \texttt{numerical ascending} (or just \texttt{numerical}) +%\item \texttt{numerical descending} +%\end{itemize} +%(Default: \texttt{sort=alphabetical ascending}) +% +%\item[variable] The sort variable. (Default: \verb|sort=\field{1}|) +% +%\item[sfirstdataline] The line on which the data starts in a data +%file without a header row. (Default: \texttt{sfirstdataline=1}.) +% +%\item[firstdataline] The line on which the data starts in a data +%file with a header row. (Default: \texttt{firstdataline=2}.) +%\end{description} +% +%Note that the \stynamefmt{csvsort} package requires +%the \stynamefmt{xfor} package and \'Eamonn McManus' +%\texttt{compare.tex} file. The \stynamefmt{csvsort} package uses +%an insertion sort method to sort the data, so large amounts of data +%may slow processing time. The following commands are provided +%by \stynamefmt{csvsort}: +% +%\DescribeMacro{\sortapplyCSVfile}\noindent +% \cmdname{sortapplyCSVfile}\oarg{options}\marg{filename}\marg{text}\par +% \cmdname{sortapplyCSVfile*}\oarg{options}\marg{filename}\marg{text}\\[10pt] +%These commands are analogous to \cmdname{applyCSVfile} and +%\cmdname{applyCSVfile*}, except that the data is first sorted. +%The optional argument is a key=value list. The keys are the same +%as those used in the package options, described above. These options +%only apply to the given instance of the command, whereas the +%package options apply to all \stynamefmt{csvsort} commands, unless +%overridden in \meta{options}. Example, suppose you have a file +%called \texttt{unsorted.csv} which looks like: +%\begin{verbatim} +%First Name,Surname,Age +%Zephram,Lang,60 +%Fred,Lang,10 +%Barney,Langley,25 +%Jane,Brown,5 +%Adam,Smith,24 +%Bert,Jones,18 +%\end{verbatim} +%Then +%\begin{verbatim} +%\sortapplyCSVfile[sort=alphabetical,variable=\insertSurname]{unsorted.csv}{% +%\insertSurname, \insertbyname{First Name}. Age: \insertAge\par} +%\end{verbatim} +%will produce the following output:\par +%Brown, Jane. Age:5\par +%Jones, Bart. Age:18\par +%Lang, Zephram. Age:60\par +%Lang, Fred. Age:10\par +%Langley, Barney. Age:25\par +%Smith, Adam. Age: 24\par +%Note that the data has only been sorted according to the surname. +%To sort first by surname, then by first name, you can +%do something like: +%\begin{verbatim} +%\sortapplyCSVfile[sort=alphabetical, +%variable={\insertSurname,\insertbyname{First Name}}]{unsorted.csv}{% +%\insertSurname, \insertbyname{First Name}. Age: \insertAge\par} +%\end{verbatim} +%As with \cmdname{applyCSVfile}, you must use \cmdname{field} if +%you use the starred version: +%\begin{verbatim} +%\sortapplyCSVfile*[sort=alphabetical, +%variable={\field{2},\field{1}}]{unsorted.csv}{% +%\field{2}, \field{1}. Age: \field{3}\par} +%\end{verbatim} +% +%The commands:\\[10pt]\DescribeMacro{\sortCSVtotabular} +%\cmdname{sortCSVtotabular}\oarg{options}\marg{filename}\marg{col-spec}\marg{first row}\marg{all but last row}\marg{last row}\\ +%\DescribeMacro{\sortCSVtolongtable} +%\cmdname{sortCSVtolongtable}\oarg{options}\marg{filename}\marg{col-spec}\marg{first row}\marg{all but last row}\marg{last row}\\ +%Are analogous to \cmdname{CSVtotabular} and \cmdname{CSVtolongtable}, +%where, again, \meta{options} is a list of key=value pairs, the same +%as \cmdname{sortapplyCSVfile}. Using the same example data as above, +%the following command will sort the data according to age (in +%numerical order) and place in a tabular environment: +%\begin{verbatim} +%\sortCSVtotabular[sort=numerical,variable=\insertAge]{unsorted.csv}{llr}{% +%\bfseries Surname & \bfseries First Name & \bfseries Age\\}{% +%\insertSurname & \insertbyname{First Name} & \insertAge\\}{% +%\insertSurname & \insertbyname{First Name} & \insertAge} +%\end{verbatim} +% +%Note that the counter \texttt{csvlinenum} has no meaning in the +%commands provided by the \stynamefmt{csvsort} package. The +%\texttt{csvrownumber} counter corresponds to the sorted data row. +% +%\section{The csvtools.pl Perl Script} +% +% Suppose you have several large CSV files, and you have included +%the information into your document using \cmdname{applyCSVfile}, +%\cmdname{CSVtolongtable}, \cmdname{CSVtotabular} or +%\cmdname{csvpiechart}, which has +%made life so much easier for you, but you are now required by a +%journal to submit your source code in a single \texttt{.tex} file. +% They don't want all your CSV files, so what do you do? If you +%have Perl installed on your system you can use the +%\texttt{csvtools.pl} Perl script. This has the following syntax:\\[5pt] +% \texttt{csvtools.pl} \meta{in-file} \meta{out-file}\\[5pt] +% where \meta{in-file} is the name of your file that contains the +%\cmdname{applyCSVfile}, \cmdname{CSVtotabular} etc +% commands, and \meta{out-file} is a new file which will be created by \texttt{csvtools.pl}. This new +% file will be the same as \meta{in-file} except that all +%occurances of \cmdname{applyCSVfile}, \cmdname{CSVtolongtable}, +%\cmdname{CSVtotabular} and \cmdname{csvpiechart} will be replaced +%by the relevant data extracted from the named CSV files. +% +%\begin{example}{csvtools.pl --- Aligning Data}{ex:perl} +% Suppose the file \texttt{mydoc.tex} contains the code given in +%Example~\ref{ex:tab1}, with the associated CSV file +%\texttt{sample.csv} also given in that example. Then if you do: +%\begin{verbatim} +%csvtools.pl mydoc.tex mydocnew.tex +%\end{verbatim} +%the file \texttt{mydocnew.tex} will be created which will be +%identical to \texttt{mydoc.tex} except the lines +% containing the code \verb'\CSVtotabular{sample.csv}{lccc}{'\ldots\verb/}{/\dots\verb!}{!\ldots\verb+}+ will be replaced +%with the lines: +%\begin{verbatim} +% % \CSVtotabular{sample.csv}... converted using csvtools.pl +% %>> START INSERT +% \begin{tabular}{lccc} +% \bfseries Name & +% \bfseries Assignment 1 & +% \bfseries Assignment 2 & +% \bfseries Total\\ +% A. Smith&80&70&150\\ +% B. Jones&60&80&140\\ +% J. Doe&85&75&160\\ +% &75&75&150 +% \end{tabular}%<< END INSERT +%\end{verbatim} +%\end{example} +% +%Similarly, \texttt{csvtools.pl} will substitute all occurrances +%of \cmdname{CSVtolongtable}, \cmdname{applyCSVfile} +%and \cmdname{csvpiechart}. +% +%\subsection{Notes} +%\begin{enumerate} +%\item If perl is located in a directory other than \texttt{/usr/bin/} +%you will need to edit the first line of \texttt{csvtools.pl} as +%appropriate. You can find the location using the command: +%\begin{verbatim} +%which perl +%\end{verbatim} +% +%\item If you can't directly execute a Perl script, +% you can do:\\[5pt] +% \texttt{perl csvtools.pl} \meta{in-file} \meta{out-file} +% +%\item You must first \LaTeX\ your document before using +%\texttt{csvtools.pl} as it checks the log file for any counters +%that have been defined. +% +%\item \texttt{csvtools.pl} only knows about a very limited set +%of \LaTeX\ commands. It should be able to understand: +%\begin{verbatim} +%\CSVtotabular{\csvGetEntry{experiment}{File}}{ll}{... +%\end{verbatim} +%(see Example~\ref{ex:index}), but it won't be able to understand, +%say, +%\begin{verbatim} +%\newcommand{\filename}{\csvGetEntry{experiment}{File}} +%\CSVtotabular{\filename}{ll}{... +%\end{verbatim} +%It can pick up on \cmdname{addtocounter}, \cmdname{stepcounter}, +%\cmdname{refstepcounter} and \cmdname{setcounter} but only if +%they are used explicitly in the named \texttt{.tex} file. (It +%ignores any files that have been included using +%\cmdname{input}, \cmdname{include} etc.) +% +%\item This Perl script has only been tested under Linux, but it +%ought to work under other systems. +%\end{enumerate} +% +% \section{Bugs/Drawbacks/``Features''}\label{sec:drawbacks} +% \begin{enumerate} +% \item\label{itm:insert} +% The package doesn't check to see whether +%\cmdname{insert}\meta{identifier} exists, otherwise you would not +%be able to use multiple CSV files with the same headers, as in +%Example~\ref{ex:index}. Therefore it is recommended that +% you check to make sure that the command does not already exist. +% For example, the \TeX\ commands \cmdname{insert} and +%\cmdname{insertpenalties} already exist, so a blank header or a +%header named \texttt{penalties} would cause problems. (These two +%will now cause an error as from version 1.1, but it's something +%bear in mind.) +% +% \item Note also that \cmdname{insertbyname} doesn't check +% if you've given a valid label, so if no text appears, +% check you've spelt it correctly, checking punctuation, spaces and case. +% +% \item\label{itm:psbyname} +% Note that in Example~\ref{ex:ps}, replacing line~3 with: +%\begin{verbatim} +%\centerline{\includegraphics{\insertbyname{File}}} +%\end{verbatim} +% will cause an error, as \verb/\insertbyname{File}/ doesn't get +% fully expanded by the time it gets passed to +% \cmdname{includegraphics}, and will prevent +%\cmdname{includegraphics} from +% finding the file. It is possible to get around this using +% \TeX's \cmdname{edef} command: +%\begin{verbatim} +%\edef\psfilename{\insertbyname{File}} +%\centerline{\includegraphics{\psfilename}} +%\end{verbatim} +% +% \item\label{itm:noalign} You can't have commands like +%\cmdname{hline}, \cmdname{cline} and \cmdname{multicolumn} in the +%first column of the \meta{middle} or \meta{last} code of +%\cmdname{CSVtotabular} or \cmdname{CSVtolongtable}. If you do, +%it will generate a \verb/misplaced \noalign/ error, instead you +%need to put it at the end of the \meta{first} or \meta{middle} +%code. (See Example~\ref{ex:tab3}.) +% +% \item You can't have nested \cmdname{applyCSVfile}, +%\cmdname{CSVtolongtable} and \cmdname{CSVtotabular} +% commands. Nor can you have \cmdname{csvpiechart} within +%one of these commands (See Example~\ref{ex:index}) +% +% \item If the CSV file has a header row, it must be on the first +%line. +% +% \item It is possible for \TeX\ to run out of memory if you use +% \cmdname{csvSaveEntry} on a large file. +% +% \item\label{itm:csvrownumber} In version 1.0, there was an +%inconsistency with \texttt{csvrownumber} within +%\cmdname{applyCSVfile} and \cmdname{CSVtotabular}. In the +%former it excluded the header row, whereas the latter +%included it. This has been changed in version 1.1 so that within +%\cmdname{applyCSVfile}, \cmdname{CSVtotabular} and +%\cmdname{CSVtolongtable}, \texttt{csvrownumber} refers to the +%data row (excluding header row.) I hope this doesn't cause +%problems, but it makes more sense that they should be +%consistent. So if you have no blank lines in your CSV file, +%\texttt{csvrownumber} should always be 1 more than +%\texttt{csvlinenumber}. +% +%\end{enumerate} +% +% \section{Contact Details} +% +% Dr Nicola Talbot\\ +% School of Computing Sciences\\ +% University of East Anglia\\ +% Norwich. NR4 7TJ. England. +% \\[10pt] +% \url{http://theoval.cmp.uea.ac.uk/~nlct/} +% +%\StopEventually{\PrintIndex\addcontentsline{toc}{section}{Index}} +% +% +% +%\section{The Code} +%\iffalse +% \begin{macrocode} +%<*csvtools.sty> +% \end{macrocode} +%\fi +%\subsection{csvtools.sty} +% Declare package +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{csvtools}[2007/07/03 v1.24 (NLCT)] +% \end{macrocode} +% Required packages +% \begin{macrocode} +\RequirePackage{ifthen} +\RequirePackage{longtable} +% \end{macrocode} +% Define command to set the separator character. +% \begin{macrocode} +\newcommand*{\@csvseparator}{,} +\newcommand*{\setcsvseparator}[1]{% +\renewcommand*{\@csvseparator}{#1}% +\construct@lopoff{#1}% +\@construct@qlopoff{#1}% +\@construct@lopoff{#1}} +% \end{macrocode} +% Define command to remove first element from list. CSV files +% usually use double quote characters to enclose entries containing +% a comma. The first argument is the control sequence containing +% the list, the second argument is the control sequence to +% contain the first item in the list. +% \begin{macrocode} +\newcommand*{\extractentry}[2]{% +\expandafter\csvlopoff#1\to{#1}{#2}} +% \end{macrocode} +% The definitions are constructed on the fly to allow for +% different separators. The argument is the separator. +%\changes{1.23}{2007 May 23}{'csvlopoff changed to a long command} +% \begin{macrocode} +\edef\construct@lopoff#1{% +\noexpand\long\noexpand\def\noexpand\csvlopoff#1##1##2\noexpand\to##3##4{% +\noexpand\ifx"##1\noexpand\relax +\noexpand\@csv@qlopoff#1##1##2\noexpand\to##3##4\relax +\noexpand\else +\noexpand\@csv@lopoff#1##1##2\noexpand\to##3##4\relax +\noexpand\fi +}} +% \end{macrocode} +% Command to contruct control sequence to be used when the +% entry is surrounded by double quotes. +%\changes{1.23}{2007 May 23}{'@csv@qlopoff changed to a long command} +% \begin{macrocode} +\edef\@construct@qlopoff#1{% +\noexpand\long\noexpand\def\noexpand\@csv@qlopoff#1"##1"#1##2\noexpand\to##3##4{% +\noexpand\def##4{##1}\noexpand\def##3{#1##2}}} +% \end{macrocode} +% Command to construct control sequence to be used when the +% entry isn't surrounded by double quotes. +%\changes{1.23}{2007 May 23}{'@csv@lopoff changed to a long command} +% \begin{macrocode} +\edef\@construct@lopoff#1{% +\noexpand\long\noexpand\def\noexpand\@csv@lopoff#1##1#1##2\noexpand\to##3##4{% +\noexpand\def##4{##1}\noexpand\def##3{#1##2}}} +% \end{macrocode} +% Set the default separator: +% \begin{macrocode} +\setcsvseparator{,} +% \end{macrocode} +% Define some variables +% \begin{macrocode} +\newread\csvfile +\newif\ifmore +\newcount\c@field +\newcount\c@maxfields +\newcounter{csvlinenum} +\newcount\maxlines +\newcount\csvlastbutone +\newcounter{csvrownumber} +\toksdef\csv@tb=2 +% \end{macrocode} +% Define commands to access element in current row. +% Access element by column number: +% \begin{macrocode} +\newcommand{\field}[1]{\csname @field\romannumeral#1\endcsname} +% \end{macrocode} +% Set field (header) label, the first argument is the index, second argument is the header for that column.) +% \begin{macrocode} +\newcommand{\setcsvfieldlabel}[2]{% +\expandafter\def\csname @fieldlabel\romannumeral#1\endcsname{#2}} +% \end{macrocode} +% Access element by header: +% \begin{macrocode} +\newcommand{\insertbyname}[1]{\csname insert#1\endcsname} +% \end{macrocode} +% Define command to trim trailing space (caused by EOL) in argument. +% Argument should be a command name containing the current line. +% \begin{macrocode} +\newcommand{\trim}[1]{\def\@trmstr{}% +\def\csv@trmarg{#1}% +\if\par\csv@trmarg +\else +\expandafter\@trim#1\end +\let#1\@trmstr +\fi +} +\long\def\@trim#1 \end{\def\@trmstr{#1}} +% \end{macrocode} +% Define "\applyCSVfile" +% \begin{macrocode} +\newcommand{\applyCSVfile}{\@ifstar\@sapplyCSVfile\@applyCSVfile} +% \end{macrocode} +% Starred version of "\applyCSVfile": +% \begin{macrocode} +\newcommand{\@sapplyCSVfile}[3][1]{% +\IfFileExists{#2}{% +\openin\csvfile=#2 +\ifeof\csvfile\morefalse\else\moretrue\fi +\ifmore +{\c@csvlinenum=1\relax +\global\c@csvrownumber=0\relax +\loop +\read\csvfile to\csvline +\advance\c@csvlinenum by 1\relax +\ifnum\c@csvlinenum>#1\relax +\trim{\csvline}% +\csv@tb=\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field = 0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator} \and +\not\equal{\@csvlin@}{\@csvseparator\@csvseparator} \and +\not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\csv@tb=\expandafter{\param}% +\advance\c@field by 1\relax +\expandafter\xdef\csname @field\romannumeral\c@field\endcsname{% +\the\csv@tb}% +}% +\ifthenelse{\not\equal{\csvline}{\par} \and +\not\equal{\csvline}{}}{% +\refstepcounter{csvrownumber}\relax +#3}{}% +\fi +\ifeof\csvfile\morefalse\else\moretrue\fi +\ifmore +\repeat}% +\closein\csvfile +\fi +}{\PackageError{csvtools}{Can't find file '#2'}{}}% +} +% \end{macrocode} +% Unstarred version: +% \begin{macrocode} +\newcommand{\@applyCSVfile}[3][2]{% +\ifnum#1<2\relax +\PackageError{csvtools}{Header line required}{The optional +argument to `\string\applyCSVfile' needs to be > 1. The header +line should be on line 1}% +\else +\IfFileExists{#2}{% +\openin\csvfile=#2 +\ifeof\csvfile\morefalse\else\moretrue\fi +\ifmore +\global\c@csvlinenum=1\relax +\global\c@csvrownumber=0\relax +\global\c@maxfields=0\relax +{\loop +\read\csvfile to\csvline +\trim{\csvline}% +\ifnum\c@csvlinenum=1\relax +\ifthenelse{\not\equal{\csvline}{\par} \and +\not\equal{\csvline}{}}{% +\csv@tb=\expandafter{\csvline}\relax +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field=0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\advance\c@field by 1\relax +\csv@tb=\expandafter{\param}\relax +\expandafter +\xdef\csname @fieldlabel\romannumeral\c@field\endcsname{\the\csv@tb}% +}% +\c@maxfields=\c@field +}{% +\PackageError{csvtools}{Header line missing in file #2}{Header +line required on line 1}}% +\fi +\c@field=0\relax +\whiledo{\c@field < \c@maxfields}{% +\advance\c@field by 1\relax +\expandafter\let\csname @field\romannumeral\c@field\endcsname\relax% +\edef\@fieldlabel{% +\csname @fieldlabel\romannumeral\c@field\endcsname}% +\ifthenelse{\equal{\@fieldlabel}{} +\TE@or \equal{\@fieldlabel}{penalties} +\TE@or \equal{\@fieldlabel}{byname}}{\PackageError{csvtools}{% +\string\insert\@fieldlabel \space already defined}{% +You can't have the label '\@fieldlabel' in your header row.}}{}% +\expandafter\let\csname insert\@fieldlabel\endcsname\relax% +}% +\advance\c@csvlinenum by 1\relax +\ifnum\c@csvlinenum>#1\relax +\csv@tb=\expandafter{\csvline}\relax +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field=0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\csv@tb=\expandafter{\param}\relax +\advance\c@field by 1\relax +\expandafter +\xdef\csname @field\romannumeral\c@field\endcsname{\the\csv@tb}% +\edef\@fieldlabel{% +\csname @fieldlabel\romannumeral\c@field\endcsname}% +\ifthenelse{\equal{\@fieldlabel}{} +\TE@or \equal{\@fieldlabel}{penalties} +\TE@or \equal{\@fieldlabel}{byname}}{\PackageError{csvtools}{% +\string\insert\@fieldlabel \space already defined}{% +You can't have the label '\@fieldlabel' in your header row.}}{}% +\expandafter\xdef\csname insert\@fieldlabel\endcsname{\the\csv@tb}% +}% +\ifthenelse{\not\equal{\csvline}{\par} +\and \not\equal{\csvline}{}}{% +\global\advance\c@csvrownumber by 1\relax +#3}{}% +\fi +\ifeof\csvfile\morefalse\else\moretrue\fi +\ifmore +\repeat}% +\closein\csvfile +\fi +}{\PackageError{csvtools}{Can't find file '#2'}{}}% +\fi +} +% \end{macrocode} +% Define "\CSVtotabular". Inserts contents of csv file into a tabular +% environment. +% \begin{macrocode} +\newcommand{\CSVtotabular}[5]{% +\openin\csvfile=#1 +\c@csvlinenum=0\relax +\loop +\advance\c@csvlinenum by 1\relax +\read\csvfile to\csvline +\expandafter +\xdef\csname @csvline\romannumeral\c@csvlinenum\endcsname{\csvline}% +\ifthenelse{\not\equal{\csvline}{\par}}{\trim{\csvline}}{}% +\ifnum\c@csvlinenum=1\relax +\csv@tb=\expandafter{\csvline} +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field = 0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator}% +\and \not\equal{\@csvlin@}{\@csvseparator\@csvseparator}% +\and \not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\csv@tb=\expandafter{\param}% +\advance\c@field by 1\relax +\expandafter\xdef\csname insert\the\csv@tb\endcsname{% +\noexpand\field{\the\c@field}}% +}% +\fi +\csv@tb=\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field = 0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\csv@tb=\expandafter{\param} +\advance\c@field by 1\relax +\expandafter +\xdef\csname @l\romannumeral\c@csvlinenum @field\romannumeral\c@field\endcsname{\the\csv@tb}% +}% +\ifeof\csvfile\morefalse\else\moretrue\fi +\ifmore +\repeat +\closein\csvfile +{% +\def\field##1{% +\csname @l\romannumeral\c@csvlinenum @field\romannumeral##1\endcsname}% +\def\@r@wh{\begin{tabular}{#2}#3}% +\def\@r@w{#4}% +\def\@r@wl{#5\end{tabular}}% +\maxlines=\c@csvlinenum +\advance\maxlines by -1\relax +\csvlastbutone=\maxlines +\advance\csvlastbutone by -1\relax +\c@csvlinenum=1\relax +\setcounter{csvrownumber}{0}\relax +\whiledo{\not{\c@csvlinenum>\maxlines}}{% +\ifthenelse{\expandafter\equal{% +\csname @csvline\romannumeral\c@csvlinenum\endcsname}{\par}}% +{\relax}{% +\ifnum\c@csvlinenum=1\relax +\@r@wh +\else +\refstepcounter{csvrownumber}% +\ifnum\c@csvlinenum=\maxlines\@r@wl\else\@r@w\fi +\fi}% +\global\advance\c@csvlinenum by 1\relax +}\relax +}} +% \end{macrocode} +% Define "\CSVtolongtable". Similar to the above, but uses a +% longtable environment. +% \begin{macrocode} +\newcommand{\CSVtolongtable}[5]{% +\openin\csvfile=#1 +\c@csvlinenum=0\relax +\loop +\advance\c@csvlinenum by 1\relax +\read\csvfile to\csvline +\expandafter +\xdef\csname @csvline\romannumeral\c@csvlinenum\endcsname{\csvline}% +\ifthenelse{\not\equal{\csvline}{\par}}{\trim{\csvline}}{}% +\ifnum\c@csvlinenum=1\relax +\csv@tb=\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field = 0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\csv@tb=\expandafter{\param}% +\advance\c@field by 1\relax +\expandafter +\xdef\csname insert\the\csv@tb\endcsname{% +\noexpand\field{\the\c@field}}% +}% +\fi +\csv@tb=\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\csv@tb\@csvseparator}% +\c@field = 0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator\par\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator\@csvseparator} +\and \not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\csv@tb=\expandafter{\param}% +\advance\c@field by 1\relax +\expandafter +\xdef\csname @l\romannumeral\c@csvlinenum @field\romannumeral\c@field\endcsname{\the\csv@tb}% +}% +\ifeof\csvfile\morefalse\else\moretrue\fi +\ifmore +\repeat +\closein\csvfile +{\def\field##1{% +\csname @l\romannumeral\c@csvlinenum @field\romannumeral##1\endcsname}% +\def\@r@wh{\begin{longtable}{#2}#3}% +\def\@r@w{#4}% +\def\@r@wl{#5\end{longtable}}% +\maxlines=\c@csvlinenum +\advance\maxlines by -1\relax +\csvlastbutone=\maxlines +\advance\csvlastbutone by -1\relax +\c@csvlinenum=1\relax +\setcounter{csvrownumber}{0}\relax +\whiledo{\not{\c@csvlinenum>\maxlines}}{% +\ifthenelse{\expandafter\equal{% +\csname @csvline\romannumeral\c@csvlinenum\endcsname}{\par}}% +{\relax}{% +\ifnum\c@csvlinenum=1\relax +\@r@wh +\else +\refstepcounter{csvrownumber}% +\ifnum\c@csvlinenum=\maxlines\@r@wl\else\@r@w\fi +\fi}% +\global\advance\c@csvlinenum by 1\relax +}\relax +}} +% \end{macrocode} +% Define a command to determine if on the penultimate row +% \begin{macrocode} +\newcommand{\ifnextrowlast}[2]{% +\ifnum\c@csvlinenum=\csvlastbutone#1\else#2\fi} +% \end{macrocode} +% Define means to store entry for later use +% \begin{macrocode} +\newcommand{\csvSaveEntry}[2][csvrownumber]{% +\@ifnextchar[{\@csvSaveEntry{#1}{#2}}{% +\@csvSaveEntry{#1}{#2}[\insertbyname{#2}]}% +} +% \end{macrocode} +% \begin{macrocode} +\def\@csvSaveEntry#1#2[#3]{% +\edef\@csv@tmp{\insertbyname{#2}}% +\if\relax\@csv@tmp\relax +\edef\@entry{#3}% +\else +\edef\@entry{\insertbyname{#2}}% +\fi +\expandafter +\xdef\csname #2\romannumeral\value{#1}\endcsname{\@entry}} +% \end{macrocode} +% Define means to access stored entry. +% \begin{macrocode} +\newcommand{\csvGetEntry}[2]{% +\csname #2\romannumeral\value{#1}\endcsname} +% \end{macrocode} +%\iffalse +% \begin{macrocode} +%</csvtools.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*csvpie.sty> +% \end{macrocode} +%\fi +%\subsection{csvpie.sty} +% Declare package. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{csvpie}[2006/09/01 v1.0] +% \end{macrocode} +% Declare options. +% \begin{macrocode} +\newif\ifcolorpiechart +\colorpiecharttrue +\DeclareOption{color}{\colorpiecharttrue} +\DeclareOption{monochrome}{\colorpiechartfalse} +% \end{macrocode} +% Process options +% \begin{macrocode} +\ProcessOptions +% \end{macrocode} +% Specify required packages +% \begin{macrocode} +\RequirePackage{csvtools} +\RequirePackage{tikz} +\RequirePackage{calc} +\RequirePackage{keyval} +% \end{macrocode} +% Define some variables +% \begin{macrocode} +\newlength\csvradius +\newlength\csvinner +\newlength\csvouter +\newlength\csvcutawayoffset +\newcounter{csvstartangle} +\newcounter{csvendangle} +\newcounter{csvangle} +\newcounter{csvpietotal} +% \end{macrocode} +% Set default values. +% \begin{macrocode} +\newcommand*{\csvpiedefaults}{radius=2cm,inner=0.25,outer=1.25,% +cutaway={},total=100,start=0,offset=0.1} +% \end{macrocode} +% Define command to specify inner and outer labels. +% The default puts the entry in column 1 (usually the label) +% in the outer area, and the entry in column 2 (usually the +% value) in the inner area. These can be redefined by the user +% to use other variables, or change the format etc. +% \begin{macrocode} +\newcommand{\csvpieouterlabel}{\field{1}} +\newcommand{\csvpieinnerlabel}{\field{2}\%} +% \end{macrocode} +% Define command to store list of row numbers corresponding to +% cut away segments. (Segments that have been offset from the +% pie chart.) By default, none of the segments should be cut away. +% \begin{macrocode} +\newcommand*{\csvpiecutaways}{} +% \end{macrocode} +% Define a command to assign colour name "#2" to segment number "#1" +% \begin{macrocode} +\newcommand*{\csvpiesegmentcol}[2]{% +\expandafter\def\csname csvpie@segcol\romannumeral#1\endcsname{#2}} +% \end{macrocode} +% Define command to get colour name assigned to segment number "#1" +% \begin{macrocode} +\newcommand*{\csvpiesegcolname}[1]{% +\csname csvpie@segcol\romannumeral#1\endcsname} +% \end{macrocode} +% Set default colours. These can be changed by the user. More colours +% can be added in a similar manner if there are more than 8 segments. +% \begin{macrocode} +\ifcolorpiechart +\csvpiesegmentcol{1}{red} +\csvpiesegmentcol{2}{green} +\csvpiesegmentcol{3}{blue} +\csvpiesegmentcol{4}{yellow} +\csvpiesegmentcol{5}{magenta} +\csvpiesegmentcol{6}{cyan} +\csvpiesegmentcol{7}{orange} +\csvpiesegmentcol{8}{white} +\else +\csvpiesegmentcol{1}{black!15} +\csvpiesegmentcol{2}{black!25} +\csvpiesegmentcol{3}{black!35} +\csvpiesegmentcol{4}{black!45} +\csvpiesegmentcol{5}{black!55} +\csvpiesegmentcol{6}{black!65} +\csvpiesegmentcol{7}{black!75} +\csvpiesegmentcol{8}{black!85} +\fi +% \end{macrocode} +% Define keys for "\csvpiechart" optional argument +% \begin{macrocode} +\define@key{csvpie}{start}{\setcounter{csvstartangle}{#1}} +\define@key{csvpie}{total}{\setcounter{csvpietotal}{#1}} +\define@key{csvpie}{radius}{\setlength{\csvradius}{#1}} +\define@key{csvpie}{inner}{\setlength{\csvinner}{#1\csvradius}} +\define@key{csvpie}{outer}{\setlength{\csvouter}{#1\csvradius}} +\define@key{csvpie}{offset}{\setlength{\csvcutawayoffset}{#1\csvradius}} +\define@key{csvpie}{cutaway}{\renewcommand*{\csvpiecutaways}{#1}} +\providecommand*{\csv@startrow}{1} +\define@key{csvpie}{firstrow}{\renewcommand*{\csv@startrow}{#1}} +% \end{macrocode} +% Define "\csvpiechart". The starred version uses "\applyCSVfile*", +% the unstarred version uses "\applyCSVfile". +% \begin{macrocode} +\newcommand{\csvpiechart}{% +\@ifstar{\def\@@pieapplyCSVfile{\applyCSVfile*}% +\def\csv@startrow{1}% +\@csvpiechart}{% +\def\@@pieapplyCSVfile{\applyCSVfile}% +\def\csv@startrow{2}% +\@csvpiechart}% +} +% \end{macrocode} +% Set the keys for pie chart: +% \begin{macrocode} +\newcommand*{\csvpiesetkeys}[1]{% +\edef\csv@piesk{\noexpand\setkeys{csvpie}{\csvpiedefaults,#1}}% +\csv@piesk} +% \end{macrocode} +% The main body of "\csvpiechart". +% \begin{macrocode} +\newcommand{\@csvpiechart}[3][]{% +{\csvpiesetkeys{#1}% +\edef\csv@startang{\number\c@csvstartangle}% +\csv@computeangles{#2}{#3}% +\setcounter{csvstartangle}{\csv@startang}% +\begin{tikzpicture}% +\@@pieapplyCSVfile[\csv@startrow]{#3}{% +\csvpiesegment{#2}}% +\end{tikzpicture}% +}} +% \end{macrocode} +% Do individual segment in pie chart. +% \begin{macrocode} +\newcommand*{\csvpiesegment}[1]{% +\setcounter{csvstartangle}{% +\csname csv@sang@\romannumeral\c@csvrownumber\endcsname}% +\setcounter{csvangle}{% +\csname csv@angle@\romannumeral\c@csvrownumber\endcsname}% +\setcounter{csvendangle}{\value{csvangle} + \value{csvstartangle}}% +\setcounter{csvangle}{% +\csname csv@cut@angle\romannumeral\c@csvrownumber\endcsname}% +\ifthenelse{\value{csvangle}>180}{\addtocounter{csvangle}{-360}}{}% +\edef\@csv@shift{(\number\c@csvangle:% +\csname csv@cut@len\romannumeral\c@csvrownumber\endcsname)}% +\setcounter{csvangle}{% +\csname csv@angle@\romannumeral\c@csvrownumber\endcsname/2 ++\value{csvstartangle}}% +\begin{scope}[shift={\@csv@shift}]% +\fill[color=\csvpiesegcolname\c@csvrownumber] (0,0) -- +(\thecsvstartangle:\csvradius) +arc (\thecsvstartangle:\thecsvendangle:\csvradius) -- cycle; +% if 90 < csvangle < 270, the text will look upside-down, so +% adjust accordingly. Reusing csvstartangle, to save defining +% a new counter, as it's no longer required +\ifthenelse{\(\value{csvangle}>90 \and \value{csvangle}<270\) +\TE@or \value{csvangle}<-90}{% +\setcounter{csvstartangle}{\value{csvangle}-180}% +\draw (\thecsvangle:\csvinner) +node[left,rotate=\thecsvstartangle]{\csvpieinnerlabel}; +\draw (\thecsvangle:\csvouter) +node[left,rotate=\thecsvstartangle]{\csvpieouterlabel}; +}{% +\draw (\thecsvangle:\csvinner) +node[right,rotate=\thecsvangle]{\csvpieinnerlabel}; +\draw (\thecsvangle:\csvouter) +node[right,rotate=\thecsvangle]{\csvpieouterlabel}; +}% +\end{scope}% +} +% \end{macrocode} +% Compute the angles for each segment. First argument is +% variable, second argument is the name +% of the CSV file. +% \begin{macrocode} +\newcommand*{\csv@computeangles}[2]{% +\@@pieapplyCSVfile[\csv@startrow]{#2}{% +\csvsetsegmentparams{\c@csvrownumber}{#1}% +}% +\ifthenelse{\equal{\csvpiecutaways}{}}{}{\csvcomputeoffsets}} +% \end{macrocode} +% Compute offset angles for cutaway segments. +% "\csv@row" should either be a single number (e.g.\ "2") +% or a number range (e.g.\ "1-2") +% \begin{macrocode} +\newcommand*{\csvcomputeoffsets}{% +\@for\csv@row:=\csvpiecutaways\do{% +\expandafter\@csv@set@off\csv@row-\relax +}} +% \end{macrocode} +% Set the offset angle. +% \begin{macrocode} +\def\@csv@set@off#1-#2\relax{% +\ifthenelse{\equal{#2}{}}{% +\@@csv@set@off{#1}}{% +\@@csv@set@offr#1-#2\relax}% +} +% \end{macrocode} +% Set offset for individual segment: +% \begin{macrocode} +\newcommand*{\@@csv@set@off}[1]{% +\setcounter{csvangle}{% +\csname csv@angle@\romannumeral#1\endcsname/2 ++ \csname csv@sang@\romannumeral#1\endcsname}% +\expandafter\xdef\csname csv@cut@angle\romannumeral#1\endcsname{% +\number\c@csvangle}% +\expandafter +\gdef\csname csv@cut@len\romannumeral\csv@row\endcsname{% +\csvcutawayoffset}% +} +% \end{macrocode} +% Set offset for range of segments: +% \begin{macrocode} +\newcount\@csv@seg +\def\@@csv@set@offr#1-#2-\relax{% +\ifnum#1>#2\relax +\PackageError{csvpie}{Segment ranges must go in ascending +order}{Try #2-#1 instead of #1-#2}% +\else +\setcounter{csvangle}{0}% +\@csv@seg=#1\relax +\whiledo{\not\(\@csv@seg > #2\)}{% +\addtocounter{csvangle}{% +\csname csv@angle@\romannumeral\@csv@seg\endcsname}% +\advance\@csv@seg by 1}% +\setcounter{csvangle}{\value{csvangle}/2 ++ \csname csv@sang@\romannumeral#1\endcsname}% +\@csv@seg=#1\relax +\whiledo{\not\(\@csv@seg > #2\)}{% +\expandafter\xdef\csname csv@cut@angle\romannumeral\@csv@seg\endcsname{% +\number\c@csvangle}% +\expandafter +\gdef\csname csv@cut@len\romannumeral\@csv@seg\endcsname{% +\csvcutawayoffset}% +\advance\@csv@seg by 1}% +\fi +} +% \end{macrocode} +% Set the relevent variables required for "\csvpiesegment": +% The first argument is the segment number, the second argument +% is the variable. The "csvstartangle" counter is updated. +% This command should be called sequentially, and is provided +% for the convenience of \texttt{csvtools.pl}. +% \begin{macrocode} +\newcommand*{\csvsetsegmentparams}[2]{% +\ifthenelse{\value{csvstartangle}>180}{% +\addtocounter{csvstartangle}{-360}}{}% +\ifthenelse{\value{csvstartangle}<-180}{% +\addtocounter{csvstartangle}{360}}{}% +\expandafter +\xdef\csname csv@sang@\romannumeral#1\endcsname{% +\number\c@csvstartangle}% +\setcounter{csvangle}{360*\real{#2}/\value{csvpietotal}}% +\addtocounter{csvstartangle}{\value{csvangle}}% +\expandafter +\xdef\csname csv@angle@\romannumeral#1\endcsname{% +\number\c@csvangle}% +\expandafter +\gdef\csname csv@cut@angle\romannumeral#1\endcsname{0}% +\expandafter +\gdef\csname csv@cut@len\romannumeral#1\endcsname{0cm}% +} +% \end{macrocode} +%\iffalse +% \begin{macrocode} +%</csvpie.sty> +% \end{macrocode} +%\fi +%\iffalse +% \begin{macrocode} +%<*csvsort.sty> +% \end{macrocode} +%\fi +%\subsection{csvsort.sty} +% Declare package: +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{csvsort}[2007/07/03 v1.0 (NLCT)] +% \end{macrocode} +% If \cmdname{compare} hasn't been defined, use compare.tex +% \begin{macrocode} +\@ifundefined{compare}{\input{compare}}{} +% \end{macrocode} +% Define comparison commands. Each of the comparison commands must +% set the boolean \cmdname{if@csv@ishigher} +% \begin{macrocode} +\newif\if@csv@ishigher +% \end{macrocode} +% Alphabetical ascending comparison: +% \begin{macrocode} +\newcommand{\csv@alphaascendingcompare}[2]{% +\@csv@extractkey#1{\@csv@keya}% +\@csv@extractkey#2{\@csv@keyb}% +\csvsort@verbose{Comparing \@csv@keya\space and \@csv@keyb}% +\edef\@csvsrt@result{\noexpand\compare{\@csv@keya}{\@csv@keyb}}% +\ifnum\@csvsrt@result=1\relax + \@csv@ishighertrue +\else + \@csv@ishigherfalse +\fi} +% \end{macrocode} +% Alphabetical descending comparison: +% \begin{macrocode} +\newcommand{\csv@alphadescendingcompare}[2]{% +\@csv@extractkey#1{\@csv@keya}% +\@csv@extractkey#2{\@csv@keyb}% +\csvsort@verbose{Comparing \@csv@keya\space and \@csv@keyb}% +\edef\@csvsrt@result{\noexpand\compare{\@csv@keya}{\@csv@keyb}}% +\ifnum\@csvsrt@result=-1\relax + \@csv@ishighertrue +\else + \@csv@ishigherfalse +\fi} +% \end{macrocode} +% Numerical ascending comparison: +% \begin{macrocode} +\newcommand{\csv@numericascendingcompare}[2]{% +\@csv@extractkey#1{\@csv@keya}% +\@csv@extractkey#2{\@csv@keyb}% +\if\relax\@csv@keya\relax\def\@csv@keya{0}\fi +\if\relax\@csv@keyb\relax\def\@csv@keyb{0}\fi +\csvsort@verbose{Comparing \number\@csv@keya\space and \number\@csv@keyb}% +\ifnum\@csv@keya>\@csv@keyb\relax + \@csv@ishighertrue +\else + \@csv@ishigherfalse +\fi} +% \end{macrocode} +% Numerical descending comparison: +% \begin{macrocode} +\newcommand{\csv@numericdescendingcompare}[2]{% +\@csv@extractkey#1{\@csv@keya}% +\@csv@extractkey#2{\@csv@keyb}% +\if\relax\@csv@keya\relax\def\@csv@keya{0}\fi +\if\relax\@csv@keyb\relax\def\@csv@keyb{0}\fi +\csvsort@verbose{Comparing \number\@csv@keya\space and \number\@csv@keyb}% +\ifnum\@csv@keya<\@csv@keyb\relax + \@csv@ishighertrue +\else + \@csv@ishigherfalse +\fi} +% \end{macrocode} +% The sort key needs to be extracted from the data (3rd argument +% must be a control sequence): +% \begin{macrocode} +\def\@csv@extractkey#1#2#3{\def#3{#1}} +% \end{macrocode} +% Conversely, extract the data and ignore the sort key: +% \begin{macrocode} +\def\@csv@extractdata#1#2#3{\def#3{#2}} +% \end{macrocode} +% The command \cmdname{csv@compare} should be set to the +% appropriate comparison command (\cmdname{csv@alphaascendingcompare} +% by default.) +% \begin{macrocode} +\let\csv@compare\csv@alphaascendingcompare +% \end{macrocode} +% The package options are a comma-separated list of key=value +% pairs, so need the \stynamefmt{xkeyval} package. +% \begin{macrocode} +\RequirePackage{xkeyval} +% \end{macrocode} +% Package options. Verbose mode: +% \begin{macrocode} +\define@boolkey{csvsort.sty}[csvsrt]{verbose}[true]{} +% \end{macrocode} +% Default is verbose: +% \begin{macrocode} +\csvsrtverbosetrue +% \end{macrocode} +% Define command to display message if verbose option is set: +% \begin{macrocode} +\newcommand{\csvsort@verbose}[1]{% +\ifcsvsrtverbose\typeout{#1}\fi} +% \end{macrocode} +% Sort type (can be either numerical or alphabetical, ascending +% or descending): +% \begin{macrocode} +\define@choicekey{csvsort.sty}{sort}[\val\nr]{alphabetical,numerical,% +alphabetical ascending,numerical ascending,% +alphabetical descending,numerical descending,% +alphabeticalascending,alphabeticaldescending,% +numericalascending,numericaldescending}{% +\ifcase\nr + % alphabetical (ascending) + \let\csv@compare\csv@alphaascendingcompare + \or + % numerical (ascending) + \let\csv@compare\csv@numericascendingcompare + \or + % alphabetical ascending + \let\csv@compare\csv@alphaascendingcompare + \or + % numerical ascending + \let\csv@compare\csv@numericascendingcompare + \or + % alphabetical descending + \let\csv@compare\csv@alphadescendingcompare + \or + % numerical descending + \let\csv@compare\csv@numericdescendingcompare + \or + % alphabeticalascending + \let\csv@compare\csv@alphaascendingcompare + \or + % alphabetical descending + \let\csv@compare\csv@alphadescendingcompare + \or + % numericalascending + \let\csv@compare\csv@numericascendingcompare + \or + % numericaldescending + \let\csv@compare\csv@numericdescendingcompare +\fi} +% \end{macrocode} +% The variable used to sort is given by: +% \begin{macrocode} +\newcommand{\csv@sortvariable}{\field{1}} +% \end{macrocode} +% A different variable can be set using the variable package option: +% \begin{macrocode} +\define@key{csvsort.sty}{variable}{% +\renewcommand{\csv@sortvariable}{#1}} +% \end{macrocode} +% The first data line in CSV files with no headers is given by +% \begin{macrocode} +\newcounter{sfirstdataline} +% \end{macrocode} +% and defaults to line 1: +% \begin{macrocode} +\setcounter{sfirstdataline}{1} +% \end{macrocode} +% This value can be set using the "sfirstdataline" option: +% \begin{macrocode} +\define@key{csvsort.sty}{sfirstdataline}{% +\setcounter{sfirstdataline}{#1}} +% \end{macrocode} +% The first data line in CSV files with headers is given by +% \begin{macrocode} +\newcounter{firstdataline} +% \end{macrocode} +% and defaults to line 2: +% \begin{macrocode} +\setcounter{firstdataline}{2} +% \end{macrocode} +% This value can be set using the "firstdataline" option: +% \begin{macrocode} +\define@key{csvsort.sty}{firstdataline}{% +\setcounter{firstdataline}{#1}} +% \end{macrocode} +% Process package options: +% \begin{macrocode} +\ProcessOptionsX +% \end{macrocode} +% Required packages: +% \begin{macrocode} +\RequirePackage{csvtools} +\RequirePackage{xfor} +% \end{macrocode} +% Insertion sort macro. The argument is a comma-separated list +% in the form \marg{sort-key1}\marg{data1},\ldots,% +%\marg{sort-keyN}\marg{dataN}. The list is sorted according to +% \cmdname{csv@compare} +%\begin{macro}{\csv@insertionsort} +% \begin{macrocode} +\newcommand{\csv@insertionsort}[1]{% +\let\@csv@sortedlist\relax +\@for\@csv@listelement:=#1\do{% +\if\@csv@sortedlist\relax + \expandafter\toks@\expandafter{\@csv@listelement}% + \edef\@csv@sortedlist{\the\toks@}% +\else + \expandafter\@csv@insert@into\expandafter + {\@csv@listelement}{\@csv@sortedlist}% +\fi}\let#1\@csv@sortedlist} +% \end{macrocode} +%\end{macro} +% Insert element (first argument) into a sorted list (second argument) +% Each element must be in the form \marg{sort-key}\marg{data}, where +% \cmdname{csv@compare} sorts according to \meta{sort-key}. The +% insertion code ignores \meta{data}. +%\begin{macro}{\@csv@insertinto} +% \begin{macrocode} +\newcommand\@csv@insert@into[2]{% +\let\@csv@tmplist\relax +\@for\@sort@list@element:=#2\do{% + \expandafter\csv@compare\expandafter{\@sort@list@element}{#1}% + \if@csv@ishigher + \toks@{#1}% + \if\relax\@csv@tmplist + \edef\@csv@tmplist{\the\toks@,\@sort@list@element}% + \else + \edef\@csv@tmplist{\@csv@tmplist,\the\toks@,\@sort@list@element}% + \fi + \@endfortrue + \else + \if\relax\@csv@tmplist + \edef\@csv@tmplist{\@sort@list@element}% + \else + \edef\@csv@tmplist{\@csv@tmplist,\@sort@list@element}% + \fi + \fi +}% +\if@endfor + \ifx\@forremainder\@empty + \else + \edef\@csv@tmplist{\@csv@tmplist,\@forremainder}% + \fi +\else + \toks@{#1}% + \if\relax\@csv@tmplist + \edef\@csv@tmplist{\the\toks@}% + \else + \edef\@csv@tmplist{\@csv@tmplist,\the\toks@}% + \fi +\fi +\@endforfalse +\let#2\@csv@tmplist +} +% \end{macrocode} +%\end{macro} +% Define \cmdname{sortapplyCSVfile}. This is akin to \stynamefmt{csvtools}' +% \cmdname{applyCSVfile}, except it stores each data row in a list, +% sorts the list, and then iterates through the sorted list. As +% with, \cmdname{applyCSVfile}, the starred version should be used +% for a file that doesn't contain a header row, and the un-starred +% version should be used for a file that has a header row. Both +% forms take an optional argument, which should be a key=value list, +% the same as the package options, but they only apply to the +% current instance of \cmdname{sortapplyCSVfile}. +%\begin{macro}{\sortapplyCSVfile} +% \begin{macrocode} +\newcommand{\sortapplyCSVfile}{% +\@ifstar\@ssortapplyCSVfile\@sortapplyCSVfile} +% \end{macrocode} +%\end{macro} +% Starred version (see above): +%\begin{macro}{\@ssortapplyCSVfile} +% \begin{macrocode} +\newcommand{\@ssortapplyCSVfile}[3][]{% +\bgroup +\setkeys{csvsort.sty}{#1}% +\def\@csv@list{}% +\@sapplyCSVfile[\c@sfirstdataline]{#2}{% +\edef\csv@key{\csv@sortvariable}% +\if\relax\@csv@list\relax +\protected@xdef\@csv@list{{\csv@key}{\csvline}}% +\else +\protected@xdef\@csv@list{\@csv@list,{\csv@key}{\csvline}}% +\fi +}% +\@ssortapplyCSVdata{\@csv@list}{#3}% +\egroup} +% \end{macrocode} +%\end{macro} +% Unstarred version (see above): +%\begin{macro}{\@sortapplyCSVfile} +% \begin{macrocode} +\newcommand{\@sortapplyCSVfile}[3][]{% +\bgroup +\setkeys{csvsort.sty}{#1}% +\def\@csv@list{}% +\@applyCSVfile[\c@firstdataline]{#2}{% +\edef\csv@key{\csv@sortvariable}% +\if\relax\@csv@list\relax +\protected@xdef\@csv@list{{\csv@key}{\csvline}}% +\else +\protected@xdef\@csv@list{\@csv@list,{\csv@key}{\csvline}}% +\fi +}% +\@sortapplyCSVdata{\@csv@list}{#3}% +\egroup} +% \end{macrocode} +%\end{macro} +% \cmdname{sortapplyCSVdata}\oarg{sort type}\marg{cmd}\marg{text} +% will sort the data given by \meta{cmd}, which should contain +% a comma separated +% list of the form \marg{sort1}\marg{data1},\ldots\marg{sortN}\marg{dataN} +% and the applies \meta{text} to each data element of the list. +% The sort ordering is specified by \meta{sort type}, which should +% have the same values as the sort key used by +% \cmdname{sortapplyCSVfile}. +% The starred version doesn't permit +% \cmdname{insert}\meta{label} commands. First argument is the list, +% the second argument specifies what to do for each data element. +% (Note, these commands are primarily provided for the +% benefit of \texttt{csvtools.pl}, which is why they're not +% documented in the main part of the \stynamefmt{csvtools} manual.) +%\begin{macro}{\sortapplyCSVdata} +% \begin{macrocode} +\newcommand{\sortapplyCSVdata}{% +\@ifstar\@ssortapplyCSVdata\@sortapplyCSVdata} +% \end{macrocode} +%\end{macro} +% Starred version: +%\begin{macro}{\@ssortapplyCSVdata} +% \begin{macrocode} +\newcommand{\@ssortapplyCSVdata}[3][\relax]{% +\bgroup +\if\relax#1\relax\else\setkeys{csvsort.sty}{sort=#1}\fi +\csv@insertionsort{#2}% +\c@csvrownumber=0\relax +\@for\@csv@element:=#2\do{% +\expandafter\@csv@extractdata\@csv@element\csvline +\expandafter\toks@\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\toks@\@csvseparator}% +\long\edef\@csvlin@{\@csvseparator\csvline\@csvseparator}% +\c@field=0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\expandafter\toks@\expandafter{\param}% +\advance\c@field by 1\relax +\expandafter\xdef\csname @field\romannumeral\c@field\endcsname{% +\the\toks@}% +}% +\ifthenelse{\not\equal{\csvline}{}}{% +\refstepcounter{csvrownumber}% +#3}{}% +}% +\egroup +} +% \end{macrocode} +%\end{macro} +% Unstarred version (field labels will need to be set (using +% \cmdname{setcsvfieldlabel}) before using this macro.) +%\begin{macro}{\@sortapplyCSVdata} +% \begin{macrocode} +\newcommand{\@sortapplyCSVdata}[3][\relax]{% +\bgroup +\if\relax#1\relax\else\setkeys{csvsort.sty}{sort=#1}\fi +\csv@insertionsort{#2}% +\c@csvrownumber=0\relax +\@for\@csv@element:=#2\do{% +\expandafter\@csv@extractdata\@csv@element\csvline +\expandafter\toks@\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\toks@\@csvseparator}% +\long\edef\@csvlin@{\@csvseparator\csvline\@csvseparator}% +\c@field=0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +\expandafter\toks@\expandafter{\param}% +\advance\c@field by 1\relax +\expandafter\xdef\csname @field\romannumeral\c@field\endcsname{% +\the\toks@}% +\edef\@fieldlabel{% +\csname @fieldlabel\romannumeral\c@field\endcsname}% +\expandafter\xdef\csname insert\@fieldlabel\endcsname{\the\toks@}% +}% +\ifthenelse{\not\equal{\csvline}{}}{% +\refstepcounter{csvrownumber}% +#3}{}% +}% +\egroup +} +% \end{macrocode} +%\end{macro} +% Define \cmdname{sortCSVtotabular}. This is akin to \stynamefmt{csvtools}' +% \cmdname{CSVtotabular}, but sorts the data. Takes an optional +% argument that is a key=value list which is that same as the +% package options, but only applies to this instance of +%\cmdname{sortCSVtotabular}. This command first loads all the data +% into a list, sorts the list, and then puts it in a tabular +% environment. The total number of data rows is stored in +% \cmdname{maxlines}. +%\begin{macro}{\sortCSVtotabular} +% \begin{macrocode} +\newcommand{\sortCSVtotabular}[6][]{% +\@sortCSVtotabular[#1]{#2}{#3}{#4}{#5}{#6}{tabular}} +% \end{macrocode} +%\end{macro} +% As above, but use longtable environment instead: +%\begin{macro}{\sortCSVtolongtable} +% \begin{macrocode} +\newcommand{\sortCSVtolongtable}[6][]{% +\@sortCSVtotabular[#1]{#2}{#3}{#4}{#5}{#6}{longtable}} +% \end{macrocode} +%\end{macro} +% The final argument specifies which tabular-like environment +% to use: +%\begin{macro}{\@sortCSVtotabular} +% \begin{macrocode} +\newcommand{\@sortCSVtotabular}[7][]{% +\bgroup +\setkeys{csvsort.sty}{#1}% +% \end{macrocode} +% Read all data into \cmdname{@csv@list}: +% \begin{macrocode} +\def\@csv@list{}% +\@applyCSVfile[\c@firstdataline]{#2}{% +\edef\csv@key{\csv@sortvariable}% +\if\relax\@csv@list\relax +\protected@xdef\@csv@list{{\csv@key}{\csvline}}% +\else +\protected@xdef\@csv@list{\@csv@list,{\csv@key}{\csvline}}% +\fi +}% +% \end{macrocode} +% Sort data, and put in required tabular-like environment +% \begin{macrocode} +\sortCSVdatatotabular{\c@csvrownumber}{\@csv@list}{#3}{#4}{#5}{#6}{#7}% +\egroup +} +% \end{macrocode} +%\end{macro} +% \cmdname{sortCSVdatatotabular}\marg{n}\marg{list}\marg{col-align}\marg{header-row}\marg{all but last rows}\marg{last row}\marg{env-name}\par +% This command sorts the data specified by \meta{list} (which has +% \meta{n} elements) and puts in a tabular-like environment called +% \meta{env-name}. This command is mainly provided for the benefit +% of \texttt{csvtools.pl}, which is why it is not documented in the +% main part of the \stynamefmt{csvtools} manual. Field names must be +% set prior to use (using \cmdname{setcsvfieldlabel}.) +%\begin{macro}{\sortCSVdatatotabular} +% \begin{macrocode} +\newcommand{\sortCSVdatatotabular}[7]{% +% \end{macrocode} +% Set \cmdname{maxlines} (total number of data rows, not including +% header row). +% \begin{macrocode} +\maxlines=#1\relax +% \end{macrocode} +% Sort the data: +% \begin{macrocode} +\csv@insertionsort{#2}% +% \end{macrocode} +% Set \cmdname{csvlastbutone} to \cmdname{maxlines}$-1$: +% \begin{macrocode} +\csvlastbutone=\maxlines +\advance\csvlastbutone by -1\relax +% \end{macrocode} +% Reset \cmdname{c@csvrownumber}: +% \begin{macrocode} +\c@csvrownumber=0\relax +\c@csvlinenum=0\relax +% \end{macrocode} +% Initialise first row, last row and middle rows (in case not enough +% data) +% \begin{macrocode} +\def\@r@wh{#4}\def\@r@w{}\def\@r@wl{}% +% \end{macrocode} +% Iterate through each element of sorted list +% \begin{macrocode} +\@for\@csv@element:=#2\do{% +% \end{macrocode} +% Extract data from the current list element (ignoring sort key) +% and store in \cmdname{csvline}: +% \begin{macrocode} +\expandafter\@csv@extractdata\@csv@element\csvline +% \end{macrocode} +% Extract each field of \cmdname{csvline}: +% \begin{macrocode} +\expandafter\toks@\expandafter{\csvline}% +\edef\@csvlin@{\@csvseparator\the\toks@\@csvseparator}% +\long\edef\@csvlin@{\@csvseparator\csvline\@csvseparator}% +\c@field=0\relax +\whiledo{\not\equal{\@csvlin@}{\@csvseparator}}{% +\extractentry{\@csvlin@}{\param}% +% \end{macrocode} +% Store field in \cmdname{toks@} +% \begin{macrocode} +\expandafter\toks@\expandafter{\param}% +% \end{macrocode} +% Increment field counter +% \begin{macrocode} +\advance\c@field by 1\relax +% \end{macrocode} +% Define \cmdname{field}\meta{n} and associated +% \cmdname{insert}\meta{label} +% \begin{macrocode} +\expandafter\xdef\csname @field\romannumeral\c@field\endcsname{% +\the\toks@}% +\edef\@fieldlabel{% +\csname @fieldlabel\romannumeral\c@field\endcsname}% +\expandafter\xdef\csname insert\@fieldlabel\endcsname{\the\toks@}% +}% +% \end{macrocode} +% Increment row counter. +% \begin{macrocode} +\refstepcounter{csvrownumber}% +\refstepcounter{csvlinenum}% +% \end{macrocode} +% Check to see if this is the first row, last row, of somewhere in +% between +% \begin{macrocode} +\ifnum\c@csvrownumber=\maxlines + \protected@edef\@r@wl{#6}% +\else + \expandafter\toks@\expandafter{\@r@w} + \protected@edef\@r@w{\the\toks@#5}% +\fi +}% +% \end{macrocode} +% Now do tabular environment: +% \begin{macrocode} +\begin{#7}{#3}% +\@r@wh +\@r@w +\@r@wl +\end{#7}% +} +% \end{macrocode} +%\end{macro} +%\iffalse +% \begin{macrocode} +%</csvsort.sty> +% \end{macrocode} +%\fi +%\Finale +\endinput diff --git a/Master/texmf-dist/doc/latex/csvtools/source/csvtools.ins b/Master/texmf-dist/doc/latex/csvtools/source/csvtools.ins new file mode 100644 index 00000000000..a4b96b0cd8e --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/source/csvtools.ins @@ -0,0 +1,23 @@ +% csvtools.ins generated using makedtx version 0.91b 2007/7/3 10:24 +\input docstrip + +\preamble +Copyright (C) 2007 Nicola Talbot, all rights reserved. +If you modify this file, you must change its name first. +You are NOT ALLOWED to distribute this file alone. You are NOT +ALLOWED to take money for the distribution or use of either this +file or a changed version, except for a nominal charge for copying +etc. +\endpreamble + +\askforoverwritefalse + +\generate{\file{csvpie.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{csvtools.dtx}{csvpie.sty,package}} +\file{csvsort.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{csvtools.dtx}{csvsort.sty,package}} +\file{csvtools.sty}{\usepreamble\defaultpreamble +\usepostamble\defaultpostamble\from{csvtools.dtx}{csvtools.sty,package}} +} + +\endbatchfile |