# Formatting Strings in Dynamic Variables with xstring

I need to format a string resulting from a dynamic variable set in a separate program for a LaTeX generated report. In particular, if a variable has a negative value (starts with a minus sign), I want to show the variable as red without the minus sign. Here is a minimum working example:

\documentclass{article}
\usepackage{amsmath}
\usepackage{color}
\usepackage{xstring}

\makeatletter
\newcommand{\ChgFmt}[1]{%
\begingroup\fullexpandarg
\let\$\relax \let\text\unexpanded \IfSubStr{#1}{-} {\endgroup\@firstoftwo} {\endgroup\@secondoftwo}% {\begingroup\color{red}#1\endgroup} {\begingroup\color{green}#1\endgroup}% } \makeatother % Output from variables file \newcommand{\FirstDollarAmount}{\$1\text{ million}}

I would like also to have the flexibility to format the string more. For example, I'd like to prepend a $\uparrow$ to positive numbers and prepend a $\downarrow$ to negative numbers. The solution provided by Steven B. Segletes is elegant but not flexible enough to add these (at least naively):

\documentclass{article}
\usepackage{amsmath,xcolor}
\def\ChgFmt#1{\textcolor{red}{\if-#1\else\textcolor{green}{$\uparrow$#1}\fi}}

% Output from variables file
\newcommand{\inputnum}[2]{\csname #1#2\endcsname}

\begin{document}
This number is printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}

This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}


Would this one-line parsing suffice, without use of xstring? This problem is really tailor-made for an \if-#1 construct for two reasons:

1. \if fully expands its arguments before the test (which matters because the - is embedded several expansions down inside #1); and

2. a "positive" test strips the leading token from the argument, which is exactly what the OP wants.

I set the string red to start and use an \if-#1...\else...\fi construct to decide whether the leading token of the argument is a -. If a leading - is found, it is stripped by the \if, while leaving the remaining text red. If a leading - is not found, then the whole argument is output in green.

\documentclass{article}
\usepackage{amsmath,xcolor}
\def\ChgFmt#1{\textcolor{red}{\if-#1\else\textcolor{green}{#1}\fi}}

% Output from variables file
\newcommand{\inputnum}[2]{\csname #1#2\endcsname}

\begin{document}
This number is printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}

This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}


UPDATE

To handle the OP's revised formulation, one can perform a test inside a temporary box, which is then discarded, but not before it \gdef's the desired outcome (a green \uparrow or a red \downarrow) into a temporary variable. Then, prepend that temporary variable, followed by the prior test described in the initial solution.

\documentclass{article}
\usepackage{amsmath,xcolor}
\def\ChgFmt#1{\setbox0=\hbox{%
\if-#1\gdef\tmp{\textcolor{red}{$\downarrow$}}\else%
\gdef\tmp{\textcolor{green!60!black}{$\uparrow$}}\fi%
}\tmp%
\textcolor{red}{\if-#1\else\textcolor{green!60!black}{#1}\fi}%
}

% Output from variables file
\newcommand{\inputnum}[2]{\csname #1#2\endcsname}

\begin{document}
This number is printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}

This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}


• Your solution is elegant, but not flexible enough to address my application. See the revised question above. – DrTRD Aug 18 '15 at 13:46
• @DrTRD Please see UPDATE – Steven B. Segletes Aug 18 '15 at 14:14

Here's a modification of the former solution that uses a different workaround:

\documentclass{article}
\usepackage{amsmath}
\usepackage{color}
\usepackage{xstring}

\makeatletter
\newcommand{\ChgFmt}[1]{%
\ensuremath{%
\begingroup
\expandarg
\protected@edef\temp{#1}%
\IfSubStr{\temp}{-}
{\StrSubstitute{\temp}{-}{}[\temp]\@firstoftwo}
{\@secondoftwo}%
{\color{red}{\downarrow}\temp\endgroup}
{\color{green}{\uparrow}\temp\endgroup}%
}%
}

\newcommand{\inputnum}[2]{\expandafter\csname #1#2\endcsname}

\begin{document}
This number is printed in green: \ChgFmt{\$1 \text{ million}} This number is printed in red: \ChgFmt{-\$1 \text{ million}}

This number should be printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}

This number should be printed in red: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}