2

I am trying to semi-automatically import multiple parameters/variables from an excel (via .txt) file into both equation environments and $$ = math environments in (share)latex.

It is semi-automattically because I still need to manually import a .txt file into (share)latex.

My approach consists of the following e.g. test.txt file:

2: The old conversion coefficient k_{roe,Sv}
9.329664
4: The new conversion coefficient {K_{roe,Sv}}_{new}
0
6: r_{worst}
817278.6
8: r_{best}
81727.9

And the numbers are imported with the following/similair latex lines:

\item $K_{sh} = \lstinputlisting[firstline=28,lastline=28]{data_input/test.txt}$

Where the datapoint/number is selected by varying the line number (e.g. 4 to 6) in both firstline=4 and lastline=4.

It works fine in the normal (share)latex environment. However, if I apply the command in a $$ environment, I get the following error:

missing $ inserted

and if I add an extra $ sign after the command e.g.

\item $K_{sh} = \lstinputlisting[firstline=28,lastline=28]{data_input/test.txt}$$

it still get that same error.

So I tried putting it in a math Environment with:

\item $K_{sh} = \ensuremath{\lstinputlisting[firstline=28,lastline=28]{data_input/test.txt}}$

and

\item $K_{sh} = \ensuremath{\lstinputlisting[firstline=28,lastline=28]{data_input/test.txt}}$$

As was suggested in this question. However, the missing $ error still remains.

I fear it might be a double question, but with the searchterms known to me, I have not been able to find a working solution. Would you know the solution?

As to comply with BambOo's tip/comment, I have created the following MWE in which the K_{sh.. lines are tested individually by commenting the other 3 K_{sh.. lines out.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{listings}


\title{MWE import data}
\author{A.T.}
\date{April 2018}

\begin{document}

\maketitle

\section{Introduction}

\ensuremath{test} %Testing whether the \ensuremath command requires a package; it does not.

% $K_{sh} = \lstinputlisting[firstline=2,lastline=2]{test.txt}$

% $K_{sh} = \lstinputlisting[firstline=2,lastline=2]{test.txt}$$

% $K_{sh} = \ensuremath{\lstinputlisting[firstline=2,lastline=2]{test.txt}}$

$K_{sh} = \ensuremath{\lstinputlisting[firstline=2,lastline=2]{test.txt}}$$



\end{document}

It makes use of the following test.txt file in the same folder as main.tex:

2: The old conversion coefficient k_{roe,Sv}
9.329664
4: The new conversion coefficient {K_{roe,Sv}}_{new}
0
6: r_{worst}
817278.6
8: r_{best}
81727.9

I did not find out whether it is convention to post the MWE here as code, or whether to link to an external file, I guess w.r.t. availability reduction when the external source goes off line, code is preferred even though it takes more time to recreate.

6
  • Welcome to TeX.SX!
    – Bobyandbob
    Commented Apr 29, 2018 at 10:14
  • Welcome to TeX.SX! Please help us help you and add a minimal working example (MWE) that illustrates your problem. Reproducing the problem and finding out what the issue is will be much easier when we see compilable code, starting with \documentclass{...} and ending with \end{document}.
    – BambOo
    Commented Apr 29, 2018 at 10:34
  • Possibly related post here
    – BambOo
    Commented Apr 29, 2018 at 10:38
  • Thank you Bobyandbob! And the related post indeed appears to answer this question. I think this is still a valuable posts for people trying to accomplish the same goal.
    – a.t.
    Commented Apr 29, 2018 at 14:55
  • Tahnk you @BambOo, I think I added a correct MWE for completeness. I was not aware that the concept that distinguishes itself from an incomplete attempt to share what you are doing, had a name, so I learned that today, it will improve my interaction on the whole site. Thank you!
    – a.t.
    Commented Apr 29, 2018 at 14:56

2 Answers 2

0

I'm not sure listings is the best tool for the job:

\begin{filecontents*}{\jobname.txt}
2: The old conversion coefficient k_{roe,Sv}
9.329664
4: The new conversion coefficient {K_{roe,Sv}}_{new}
0
6: r_{worst}
817278.6
8: r_{best}
81727.9
\end{filecontents*}

\documentclass{article}
\usepackage{datatool,siunitx}

