I have to generate a number of tables from CSV data which span a couple of hundred pages or more. So, I need some kind of automation for this.
Please note the following salient points:
- The data has two main parts in each row, some kind of name in the first column followed by data in the rest of the columns.
- The number of columns in the CSV data varies from one table to another. But the number remains fixed in a single table.
- The data is generated automatically in a
software application. The number of rows in a table is variable and
may span multiple pages. Hence, I need to use
longtable
. - A variable number of columns are grouped under the main categories. That is the number of sub-categories under each category is not fixed.
- Since the application generating this data is also local (own-built), the data format can be customized (up to a certain extent).
- The number of rows in a table will vary from table to table and may (vertically) exceed one page.
- A number of leftmost columns will have to be repeated when the table is split horizontally.
The CSV file will look something like this.
Name,4:Category 1,3:Category 2,6:Category 3,8:Category 4,5:Category 5,7:Category 6 Sub-category,Sc11,Sc12,Sc13,Sc14,Sc21,Sc22,Sc23,Sc31,Sc32,Sc33,Sc34,Sc35,Sc36,Sc41,Sc42,Sc43,Sc44,Sc45,Sc46,Sc47,Sc48,Sc51,Sc52,Sc53,Sc54,Sc55,Sc61,Sc62,Sc63,Sc64,Sc65,Sc66,Sc67 Name 1,11,12,13,14,21,22,23,31,32,33,34,35,36,41,42,43,44,45,46,47,48,51,52,53,54,55,61,62,63,64,65,66,67 Name 2,11,12,13,14,21,22,23,31,32,33,34,35,36,41,42,43,44,45,46,47,48,51,52,53,54,55,61,62,63,64,65,66,67
Each number, m preceding the Category n
indicates
the number of sub-categories under that category. As such, 4:Category 1
indicates that there are 4 sub-categories under Category 1
.
Though the above one is more or less a pure CSV input, putting some kind of predefined macro command around each row, and an environment around the whole table is also possible. So, the input for one table could be like:
\begin{csvwidetable}{1}
\csvwidetableheader{Name,4:Category 1,3:Category 2,6:Category 3,8:Category 4,5:Category 5,7:Category 6}
\csvwidetablescheader{Sub-category,Sc11,Sc12,Sc13,Sc14,Sc21,Sc22,Sc23,Sc31,Sc32,Sc33,Sc34,Sc35,Sc36,Sc41,Sc42,Sc43,Sc44,Sc45,Sc46,Sc47,Sc48,Sc51,Sc52,Sc53,Sc54,Sc55,Sc61,Sc62,Sc63,Sc64,Sc65,Sc66,Sc67}
\csvwidetablerow{Name 1,11,12,13,14,21,22,23,31,32,33,34,35,36,41,42,43,44,45,46,47,48,51,52,53,54,55,61,62,63,64,65,66,67}
\csvwidetablerow{Name 2,11,12,13,14,21,22,23,31,32,33,34,35,36,41,42,43,44,45,46,47,48,51,52,53,54,55,61,62,63,64,65,66,67}
\end{csvwidetable}
Here 1
as environment argument indicates that 1 left most column will have to be repeated.
Please see the code below which I believe should be able to explain the effect I am trying to achieve.
\begin{document}
\newlength{\ncw}
\setlength{\ncw}{10.00mm}
If we resort to putting each row of CSV in a single row of the table,
it will not fit. Moreover, we will need to find a way to put those
headers like `Category 1` over multiple columns.
\begin{longtable}[l]{|l|*{33}{C{\ncw}|}}
\hline
Name&\multicolumn{4}{|c|}{Category 1}&\multicolumn{3}{c|}{Category 2}&\multicolumn{6}{c|}{Category 3}&\multicolumn{8}{|c|}{Category 4}&\multicolumn{5}{c|}{Category 5}&\multicolumn{7}{c|}{Category 6}\\\hline
Sub-category&Sc11&Sc12&Sc13&Sc14&Sc21&Sc22&Sc23&Sc31&Sc32&Sc33&Sc34&Sc35&Sc36&Sc41&Sc42&Sc43&Sc44&Sc45&Sc46&Sc47&Sc48&Sc51&Sc52&Sc53&Sc54&Sc55&Sc61&Sc62&Sc63&Sc64&Sc65&Sc66&Sc67\\\hline
\endhead
\hline
\endfoot
Name 1&11&12&13&14&21&22&23&31&32&33&34&35&36&41&42&43&44&45&46&47&48&51&52&53&54&55&61&62&63&64&65&66&67\\\hline
Name 2&11&12&13&14&21&22&23&31&32&33&34&35&36&41&42&43&44&45&46&47&48&51&52&53&54&55&61&62&63&64&65&66&67\\
\end{longtable}
As of this moment, we employ some pre-fixed heuristics in the
application to break columns at convenient points. We need to
repeat the left column. See below for examples.
In this table, I can accommodate up to Category 3.
\begin{longtable}[l]{|l|*{13}{C{\ncw}|}}
\hline
Name&\multicolumn{4}{|c|}{Category 1}&\multicolumn{3}{c|}{Category 2}&\multicolumn{6}{c|}{Category 3}\\\hline
Sub-category&Sc11&Sc12&Sc13&Sc14&Sc21&Sc22&Sc23&Sc31&Sc32&Sc33&Sc34&Sc35&Sc36\\\hline
\endhead
\hline
\endfoot
Name 1&11&12&13&14&21&22&23&31&32&33&34&35&36\\\hline
Name 2&11&12&13&14&21&22&23&31&32&33&34&35&36\\
\end{longtable}
The rest (Category 4--Category 6) goes in this table.
\begin{longtable}[l]{|l|*{20}{C{\ncw}|}}
\hline
Name&\multicolumn{8}{|c|}{Category 4}&\multicolumn{5}{c|}{Category 5}&\multicolumn{7}{c|}{Category 6}\\\hline
Sub-category&Sc41&Sc42&Sc43&Sc44&Sc45&Sc46&Sc47&Sc48&Sc51&Sc52&Sc53&Sc54&Sc55&Sc61&Sc62&Sc63&Sc64&Sc65&Sc66&Sc67\\\hline
\endhead
\hline
\endfoot
Name 1&41&42&43&44&45&46&47&48&51&52&53&54&55&61&62&63&64&65&66&67\\\hline
Name 2&41&42&43&44&45&46&47&48&51&52&53&54&55&61&62&63&64&65&66&67\\
\end{longtable}
\end{document}
Here is the output from the above code.
So, what we are trying to achieve is to generate long tables
from CSV data, break columns at convenient columns when the width
exceeds text width (without breaking
at mid of any Category n
), and (optionally) repeat some the left-most column.
(Please ignore the issue of vertical lines. I know that vertical lines in table did not have much good time in this forum.)
xtable
,kable
or similar packages can export to nice latex tables of selected columns and rows (also in longtable format at least withxtable
) Code it all in the own LateX source code withknitr
is straightforward. The main problem are the main multicolumns categories that do not fit the structure of a data frame, but they can be added to a particular sub data frame.