3

I am using datatool package. Several csv files with data are generated in my project and I create index.csv to use Nested \ DTLforeach.

I do not understand how I can assemble a 3x3 / 3x4 or 3x5 matrix depending on the number of csv files.

\documentclass[a4paper]{article}
\usepackage{pgf}
\usepackage{pgffor}
\usepackage{datatool}


\begin{document}
\begin{filecontents}{index.csv}
    File
    1.csv
    2.csv
    3.csv
    4.csv
    5.csv
    6.csv
    7.csv
\end{filecontents}
\begin{filecontents}{1.csv}
    Header 1
    image 1
    description 1
\end{filecontents}
\begin{filecontents}{2.csv}
    Header 2
    image 2
    description 2
\end{filecontents}
\begin{filecontents}{3.csv}
    Header 3
    image 3
    description 3
\end{filecontents}
\begin{filecontents}{4.csv}
    Header 4
    image 4
    description 4
\end{filecontents}
\begin{filecontents}{5.csv}
    Header 5
    image 5
    description 5
\end{filecontents}
\begin{filecontents}{6.csv}
    Header 6
    image 6
    description 6
\end{filecontents}
\begin{filecontents}{7.csv}
    Header 7
    image 7
    description 7
\end{filecontents}

\DTLloaddb{index}{index.csv}
\DTLforeach{index}{\theFile=File}{
    \DTLloaddb{\theFile}{\theFile}
    \DTLforeach{\theFile}{\theHeader=\theFile}{\theHeader & \theHeader & \theHeader \\}
}
\end{document}

How can a matrix be formed so that it detects the heading of each csv file and substitutes it in the tabular environment. I have no idea how to achieve this result, thank you for any help.

enter image description here

4
  • 1
    Welcome to TeX.SE!
    – Mensch
    Sep 22, 2021 at 10:32
  • I added some explanation of the code to allow for your customization. Thank for your feedback. Sep 23, 2021 at 20:54
  • @Simon Dispa Thank you very much !!! This is what you need, something that I could not reproduce! Sep 23, 2021 at 20:56
  • Please see the updated answer Oct 1, 2021 at 13:56

2 Answers 2

3

Try this code.

A3

The code:

The Ncols parameter sets the number of columns in the width of the text. The figure was created with Ncols =3.

First we load the database index with the file names. They will be displayed in the same order. The file names are irrelevant.

Then we go through all the index entries, opening the named file and loading databases 1, 2, 3, ... and so on, using the [noheader] option.

To display its content we use an internal loop to create another tabular and insert it in a minipage with an auto-adjusted width, to be able to insert Ncols in the width of the text on the page, as a row of the outer tabular.

\documentclass[a4paper]{article}

\usepackage{datatool}
\usepackage{ifthen}% added <<
\usepackage{calculator}% added <<

\newcounter{nrow}
\setcounter{nrow}{1}

\newcounter{Ncols}
\setcounter{Ncols}{3} % set the number of columns in text width <<<<<<<<<<<<<<<<<<<<<<<

\newlength{\Mwidth}
\DIVIDE{1}{\value{Ncols}}{\Wcmd} 
\LENGTHSUBTRACT{\Wcmd\textwidth}{1.5em}{\Mwidth}

\begin{document}    
    \begin{filecontents}{index.csv}
        File
        ONE.csv
        TWO.csv
        alpha.csv
        beta.csv
        gamma.csv
        simon.csv
        dispa.csv
    \end{filecontents}
    \begin{filecontents}{ONE.csv}
        Header 1
        image 1
        description 1 
        xxxx
    \end{filecontents}
    \begin{filecontents}{TWO.csv}
        Header 2
        image 2
        description 2
    \end{filecontents}
    \begin{filecontents}{alpha.csv}
        Header 3
        image 3
        description 3
    \end{filecontents}
    \begin{filecontents}{beta.csv}
        Header 4
        image 4
        description 4
    \end{filecontents}
    \begin{filecontents}{gamma.csv}
        Header 5
        image 5
        description 5
    \end{filecontents}
    \begin{filecontents}{simon.csv}
        Header 6
        image 6
        description 6
    \end{filecontents}
    \begin{filecontents}{dispa.csv}
        Header 7
        image 7
        description 7
    \end{filecontents}
    
    \DTLloaddb{index}{index.csv}
    
            \noindent\begin{tabular}{@{}l@{}}
        \DTLforeach{index}{\one=File}{%
            \DTLloaddb[noheader]{\thenrow}{\one}%
            \INTEGERDIVISION{\value{nrow}}{\value{Ncols}}{\sola}{\solb}
            \ifthenelse{\solb =1}{\\}{}% Ncols m1nipages per line
        \begin{minipage}[t]{\Mwidth}% auto adjusted width
                \noindent%
                \begin{tabular}[t]{@{}p{\Mwidth}@{}}%
                \DTLforeach{\thenrow}{\one=Column1}{\one \\}%   display file content            
                \end{tabular}%
                \stepcounter{nrow}% 
            \end{minipage}\hspace*{2em}%    
        }
    \end{tabular}   