\DTLloaddb[noheader]{data}{\jobname.txt}
\newcommand{\mydatavalue}[1]{%
  \begingroup
  \dtlgetrow{data}{#1}%
  \dtlgetentryfromcurrentrow{\temp}{1}%
  \num{\temp}%
  \endgroup
}

\begin{document}

\begin{itemize}
\item $K_{sh} = \mydatavalue{2}$

\item $K_{sh} = \mydatavalue{4}$

\item $K_{sh} = \mydatavalue{6}$
\end{itemize}

\end{document}

There is possibly a better method with datatool.

enter image description here

A different implementation, as datatool may seem overkill.

\begin{filecontents*}{\jobname.txt}
2: The old conversion coefficient k_{roe,Sv}
9.329664
4: The new conversion coefficient {K_{roe,Sv}}_{new}
0
6: r_{worst}
817278.6
8: r_{best}
81727.9
\end{filecontents*}

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

\ExplSyntaxOn

\NewDocumentCommand{\loaddatafile}{O{default}m}
 {% #1 = symbolic name, #2 = file name
  \at_datafile_load:nn { #1 } { #2 }
 }

\NewExpandableDocumentCommand{\getdataline}{O{default}m}
 {
  \seq_item:cn { g_at_datafile_#1_seq } { #2 }
 }

\ior_new:N \g_at_datafile_stream

\cs_new_protected:Nn \at_datafile_load:nn
 {
  \seq_gclear_new:c { g_at_datafile_#1_seq }
  \ior_open:Nn \g_at_datafile_stream { #2 }
  \ior_map_inline:Nn \g_at_datafile_stream
   {
    \seq_put_right:cx { g_at_datafile_#1_seq } { \tl_trim_spaces:n { ##1 } }
   }
  \ior_close:N \g_at_datafile_stream
 }

\ExplSyntaxOff

\loaddatafile{\jobname.txt}

\begin{document}

\begin{itemize}
\item $K_{sh} = \num{\getdataline{2}}$

\item $K_{sh} = \num{\getdataline{4}}$

\item $K_{sh} = \num{\getdataline{6}}$
\end{itemize}

\end{document}
3
  • Thank you @egreg, that was exactly what I have been trying to build! I noticed if I add the txt the way you did it, to the (share)latex, that the values do not get updated in a "normal"(not "fast") recompile. But when I upload the test.txt manually as a separate file to the same folder as main.text it does. You made my day! It allows me to work more effectively through iterations. (I can not upvote you nor the comments yet since I do not have enough reputation, yet.)
    – a.t.
    Commented Apr 29, 2018 at 15:01
  • @a.t. I used filecontents just to make the example self-contained. Use an independent file with the name you prefer.
    – egreg
    Commented Apr 29, 2018 at 15:05
  • Ah, thank you, convenient. I was actually curious how it gets processed with that method and why it then does not synchronize, but I will investigate that at a later point in time.
    – a.t.
    Commented Apr 29, 2018 at 15:11
0

So for future users running into the same problem, here is the implementation of the solution that @egreg gave, (including a script to export your excel parameters to .txt for your convenience):

First add package to main.tex:

\usepackage{datatool,siunitx} %To import data from a textfile

Then

%Make own commands to import variable parameters in main.tex:

\DTLloaddb[noheader]{data0}{data_input/excel_output_L.txt}
\newcommand{\inl}[1]{%
  \begingroup
  \dtlgetrow{data0}{#1}%
  \dtlgetentryfromcurrentrow{\temp}{1}%
  \num{\temp}%
  \endgroup
}

\DTLloaddb[noheader]{data1}{data_input/excel_output_M_G.txt}
\newcommand{\inmg}[1]{%
  \begingroup
  \dtlgetrow{data1}{#1}%
  \dtlgetentryfromcurrentrow{\temp}{1}%
  \num{\temp}%
  \endgroup
}

\DTLloaddb[noheader]{data2}{data_input/excel_output_H.txt}
\newcommand{\inh}[1]{%
  \begingroup
  \dtlgetrow{data2}{#1}%
  \dtlgetentryfromcurrentrow{\temp}{1}%
  \num{\temp}%
  \endgroup
}

After that add txt files to folder: data_input in the (share)latex folder

Proceed by calling the parameters (e.g. the number in line 6 of excel_output_H.txt) with:

\inmg{6}

(Which can be called in a math environment inside a itemize/enumerate environment:

\item $K_{shielding} = \inmg{6}$

And for completeness This is the code that exports the excel columns E3:E100 to .txt for the 3 sheets in "the" workbook:

Sub export_to_txt()
Dim myFile As String, rng As Range, cellValue As Variant, i As Integer, j As Integer
For nr_sheets = 1 To 3
    If nr_sheets = 1 Then
        sheetname = "L"
    End If
    If nr_sheets = 2 Then
        sheetname = "M_G"
    End If
    If nr_sheets = 3 Then
        sheetname = "H"
    End If
    myFile = ThisWorkbook.Path & "\excel_output_" & sheetname & ".txt"
    'MsgBox (sheetname)
    ThisWorkbook.Worksheets(sheetname).Activate
    Set rng = ThisWorkbook.Worksheets(sheetname).Range("E3:E100")
    Open myFile For Output As #1
    For i = 1 To rng.Rows.Count
        For j = 1 To rng.Columns.Count
    cellValue = rng.Cells(i, j).Value
    If j = rng.Columns.Count Then
        Write #1, cellValue
    Else
        Write #1, cellValue,
    End If
        Next j
    Next i
    Close #1
Next nr_sheets
End Sub

You must log in to answer this question.

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