6

Another file question from Latex; this time I'm trying to read in data from a single text file and put it directly into a table.

The file reads something like:

something | data | stuff | bacon

something else | data | different stuff | more bacon

3rd | 3rd data | you get the idea | bacon

To do this I could just use a simple \input but then I'd have to have all the table setup inside the text file. Since I'm not the one going to make the .txt files I'd prefer it stay nice and simple. My solution was to use expl3 and xparse. However I'm having a rough time figuring out how to make Latex spit out the file into a table. The closest I've come uses the following code and makes something like the picture.

This code I did not make myself. I found it from Arbitrary text parsing from a separate file via egreg: https://tex.stackexchange.com/users/4427/egreg . His response there was very helpful and I looked into expl3 and am beginning to get a better understanding. Unfortunately I don't understand this code too much; merely the syntax (still a bit shaky there too). My general understanding is that it makes a function within a function, etc. And then reads in a file. This code will read all the lines of a file, and I'm not sure how that loops or if it's recursive. I also have no idea what \taylor means. (Google was helpful in figuring most of it out, but no luck finding \taylor).

Any explanations of the code would also be much appreciated.

\NewDocumentCommand{\readdata}{O{|} m}
{ 
    \readdata:nn { #1 } { #2 }%
}


\cs_new_protected:Npn \readdata:nn #1 #2%
{
    \ior_open:Nn \g__read_ior { #2 }%
    \ior_map_inline:Nn \g__read_ior%
    {%
        \__process:nn { #1 } { ##1 }%
    }%
    \ior_close:N \g__read_ior%

}


\cs_new_protected:Npn \__process:nn #1 #2%
{   
    \seq_set_split:Nnn \l__line_seq { #1 } { #2 }%
    \use:x%
    {%
        \exp_not:N \DataEntry%
        \seq_map_function:NN \l__line_seq \__brace:n%
    }%
}


\cs_new:Npn \__brace:n #1 { { #1 } }%
\ExplSyntaxOff


\newcommand{\DataEntry}[4]  % Predetermined number of columns for data
{
    #1 & #2 & #3 & #4 \\%
    \hline
}


...later...


\begin{table}[ht] 
    \head{\caption{Results}}% title of Table 
    \centering 
    \begin{tabular}{|p{2.5cm}|p{2.5cm}|p{2.5cm}|p{3.5cm}|}

           I'd prefer to use |c| to have them centered, but that doesn't seem to work yet...

    \hline\hline
    Sample \# & Something & Results & Description \\ [0.5ex] % inserts table headings
    \hline      

\readdata[|]{data6.txt}
    \label{table:nonlin} % is used to refer this table in the text 
        \end{tabular}
    \end{table}

Image of horrible table

4
  • 1
    \taylor_ is just a prefix that acts somewhat as a namespace; probably the poster of the question you refer to is called Taylor, so I chose that prefix; for you I'd choose \mhag_
    – egreg
    May 15, 2014 at 18:07
  • Ahhh, Thanks. That helps clarify some of the syntax as well. I was thinking that \taylor_ was a necessary part.
    – mhag
    May 15, 2014 at 18:35
  • Surely the \label mustn't go inside the tabular. Also \head is an unknown command.
    – egreg
    May 15, 2014 at 19:52
  • Mmmh, bacon! :)
    – cgnieder
    May 15, 2014 at 20:34

1 Answer 1

4

The problem is that you're trying to add more lines to a tabular, but this can't be done with a loop starting in one cell and ending in another one. The loop must be performed completely, by storing the various table rows in a token list variable and eventually delivering this one.

\begin{filecontents*}{\jobname-data.txt}
something | data | stuff | bacon
something else | data | different stuff | more bacon
3rd | 3rd data | you get the idea | bacon
\end{filecontents*}

\documentclass{article}
\usepackage{xparse,booktabs}

\ExplSyntaxOn
\NewDocumentCommand{\readdata}{O{|} m}
 { 
  \mhag_readdata:nn { #1 } { #2 }
 }
\NewDocumentCommand{\DataEntry}{m m m m}% Predetermined number of columns for data
 {
  #1 & #2 & #3 & #4 \\
 }

\ior_new:N \g__mhag_read_stream % an input stream
\seq_new:N \l__mhag_line_seq    % a temporary sequence for processing a row
\tl_new:N \l__mhag_body_tl      % a container for the table body

\cs_new_protected:Npn \mhag_readdata:nn #1 #2
 {
  % clear the table body
  \tl_clear:N \l__mhag_body_tl
  % open the input stream
  \ior_open:Nn \g__mhag_read_stream { #2 }
  % loop on the file lines
  \ior_map_inline:Nn \g__mhag_read_stream
   {% process the current line
    \__mhag_process:nn { #1 } { ##1 }
   }
  % the loop has ended, close the stream
  \ior_close:N \g__mhag_read_stream
  % deliver the table body
  \tl_use:N \l__mhag_body_tl
 }


\cs_new_protected:Npn \__mhag_process:nn #1 #2
 {% split the line at | (or the character specified in the optional argument
  \seq_set_split:Nnn \l__mhag_line_seq { #1 } { #2 }
  % add a line to the table body
  \tl_put_right:Nx \l__mhag_body_tl
   {% this will put a in \l__mhag_body_tl the tokens
    % \DataEntry{<item 1>}{<item 2>}{<item 3>}{<item 4>}
    \DataEntry \seq_map_function:NN \l__mhag_line_seq \__mhag_brace:n
   }
 }

% the auxiliary function for bracing each item
\cs_new:Npn \__mhag_brace:n #1 { { #1 } }
\ExplSyntaxOff

\begin{document}

\begin{table}[ht] 
\centering 
\caption{Results}% title of Table 
\label{table:nonlin} % is used to refer this table in the text

\medskip

\begin{tabular}{@{}p{2.5cm}p{2.5cm}p{2.5cm}p{2.5cm}@{}}
\toprule
Sample \# & Something & Results & Description \\ % inserts table headings
\midrule
\readdata[|]{\jobname-data.txt}
\bottomrule
\end{tabular}

\end{table}

\end{document}

I've used filecontents* to keep the example selfcontained. I also used booktabs to get a better table.

enter image description here

2
  • Thanks; \head is a \newcommand I had to make for a specific looking header I had been using multiple times, and \label was misplaced. For my purposes I don't need it, I must have forgotten about it. I greatly appreciate your help. I have a lot to learn working in this new environment. It's pretty daunting to learn when are there so many packages. Is there any documents/books you could recommend to me?
    – mhag
    May 15, 2014 at 20:46
  • 1
    @mhag I'm (slowly) writing one about LaTeX3 programming.
    – egreg
    May 15, 2014 at 20:47

You must log in to answer this question.

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