在表格标题中使用 CSV 数据吗?

在表格标题中使用 CSV 数据吗?

我想在表格标题中使用一些通过 csvsimple 导入的数据。

\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

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

\newcommand{\csvget}[3]{\csvreader[no head, filter equal={\thecsvinputline}{#2}]{#1}{}{#3}}

\begin{document}
\listoftables

\begin{table}
   \centering
   My Tabular
   \caption{A caption \csvget{data.csv}{2}{\csvcolii}}
\end{table}

\end{document}

使用上面的代码我收到一个错误,如有Argument of \@caption has an extra...
什么建议吗?

提前感谢
CX

答案1

这是脆弱命令的一个问题。请参阅脆弱命令和坚固命令之间有什么区别?

使用 e-tex 兼容编译器,您可以\newrobustcmd使用etoolbox

\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}
\usepackage{etoolbox}

\newrobustcmd{\csvget}[3]{\csvreader[no head, filter equal={\thecsvinputline}{#2}]{#1}{}{#3}}

\begin{document}
\listoftables

\begin{table}
   \centering
   \csvautotabular{data.csv}
   \caption{A caption \csvget{data.csv}{2}{\protect\csvcolii}}
\end{table}

\end{document}

如果没有它你可以使用\DeclareRobustCommand

\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

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

\DeclareRobustCommand{\csvget}[3]{\csvreader[no head, filter equal={\thecsvinputline}{#2}]{#1}{}{#3}}

\begin{document}
\listoftables

\begin{table}
   \centering
   \csvautotabular{data.csv}
   \caption{A caption \csvget{data.csv}{2}{\protect\csvcolii}}
\end{table}

\end{document}

结果是:

结果

答案2

编辑 (2017):代码已损坏,因为xint 1.1 (2014/10/28)从那时起包xint就不会加载。因此,这里需要一个xinttools而不是。\usepackage{xint}\usepackage{xinttools}

这是一些通用的 csv 文件处理宏\ReadCSVfile {filename}\to \MACRO。然后\MACRO {i}{j}扩展到第 行j的第 项i,您可以在 或任何其他方式中执行所有操作\caption。文件名必须带有扩展名。

csvcaption

代码依赖于信特这些最近才被移到包中。但由于一些疏忽xinttools,仍然至少有一个依赖项,因此我们在此处加载。xinttoolsxintxint

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

\usepackage{xinttools}

% VERY SIMPLE CSV HANDLING. Syntax:

% \ReadCSVfile {data.csv} \to \DATA

% \DATA WILL BE DEFINED AS A TWO ARGUMENTS COMMAND:

% \DATA {0}{0}: number of lines
% \DATA {i}{0}: number of items in i th line
% \DATA {i}{j}: j th item of i th line
% \DATA {0}{i}: the ith line as a list of braced items.

% WARNING: \DATA (or whatever it is called) WILL BE OVERWRITTEN.

\makeatletter
% example \ReadCSVfile {data.csv} \to \DATA
% WARNING: macro \DATA gets defined with no check if it already exists !!
\newcount\ReadCSV@linecount
\newcount\ReadCSV@itemcount
\newcommand\ReadCSVfile [3]{%
    \IfFileExists{#1}
    {%
      \edef\ReadCSV@restore{\endlinechar=\the\endlinechar\relax
                            \catcode`\noexpand\@=\the\catcode`\@\relax}%
      \endlinechar=-1 
      \makeatletter % in case csv file contains LaTeX macros with @ character
      \newread\ReadCSV@instream
      \openin\ReadCSV@instream\@filef@und
      \ReadCSV@linecount\z@
      \xintloop
         \read\ReadCSV@instream to\ReadCSV@oneline
      \unless\ifeof\ReadCSV@instream
         \advance\ReadCSV@linecount\@ne
         \ReadCSV@itemcount\z@
% we suppress all spaces around commas from the input file. Use braces around
% the item with spaces to force such spaces.
%
% the reason for such definition is for optimization in order for the conversion
% from  CSV format to be done only once. We take care not to expand the file
% contents, in case they have some LaTeX meaning.        
% 
         \toks@ \expandafter{\romannumeral0\expandafter\xintcsvtolist
                     \expandafter{\expandafter\space\ReadCSV@oneline}}%
         \expandafter
         \edef\csname CSV@\string#3@0.\the\ReadCSV@linecount\endcsname
                            {\the\toks@}%
         \xintFor* ####1 in {\the\toks@} \do
         {%
           \advance\ReadCSV@itemcount\@ne
           \expandafter
           \def\csname CSV@\string#3@\the\ReadCSV@linecount.%
                                     \the\ReadCSV@itemcount\endcsname
                  {####1}%
         }%
         \expandafter
         \def\csname CSV@\string#3@\the\ReadCSV@linecount.%
                                      0\expandafter\endcsname
                                       \expandafter{\the\ReadCSV@itemcount}%
      \repeat
      \closein\ReadCSV@instream
      \ReadCSV@restore
      \expandafter
      \edef\csname CSV@\string#[email protected]\endcsname {\the\ReadCSV@linecount}%
      \def#3####1####2%
      {\csname CSV@\string#3@\the\numexpr####1.\the\numexpr####2\endcsname }%
    }
    {\typeout{No file #1}}%
}


\ReadCSVfile {data.csv} \to \DATA

% \DATA {0}{0}: number of lines
% \DATA {i}{0}: number of items in i th line
% \DATA {i}{j}: j th item of i th line
% \DATA {0}{i}: the ith line as a list of *braced* items.

% spaces around commas in input file are REMOVED.


\begin{document}
\listoftables
\bigskip

\begin{table}
   \centering
   My Tabular
   \caption{Second of second line \DATA {2}{2}}
\end{table}

\begin{table}
   \centering
   My Tabular
   \caption{Third of first line \DATA {1}{3}}
\end{table}

The data file contains \DATA {0}{0} lines. 

\newcounter{linecount}
\setcounter{linecount}{0}

% Note: we must use \endgraf because \xintloop currently does not accept \par.
\xintloop
\stepcounter{linecount}
The line numbered \arabic{linecount} contains \DATA {\value{linecount}}{0}
entries. Here they are:%
\xintFor* #1 in {\xintSeq {1}{\DATA {\value{linecount}}{0}}} 
\do 
  { \DATA {\value{linecount}}{#1},} and that's
  it for that line.\endgraf
\ifnum\value{linecount}<\DATA{0}{0}
\repeat

\bigskip

We can also handle files with lines of different lengths.

\begin{filecontents*}{data2.csv}
column1,column2,column3,column4
name1,val1a,val1b
name2,val2a,val2b,X,Y,Z
a,b,c,d,e,f,g
\end{filecontents*}

\ReadCSVfile {data2.csv} \to \DATAII

\setcounter{linecount}{0}

% Note: we must use \endgraf because \xintloop currently does not accept \par.
\xintloop
\stepcounter{linecount}
The line numbered \arabic{linecount} contains \DATAII {\value{linecount}}{0}
entries. Here they are: 
\xintListWithSep{, }{\DATAII {0}{\value{linecount}}}.\endgraf 
\ifnum\value{linecount}<\DATAII {0}{0}
\repeat

\setcounter{linecount}{0}

Here is a nice Plain \TeX{} alignment with this data:

\tabskip1em
\fbox{\vbox{\halign{&\hfil#\hfil\cr
        \xintloop 
        \ifnum\value{linecount}<\DATAII {0}{0}
        \stepcounter{linecount}%
        \xintListWithSep {&}{\DATAII {0}{\value{linecount}}}%
        \cr 
        \repeat
}}}

\medskip \LaTeX{}'s tabulars can be used with lines
having a varying number of items but one must know the maximal number of items
from all rows (I think).

\end{document}

相关内容