0

Suppose I have an Excel spreadsheet file data.xlsx whose content is

        A             B
1  Third Parameter    7
2  First Parameter    5
3  Second Parameter   3

and I would like to look up the value in column B using the corresponding text in column A.

In other words, I need to have a Latex command like, for instance, \getValue{<macro name to save the value in>}{<Search word>}{<Excel file name>}. So, for example, \getValue{\rdPar}{Third Parameter}{data.xlsx} will store the value of 7 in \rdPar to be used later in my latex document.

P.S. Maybe, this question is helpful but I don't know how to edit the answers for my need.

Diaa
  • 9,599
  • 1
    This has nothing whatsoever to do with TeX/LaTeX. – vonbrand Sep 15 '20 at 01:05
  • I’m voting to close this question because it is not about TeX/LaTeX and friends – vonbrand Sep 15 '20 at 01:06
  • 1
    @vonbrand I need latex to retrieve data from excel file, so how (by any means) does my question not relate to latex? – Diaa Sep 15 '20 at 01:09
  • @Diaa I disagree with the close vote, however I'm afraid what you want is nearly impossible with LaTeX. You see, TeX is build for reading plain text files, not binary (.xls(x) is binary), so doing what you want would require 1) to get a full spec of the .xlsx file format (the easy part) and 2) implement that in LaTeX (the hard, if not impossible part, due to how TeX reads files). That said, if you can export your .xlsx file to a plain text (usually .csv) format, the solution would be rather easy. – Phelype Oleinik Sep 15 '20 at 01:21
  • 1
    I think your problem is that you didn't explicitly say "I need latex to do this". The closest you come is \getValue. Also, your tagging implies that you're trying to do this in perl, not tex. Your question is relatively easy to solve if you change your file to a csv. Is that feasible? Or must it be xlsx? – Teepeemm Sep 15 '20 at 01:21
  • @PhelypeOleinik I can have the file in csv format. So, I would be grateful if you can help in this case. – Diaa Sep 15 '20 at 01:28
  • @Teepeemm I can get the data in csv format. So, I will be happy if you give a hand on it. – Diaa Sep 15 '20 at 01:30
  • You can have a peek at https://ctan.org/pkg/datatool and https://ctan.org/pkg/csvsimple?lang=en – Rmano Sep 15 '20 at 07:30
  • Also look at https://tex.stackexchange.com/questions/472182/use-foreach-to-read-columns-from-a-csv-file – Rmano Sep 15 '20 at 07:39

1 Answers1

4

Assuming you can use .csv instead of .xls(x), there are several tools for manipulating CSV files, for example csvsimple.

Though if you want to reinvent some wheels: you can use \ReadCSV to read in the .csv file to a key-value structure, then \getValue to fetch those values when needed. The syntax of \ReadCSV is:

\ReadCSV [*] {<label>} [<name>,<value>] {<file>}

\ReadCSV will read the CSV <file>, and take columns <name> and <value> (<name> and <value> are the number of the columns; defaults are <name>=1 and <value>=2) and save them under the <label> for later. If the optional * is used, the file is read as a string.

Once the file is read, you can fetch the saved values using \getValue:

\getValue <macro> {<name>} {<label>}

\getValue will fetch the <value> column for the respective <name> in the CSV file read under <label>, and save that in the <macro>.

In your example (removing header row and column), you'd have:

\ReadCSV{mydata}{test.csv}
\getValue\rdPar{Third Parameter}{mydata}
\rdPar % prints 7

Here's the expl3 implementation (it is minimalistic: there's no error checking for wrong input, missing data, etc.):

\begin{filecontents*}{test.csv}
Third Parameter  , 7
First Parameter  , 5
Second Parameter , 3
\end{filecontents*}

\documentclass{article} \usepackage{xparse}

\ExplSyntaxOn % Step 1: reading the file \ior_new:N \l__diaa_csv_ior \bool_new:N \l__diaa_csv_str_bool \NewDocumentCommand \ReadCSV { s m >{ \SplitArgument {1} {,} }O{ 1,2 } m } { \IfBooleanTF {#1} { \bool_set_true:N \l__diaa_csv_str_bool } { \bool_set_false:N \l__diaa_csv_str_bool } \diaa_csv_read:nnnn {#2} #3 {#4} } \cs_new_protected:Npn \diaa_csv_read:nnnn #1 #2 #3 #4 { \prop_new:c { g__diaa_csv_#1_prop } \ior_open:NnTF \l__diaa_csv_ior {#4} { __diaa_csv_read:cnn { g__diaa_csv_#1_prop } {#2} {#3} } { \msg_error:nnn { diaa } { file-not-found } {#4} } } \msg_new:nnn { diaa } { file-not-found } { File~`#1'~not~found. } \cs_new_protected:Npn __diaa_csv_read:Nnn #1 #2 #3 { \bool_if:NTF \l__diaa_csv_str_bool { \ior_str_map_inline:Nn } { \ior_map_inline:Nn } \l__diaa_csv_ior { \prop_put:Nxx #1 { \clist_item:nn {##1} {#2} } { \clist_item:nn {##1} {#3} } } } \cs_generate_variant:Nn __diaa_csv_read:Nnn { c } % % Step 2: getting the values \NewDocumentCommand \getValue { m m m } { \tl_set:Nx #1 { \diaa_csv_item:nn {#2} {#3} } } \NewExpandableDocumentCommand \CSVItem { m m } { \diaa_csv_item:nn {#1} {#2} } \cs_new:Npn \diaa_csv_item:nn #1 #2 { \prop_item:cn { g__diaa_csv_#2_prop } {#1} } \ExplSyntaxOff

\begin{document}

\ReadCSV{mydata}{test.csv}

\getValue\rdPar{Third Parameter}{mydata} \rdPar

\edef\rdPar{\CSVItem{First Parameter}{mydata}}% \rdPar

\end{document}

frougon
  • 24,283
  • 1
  • 32
  • 55
  • Many thanks for the answer. I am away from the PC to apply it. However, is it possible to extend the functionality of the \getValue command to make it accept more inputs of the look up column number (e.g. 1 here) or its name if it has header and the number/header name of the values column?. If it is worth asking a new followup question, please let me know. – Diaa Sep 15 '20 at 08:01
  • @Diaa You mean so that \getValue\rdPar{Third Parameter}{mydata} works as well as \getValue\rdPar{A}{mydata} or \getValue\rdPar{1}{mydata}? It should be possible, but a bit complicated, since you'd have to really parse the .csv file and store some data about it (my answer just reads it and discards everything except for the selected columns). I'd prefer you ask a new question, but since the requirement is similar, it's not really necessary, so do as you prefer (though I can't update my answer for your needs, sorry about that) – Phelype Oleinik Sep 15 '20 at 08:12
  • Either option is fine for me. Nevertheless, your answer does the job very well for me. – Diaa Sep 15 '20 at 09:39
  • If I have values in columns B, C, D, would it be easy to edit the code to specify which column whose value I look up? – Diaa Sep 15 '20 at 12:57
  • @Diaa With the current version, you have to read the file again with (for example) \ReadCSV{myCdata}[1,3]{test.csv} to get columns 1 and 3, then do \getValue\rdPar{1}{myCdata}. If you wait some 7 or 8 hours I can add a version that allows you to choose the column in \getValue (without the need to re-read the CSV). – Phelype Oleinik Sep 15 '20 at 15:20
  • I can happily wait for your edit. Accordingly, should I delete my relevant new followup question? – Diaa Sep 15 '20 at 16:06
  • 1
    I got an answer there, so your effort has been saved :) Thanks for the consideration. – Diaa Sep 15 '20 at 16:51