0

I have a csv file with the following columns

Section Subsection item_number text
A N 1 "first_text_n"
A M 1 "first_text_m"
A M 3 "second_text_m"

I would like to use something to import this into a Latex document that will look like:

\section{A} \subsection{N} \begin{itemize} \item [1] first_text_n \end{itemize} \subsection{M} \begin{itemize} \item [1] first_text_m \item [3] second_text_m \end{itemize} 

I could do it as a custom program, but that seems like it would be a significant amount of work (and not be that flexible). Is there any way to do this with datatool or something else?

3
  • 1
    Please make your code compilable (if possible), or at least complete it with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem tedious to you, but think of the extra work it represents for the users willing to give you a hand. Help them help you: remove that one hurdle between you and a solution to your problem. Commented Jun 5 at 8:49
  • 1
    Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. Commented Jun 5 at 9:18
  • There are packages that support parsing CSV files. I think datatool and csvsimple should be interesting for you. Commented Jun 5 at 10:16

1 Answer 1

3

Datatool can do this task by looping over all items and inserting the desired \section, \subsection, and \begin{itemize}/\end{itemize} commands based on checking whether the values have changed. The basic algorithm is:

  1. If the Section value of the current row is different from the previous value, then close the previous itemize (except when there was no previous subsection) and add a \section{current row value} command
  2. If the Subsection value of the current row is different from the previous value, then:
    1. add an \end{itemize} command to end the list from the previous subsection (except when it is the first subsection in a section)
    2. add a \subsection{current row value} command
    3. add a \begin{itemize} command
  3. Add a line \item[item label] item contents

For this you need to know what the previous section and subsection are, which you can store in separate commands for comparison. These commands should be adjusted to store the new value in order to compare them for the next line.

Implementation of this algorithm with datatool:

\documentclass{article} \ExplSyntaxOn \cs_new_eq:NN \strcompare \str_if_eq:eeTF \ExplSyntaxOff \usepackage{datatool} \DTLloadrawdb{items}{myitems.csv} \dtlsort{Section,Subsection,itemnumber}{items}{\dtlcompare} % sort the csv (might not be needed if it is already in the desired order) \begin{document} \def\currsection{-1} % separate commands for comparison \def\currsubsection{-1} % \DTLforeach{items}{% \mysection=Section,\mysubsection=Subsection,\itemlabel=itemnumber,\itemcontents=text}{% \strcompare{\mysection}{\currsection}{}{% csv goes to a new section \strcompare{\currsubsection}{-1}{}{% check if there is a previous subsection with itemize that needs to be closed first \end{itemize} } \edef\currsection{\mysection}% update current section value for comparison in the next row \def\currsubsection{-1}% reset current subsection value to force a new \begin{itemize} in the check below \section{\mysection}% start the new section } \strcompare{\mysubsection}{\currsubsection}{% check for a new subsection \item[\itemlabel] \itemcontents}{% subsection still the same, only add an \item \strcompare{\currsubsection}{-1}{}{% subsection different, if it was not the first in the section then close previous itemize \end{itemize} } \edef\currsubsection{\mysubsection}% update current subsection value for comparison in the next row \subsection{\mysubsection}% start the new subsection \begin{itemize} % with an itemize \item[\itemlabel] \itemcontents % and the item }% } \end{itemize} % close the final itemize after the csv file is finished \end{document} 

Result:

sorted output of subsection structure

Note that here the command \DTLloadrawdb is used instead of the regular \DTLloaddb. This is done because the csv contained underscore (_) characters. This also means that you cannot use any LaTeX code in the csv. If you want this then use DTLloaddb and avoid underscores in text.

Relatedly, the column headers cannot contain underscores at all, so I changed item_number in the csv to itemnumber.

Note also that the code above sorts the csv first by Section, then Subsection, then itemnumber. This may not be needed or desired, and it can also be slow for larger files, so it may be better to remove the line performing the sort and sorting the data first before loading it into datatool.

Without the sorting line the output would be:

unsorted output of subsection structure

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.