diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-09 00:49:07 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-09 00:49:07 +0000 |
commit | 007f67a693e4d031fd3d792df8e4d5f43e2cb2e7 (patch) | |
tree | 90d17e00e572ecb1e24764b6f29c80e098b08d29 /Master/texmf-dist/doc/latex/csvtools | |
parent | 950209b26f70aa87ed07c54f82a95b6f03b7c3a0 (diff) |
doc/latex
git-svn-id: svn://tug.org/texlive/trunk@84 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/latex/csvtools')
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/README | 38 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/csvtools.html | 806 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/csvtools.pdf | bin | 0 -> 199065 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/csvtools/csvtools.pl | 1305 |
4 files changed, 2149 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/csvtools/README b/Master/texmf-dist/doc/latex/csvtools/README new file mode 100644 index 00000000000..6134501469f --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/README @@ -0,0 +1,38 @@ +LaTeX Package : csvtools v 1.1 + +Last Modified : 19 Oct 2004 + +Author : Nicola Talbot + +Files : csvtools.dtx - documented source file + csvtools.ins - installation script + +The 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. 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.) + +To extract the documentation, do: + +latex csvtools.dtx +latex csvtools.dtx + +Alternatively, if you use pdflatex instead of latex, the documentation will +have hyperlinks. + +This material is subject to the LaTeX Project Public License. +See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html for +details of that license. + +http://theoval.cmp.uea.ac.uk/~nlct diff --git a/Master/texmf-dist/doc/latex/csvtools/csvtools.html b/Master/texmf-dist/doc/latex/csvtools/csvtools.html new file mode 100644 index 00000000000..3e0937c4d80 --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/csvtools.html @@ -0,0 +1,806 @@ +<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 differnew file mode 100644 index 00000000000..db205023e1e --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/csvtools.pdf diff --git a/Master/texmf-dist/doc/latex/csvtools/csvtools.pl b/Master/texmf-dist/doc/latex/csvtools/csvtools.pl new file mode 100644 index 00000000000..2cc4df9a073 --- /dev/null +++ b/Master/texmf-dist/doc/latex/csvtools/csvtools.pl @@ -0,0 +1,1305 @@ +#!/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; |