Предположим, у меня есть файл электронной таблицы Excel, data.xlsx
содержимое которого
A B
1 Third Parameter 7
2 First Parameter 5
3 Second Parameter 3
и я хотел бы найти значение в столбце B, используя соответствующий текст в столбце A.
Другими словами, мне нужна команда Latex, например, \getValue{<macro name to save the value in>}{<Search word>}{<Excel file name>}
. Так, например, \getValue{\rdPar}{Third Parameter}{data.xlsx}
сохранит значение в 7
для \rdPar
дальнейшего использования в моем документе Latex.
P.S. Может быть,этот вопросполезно, но я не знаю, как редактировать ответы для своих нужд.
решение1
Предполагая, что вы можете использовать .csv
вместо .xls(x)
, существует несколько инструментов для работы с CSV-файлами, например csvsimple
.
Хотя если вы хотите изобрести велосипед: вы можете использовать \ReadCSV
для чтения файла .csv
в структуру ключ-значение, а затем \getValue
извлекать эти значения, когда это необходимо. Синтаксис \ReadCSV
:
\ReadCSV [*] {<label>} [<name>,<value>] {<file>}
\ReadCSV
прочитает CSV <file>
и возьмет столбцы <name>
и <value>
( <name>
и <value>
— это количество столбцов; по умолчанию — <name>=1
и <value>=2
) и сохранит их в <label>
для дальнейшего использования. Если используется необязательный параметр *
, файл будет прочитан как строка.
После прочтения файла вы можете извлечь сохраненные значения с помощью \getValue
:
\getValue <macro> {<name>} {<label>}
\getValue
извлечет <value>
соответствующий столбец <name>
в CSV-файле, прочитанном в разделе <label>
, и сохранит его в файле <macro>
.
В вашем примере (удаление строки и столбца заголовка) у вас будет:
\ReadCSV{mydata}{test.csv}
\getValue\rdPar{Third Parameter}{mydata}
\rdPar % prints 7
Вот expl3
реализация (она минималистична: нет проверки ошибок на неверный ввод, пропущенные данные и т. д.):
\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}