\end{document}

Using \setcounter{Ncols}{4}

A4

UPDATE For longer descriptions (1) Write a long line (as #5) or (2) add more lines to the .csv file (as #1)

d

Test this code.

\documentclass[a4paper]{article}

\usepackage{datatool}
\usepackage{ifthen}% added <<
\usepackage{calculator}% added <<

\newcounter{nrow}
\setcounter{nrow}{1}

\newcounter{Ncols}
\setcounter{Ncols}{3} % set the number of columns in text width <<<<<<<<<<<<<<<<<<<<<<<

\newlength{\Mwidth}
\DIVIDE{1}{\value{Ncols}}{\Wcmd} 
\LENGTHSUBTRACT{\Wcmd\textwidth}{2.2em}{\Mwidth}
    
\begin{document}    
    \begin{filecontents}{index.csv}
        File
        ONE_long.csv
        TWO.csv
        alpha.csv
        beta.csv
        gamma_long.csv
        simon.csv
        dispa.csv
    \end{filecontents}
    \begin{filecontents}{ONE_long.csv} 
        Header 1
        image 1
        description 1a 
        description 1b 
        description 1c 
    \end{filecontents}
    \begin{filecontents}{TWO.csv}
        Header 2
        image 2
        description 2
    \end{filecontents}
    \begin{filecontents}{alpha.csv}
        Header 3
        image 3
        description 3
    \end{filecontents}
    \begin{filecontents}{beta.csv}
        Header 4
        image 4
        description 4
    \end{filecontents}
    \begin{filecontents}{gamma_long.csv}
        Header 5
        image 5
        a very long long description 5a     
    \end{filecontents}
    \begin{filecontents}{simon.csv}
        Header 6
        image 6
        description 6
    \end{filecontents}
    \begin{filecontents}{dispa.csv}
        Header 7
        image 7
        description 7
    \end{filecontents}
    
    \DTLloaddb{index}{index.csv}
    
    \section*{Long Descriptions}
    
    \noindent\begin{tabular}{@{}l@{}}
        \DTLforeach{index}{\one=File}{%
            \DTLloaddb[noheader]{\thenrow}{\one}%
            \INTEGERDIVISION{\value{nrow}}{\value{Ncols}}{\sola}{\solb}
            \ifthenelse{\solb =1}{\\}{}% Ncols m1nipages per line
        \begin{minipage}[t]{\Mwidth}% auto adjusted width
                \noindent%
                \begin{tabular}[t]{@{}p{\Mwidth}@{}}%
                \DTLforeach{\thenrow}{\one=Column1}{\one \\}%   display file content            
                \end{tabular}%
                \stepcounter{nrow}% 
            \end{minipage}\hspace*{2em}%    
        }
    \end{tabular}   

\end{document}
4
  • Thanks !!! This code really works and there is flexibility for customization, this is what I needed, thank you! I don't know how to thank you for this decision! Sep 23, 2021 at 20:51
  • Is it possible to break the line if it becomes too long in the description? Oct 1, 2021 at 7:34
  • @Forest Selton I added an update to the answer. Oct 1, 2021 at 13:56
  • Oh, Thank you! It works, this is what i need. Oct 7, 2021 at 6:30
2

Here's a version that doesn't depend on datatool

\begin{filecontents}{index.csv}
    File
    1.csv
    2.csv
    3.csv
    4.csv
    5.csv
    6.csv
    7.csv
\end{filecontents}
\begin{filecontents}{1.csv}
    Header 1
    image 1
    description 1
\end{filecontents}
\begin{filecontents}{2.csv}
    Header 2
    image 2
    description 2
\end{filecontents}
\begin{filecontents}{3.csv}
    Header 3
    image 3
    description 3
\end{filecontents}
\begin{filecontents}{4.csv}
    Header 4
    image 4
    description 4
\end{filecontents}
\begin{filecontents}{5.csv}
    Header 5
    image 5
    description 5
\end{filecontents}
\begin{filecontents}{6.csv}
    Header 6
    image 6
    description 6
\end{filecontents}
\begin{filecontents}{7.csv}
    Header 7
    image 7
    description 7
\end{filecontents}

\documentclass[a4paper]{article}
\usepackage{booktabs}

\ExplSyntaxOn

\NewDocumentCommand{\presentdata}{O{3}m}
 {% #1 = number of columns, default 3
  % #2 = file name
  \selton_presentdata:nn { #1 } { #2 }
 }

\ior_new:N \g__selton_presentdata_ior
\seq_new:N \l__selton_presentdata_files_seq
\seq_new:N \l__selton_presentdata_items_seq
\int_new:N \l__selton_presentdata_cols_int
\tl_new:N \l__selton_presentdata_body_tl

\cs_new_protected:Nn \selton_presentdata:nn
 {
  % clear the token list containing the body
  \tl_clear:N \l__selton_presentdata_body_tl
  % remember the desired number of columns
  \int_set:Nn \l__selton_presentdata_cols_int { #1 }
  % open the file to read the file names
  \ior_open:Nn \g__selton_presentdata_ior { #2 }
  % now we store the file names
  \seq_clear:N \l__selton_presentdata_files_seq
  \ior_map_inline:Nn \g__selton_presentdata_ior
   {
    \seq_put_right:Nx \l__selton_presentdata_files_seq { \tl_trim_spaces:n { ##1 } }
   }
  % remove blank items
  \seq_remove_all:Nn \l__selton_presentdata_files_seq { }
  % remove the first item
  \seq_pop_left:NN \l__selton_presentdata_files_seq \l_tmpa_tl
  % pad the sequence to a multiple of #2 with blanks
  \int_compare:nF { \int_mod:nn { \seq_count:N \l__selton_presentdata_files_seq } { #1 } == 0 }
   {% not a multiple, pad
    \prg_replicate:nn
     { #1 - \int_mod:nn { \seq_count:N \l__selton_presentdata_files_seq } { #1 } }
     { \seq_put_right:Nn \l__selton_presentdata_files_seq { } } 
   }
  % close the file
  \ior_close:N \g__selton_presentdata_ior
  % now populate the body of the table
  \seq_map_indexed_function:NN \l__selton_presentdata_files_seq \__selton_presentdata_entry:nn
  % and typeset the table
  \begin{tabular}{@{} *{#1}{l} @{}}
  \toprule
  \tl_use:N \l__selton_presentdata_body_tl
  \bottomrule
  \end{tabular}
 }

\cs_new_protected:Nn \__selton_presentdata_entry:nn
 {%#1 is the item number, #2 is the item
  \tl_if_blank:nF { #2 }
   {% the item is not empty, open the file and clear the sequence
    \ior_open:Nn \g__selton_presentdata_ior { #2 }
    \seq_clear:N \l__selton_presentdata_items_seq
    % populate the sequence
    \ior_map_inline:Nn \g__selton_presentdata_ior
     {
      \seq_put_right:Nn \l__selton_presentdata_items_seq { ##1 }
     }
    % remove blank items
    \seq_remove_all:Nn \l__selton_presentdata_items_seq { }
    % close the file
    \ior_close:N \g__selton_presentdata_ior
    % typeset a nested table
    \tl_put_right:Nx \l__selton_presentdata_body_tl
     {
      \exp_not:N \begin{tabular}[t]{@{}l@{}}
      \seq_use:Nn \l__selton_presentdata_items_seq { \\ }
      \exp_not:N \end{tabular}
     }
   }
  % add & or \\
  \int_compare:nTF { \int_mod:nn { #1 } { \l__selton_presentdata_cols_int } == 0 }
   {% multiple of the number of columns
    \tl_put_right:Nn \l__selton_presentdata_body_tl { \\ }
    % if not at the last cell, issue \addlinespace
    \int_compare:nT { #1 < \seq_count:N \l__selton_presentdata_files_seq }
     {
      \tl_put_right:Nn \l__selton_presentdata_body_tl { \addlinespace }
     }
   }
   {% not a multiple
    \tl_put_right:Nn \l__selton_presentdata_body_tl { & }
   }
 }

\ExplSyntaxOff

\begin{document}

\presentdata{index.csv}

\bigskip

\presentdata[4]{index.csv}

\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .