3

I am interested in loading physical quantities (number, error, unit) that I have stored elsewhere, like a .csv file, directly in my latex document. This is inspired by this video, where they use datatool to load just numbers. I did what the video does, and it works. The issue is I also want to load units like kg.m/s^2 and format them with the siunitx package, but I cant make it work. So far, I have this:

  • A .csv file like the following, generated with an external program
forza,233.0,4.0,kg.m/s^2

Note that it has 4 elements, a name (forza), value (233.0), error (4.0) and units (kg.m/s^2)

  • The main.tex file
\documentclass{article}

\usepackage{siunitx}
\usepackage{datatool}
\DTLsetseparator{,}
\DTLloaddb[
    noheader,
    keys={nome,valor,erro,unidade}
]{datos}{datos.csv}

\newcommand{\cantidade}[1]{
    \DTLfetch{datos}{nome}{#1}{valor}
    \pm
    \DTLfetch{datos}{nome}{#1}{erro}
    \DTLfetch{datos}{nome}{#1}{unidade}
}

\begin{document}

$\cantidade{forza}$

\end{document}

This generates the output poorly formatted physics value with units

The obvious idea to me was to use the \qty command from siunitx to 'parse' the units. Thats were I got stuck. I tried rewriting the command like

\newcommand{\cantidade}[1]{
    \qty{
            \DTLfetch{datos}{nome}{#1}{valor}
            \pm
            \DTLfetch{datos}{nome}{#1}{erro}
        }
        {
            \DTLfetch{datos}{nome}{#1}{unidade}
        }
}

where the first slot for \qty is supposed to be a value with an error, and the second its units. This raises an undefined control sequence error. Using only the \unit command with the units alone also results in the same error. I tried a couple things, changing the syntax (desperate attempts with math mode here and there), using \DTLfetchrawdb, but nothing seems to work.

To be concise: How do I load the units from the .csv file and parse them using siunitx?

Additionaly: I dont know whenever this is just a syntax error on my side or if its impossible to do at all. If it is the latter, an alternative solution for loading values with units that does not rely on datatool might be acceptable too!

New contributor
Deivis is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

1 Answer 1

3

The command \DTLfetch is not expandable. But you can make a variant \DTLfetchsave that stores the result in a (local) control sequence and use that to feed \qty. The idea comes from page 104 of datatool manual (look for \dtlcurrentvalue).

\begin{filecontents*}{\jobname.csv}
forza,233.0,4.0,kg.m/s^2
\end{filecontents*}

\documentclass{article}

\usepackage{siunitx}
\usepackage{datatool}

\DTLsetseparator{,}
\DTLloaddb[
  noheader,
  keys={nome,valor,erro,unidade}
]{datos}{\jobname.csv}

\newcommand{\DTLfetchsave}[5]{%
  \edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
  \dtlgetentryfromcurrentrow{#5}{\dtlcolumnindex{#1}{#4}}%
}

\newcommand{\cantidade}[1]{%
  \begingroup
  \DTLfetchsave{datos}{nome}{#1}{valor}{\valor}%
  \DTLfetchsave{datos}{nome}{#1}{erro}{\erro}%
  \DTLfetchsave{datos}{nome}{#1}{unidade}{\unidade}%
  \qty{\valor+-\erro}{\unidade}%
  \endgroup
}

\begin{document}

$\cantidade{forza}$

\sisetup{separate-uncertainty}

\cantidade{forza}

\end{document}

Each item is stored in a (local) macro, so we can use it for feeding to \qty.

I used filecontents* and \jobname just to make the example self-contained. You can use your own CSV file.

output

1
  • This works perfectly. So many thanks!
    – Deivis
    Commented Sep 3 at 17:59

You must log in to answer this question.

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