背景

背景

背景

大家好,提前感谢大家提供的任何见解!抱歉发了这么长的帖子,但我注意到大多数新用户因为没有分享足够的背景信息而受到指责。TLDR 版本是我无法弄清楚如何使用 etools 中布尔表达式中用 pgfplottable 读取的单元格值

我正在努力根据从 csv 中读取的值来格式化某些文本。每年我都必须创建一个大纲大致相同但每年在某些地方的值不同的文档。例如,在 2015 年,文档可能会说:

2015 年美国总铭牌产能为 1,159,748 兆瓦

但在2016年这句话应该更新为:

2015 年美国总铭牌产能为 1,174,115 兆瓦

我们正在尝试使用 Python + LaTeX 将其转换为更高效的过程,使用 Python 将实际数据/图形保存到 csv,并使用 LaTeX 读取这些 csv 中的文件自动更新文档,我们的想法是,我们可以使用单个命令行脚本重新创建所有文档。

迄今为止,在这个答案的帮助下,我实际上没有遇到任何读取 csv 并将其“内联”打印到 LaTeX 中的麻烦。MWE:

\documentclass[16pt]{article}

\usepackage{pgfplotstable, pgfplots, etoolbox, xcolor}

\pgfplotstableread[col sep=comma]{data_values_test.csv}\sectionIIvars

\def\getcell#1#2#3{
    \pgfplotstablegetelem{#1}{#2}\of{#3}\pgfplotsretval%
}

\begin{document}
Renewable electricity in was \textbf{\getcell{8}{all_re}{\sectionIIvars}\% of total installed electricity capacity and \getcell{3}{all_re}\sectionIIvars}\% of total annual generation in the United States}.
\end{document}

它会吐出:

代码输出显示 csv 已正确读取和打印

我可以想办法与您分享实际的 csv,但它们非常简单:第一行是标题/名称(例如,您可以从代码中看到有一列标题为“all_re”)。第一列只是名称(字符串),以帮助我们跟踪哪一行对应哪个变量。csv 的其余部分只是数字。'\getcell{8}{all_re}{\sectionIIvars}' 函数允许我从预定义表 '\sectionIIvars' 中访问第 8 行、列 'all_re' 的单元格内容。

问题

此处的 LaTeX 输出将传递给一个团队,使其“准备发布”,并且我们经常需要将文档的多个迭代传递给该团队,因为图表在最终发布之前会不断更新。为了减少这个外部团队更新“准备发布”草稿所需的时间,我们希望能够自动格式化在迭代之间发生变化的值。例如,如果上述代码片段中的第二个值在迭代之间从 15.55 更改为 17.56,我们希望 17.56 显示为红色。即使“.tex”文件中的任何代码都没有更改,只是在底层 csv 中更改了。见下文:

在此处输入图片描述

不幸的是,我无法让它工作!我尝试了一些方法,但都无济于事:

Latexdiff

我立即排除了这种可能,因为据我所知,这只能捕获“.tex”文件本身的变化。由于实际的 .tex 文件在这里没有变化,因此它无法提供帮助。

如果布尔表达式

我的大部分时间都花在这里。这一切都基于一个命令在这个答案中。在每种情况下,我都试图让布尔函数将一个 csv 中的答案与另一个 csv 中的答案进行比较。这个想法是,Python 脚本可以在迭代之间比较“\sectionIIvars”表中的答案,并将实际答案是否已更改为第二个 csv(我们​​称之为“\booltestsecII”)。然后 Latex 可以在“\sectionIIvars”中打印答案但根据 '\booltestsecII' 进行格式化。'\booltestsecII' 的大小和形状与 '\sectionIIvars' 相同,但只有 0 和 1(分别表示“没有改变”和“改变!”)。

尝试 1

首先,我尝试重写 getcell 函数以采用附加参数,以便它比较 '\sectionIIvars' 和 \booltestsecII' 之间的同一行和单元格:

\documentclass[16pt]{article}

\usepackage{pgfplotstable, pgfplots, etoolbox, xcolor}

\pgfplotstableread[col sep=comma]{data_values_test.csv}\sectionIIvars
\pgfplotstableread[col sep=comma]{Boolean_change_test.csv}\booltestsecII

\newcommand{\getcell}[4]{
      \ifboolexpr{ test {\ifnumcomp{\pgfplotstablegetelem{#1}{#2}\of{#4}\pgfplotsretval}{=}{1}}}
        {\pgfplotstablegetelem{#1}{#2}\of{#3}\pgfplotsretval}
        {\textcolor{red}{\pgfplotstablegetelem{#1}{#2}\of{#3}\pgfplotsretval}}
}

\begin{document}

Renewable electricity in was \textbf{\getcell{8}{all_re}{\sectionIIvars}{\booltestsecII}\% of total installed electricity capacity and \getcell{3}{all_re}{\sectionIIvars}{\booltestsecII}\% of total annual generation in the United States}.

\end{document}

这会产生“!缺少数字,视为零。”错误(这往往表示缺少必需的函数输入),尽管我认为我已经提供了所有必要的输入。如果我尝试继续,它会产生“缺少 = 插入 \ifnum。”错误。如果我再次尝试继续,它会产生“!您不能在水平模式下使用‘\numexpr’。”

第二次尝试

我想这可能与嵌套宏有关,所以我尝试像这样更改函数定义(基于这个问题):

\newcommand{\getcell}[4]{
      \ifboolexpr{ test {\ifnumcomp{\pgfplotstablegetelem{##1}{##2}\of{##4}\pgfplotsretval}{=}{1}}}
        {\pgfplotstablegetelem{##1}{##2}\of{##3}\pgfplotsretval}
        {\textcolor{red}{\pgfplotstablegetelem{##1}{##2}\of{##4}\pgfplotsretval}}
}

但这产生了同样的错误。

第三次尝试

我尝试简化一点,只关注从 csv 中读取一个值,然后使用“ifboolexpr”将其与数值进行比较,但这也不起作用:

\documentclass[16pt]{article}

\usepackage{pgfplotstable, pgfplots, etoolbox, xcolor}

\pgfplotstableread[col sep=comma]{Boolean_change_test.csv}\booltestsecII

\newcommand{\checkchangesecII}[3]{
      \ifboolexpr{ test {\value{\pgfplotstablegetelem{#1}{#2}\of{#3}\pgfplotsretval}{=}{1}}}
        {do this}
        {\textcolor{red}{do that}}
}


\begin{document}

\checkchangesecII{0}{solar}{\booltestsecII}

\end{document}

这会产生一个 '!Missing \endcsname inserted.' 错误,然后是一个 '!Extra \endcsname.' 错误,最后打印“1=1do that”:

在此处输入图片描述

概括

到目前为止,我还没有取得任何进展,但我很想听听大家的理论。我认为,尽管 LaTeX 正在读取数值,但它可能无法识别它们,因此无法将“数字 1”与“字符串 1”进行比较?我不知道如何检查或更正这个问题,所以我在这里写这篇文章。

感谢大家的反馈。如果这个问题格式不正确,请告诉我,我会尽力修改。

答案1

你很接近了:

在第一次尝试中,你使用了

\ifboolexpr{ test {\ifnumcomp{\pgfplotstablegetelem{#1}{#2}\of{#4}\pgfplotsretval}{=}{1}}}

这里\pgfplotstablegetelem{#1}{#2}\of{#4}1或赋值0\pgfplotsretval,然后使用\pgfplotsretval。为什么需要这样做?为什么不\pgfplotstablegetelem{#1}{#2}\of{#4}直接给出返回值?问题是,有些操作,比如赋值和其他在 中需要的东西,\pgfplotstablegetelem不是“可扩展的”。这基本上意味着它们可以执行,但它们不能站在需要值的地方。所以\pgfplotstablegetelem在 中使用\test你想要测试的值预期的地方使用 是行不通的。这就是\pgfplotsretval发挥作用的地方:你可以\pgfplotstablegetelem在测试之前移动,只\pgfplotsretval在内部使用可扩展的:

\documentclass[16pt]{article}

\usepackage{pgfplotstable, pgfplots, etoolbox, xcolor}

\pgfplotstableread[col sep=comma]{data_values_test.csv}\sectionIIvars
\pgfplotstableread[col sep=comma]{Boolean_change_test.csv}\booltestsecII

\newcommand{\getcell}[4]{
      \pgfplotstablegetelem{#1}{#2}\of{#4}
      \ifboolexpr{ test {\ifnumcomp{\pgfplotsretval}{=}{1}}}
        {\pgfplotstablegetelem{#1}{#2}\of{#3}\pgfplotsretval}
        {\textcolor{red}{\pgfplotstablegetelem{#1}{#2}\of{#3}\pgfplotsretval}}
}

\begin{document}

Renewable electricity in was \textbf{\getcell{8}{all_re}{\sectionIIvars}{\booltestsecII}\% of total installed electricity capacity and \getcell{3}{all_re}{\sectionIIvars}{\booltestsecII}\% of total annual generation in the United States}.

\end{document}

在此处输入图片描述

相关内容