3

I'm trying to create a matrix table that will iteratively fill in the cells based on inputs that I can change. I originally tried the solution shown here, but I wasn't able to get Latex to properly expand when I was actually using the iterative value \i in the cells, rather than pure text like t1 and t2.

So I also came across this great solution here, which did work with inputting \i as a value. However, I'm having problems when doing mathematical operations on that \i and further values. In accordance with that second solution, here's my MWE:

\documentclass[]{article}
\usepackage{tikz}
\usepackage{tabularx}
\begin{document}
    \newcommand\costsmall{60}
    \newcommand\costmed{80}
    \newcommand\costlarge{100}
    \newcommand\rentsmall{10}
    \newcommand\rentmed{15}
    \newcommand\rentlarge{20}

    \makeatletter
    \newtoks\@tabtoks
    \newcommand\addtabtoks[1]{\global\@tabtoks\expandafter{\the\@tabtoks#1}}
    \newcommand\eaddtabtoks[1]{\edef\mytmp{#1}\expandafter\addtabtoks\expandafter{\mytmp}}
    \newcommand*\resettabtoks{\global\@tabtoks{}}
    \newcommand*\printtabtoks{\the\@tabtoks}
    \makeatother

    \resettabtoks
    \addtabtoks{\textbf{Num1} & \textbf{Num2} & \textbf{Num3} & \textbf{Num2/Num3}\\ \cline{1-4}}

    \foreach \x [count=\xi] in {\costsmall,\costmed,\costlarge}{
        \foreach \y [count=\yi] in {\the\numexpr\x - 10,\the\numexpr\x,\the\numexpr\x + 10}{
            \foreach \z [count=\zi] in {\rentsmall,\rentmed,\rentlarge}{
                \ifnum\zi=2 {
                    \ifnum\yi=2 {
                        \eaddtabtoks{\x}
                    }
                    \else {
                    }
                    \fi
                    \addtabtoks{&}
                    \eaddtabtoks{\y}
                    \addtabtoks{&}
                } 
                \else {
                    \addtabtoks{ & & }
                }
                \fi
                \eaddtabtoks{\z }
                \addtabtoks{&}
    %           \newcommand{\testthing}[2]{y is #1, z is #2, and together they are #1/#2}
    %           \testthing{\y}{\z}
                \eaddtabtoks{\y/\z}
                \addtabtoks{\\}

                \ifnum\zi=3 {
                    \ifnum\yi=3 {
                        \addtabtoks{ \cline{1-4} }
                    }
                    \else{
                        \addtabtoks{ \cline{2-4} }
                    }
                    \fi
                }
                \fi
            }
        }
    }

    \begin{tabularx}{\textwidth}{|c|c|c|c|c|}
        \printtabtoks
    \end{tabularx}%

\end{document}

As a result, I get this plot, where the "# of rents to pay off" has clearly been calculated incorrectly for most of the cases: Plot with incorrect numbers

In this code, this is at the \eaddtabtoks{\y/\z} line. I've been able to trace it back and find that it's failing in all the cases where \y has 10 subtracted or added to it in the \foreach line. In those cases, it looks like a strange order of operations takes hold, or the 10 is not seen as a number or something. I've played with the \y/\z line endlessly, trying different options of \the\numexpr and brackets and parentheses to get the order of operations done correctly, but nothing seems to work.

As a side note, I did have to use this janky \ifnum\zi=2 method of centering the first few multicolumns because I couldn't get multicolumns to work with this method. \multicolumn{9}{*}{random} worked fine with a string like random, but once I put in an iterator like \x or \y, I got errors that I couldn't fix.

MW2023
  • 143
  • This is a general advice: if you provide a complete example that starts with \documentclass, ends with \end{document} and can be compiled, many more users will look at your code. –  Jun 22 '19 at 16:59
  • 1
    tabularx can do nothing useful with a preamble of \begin{tabularx}{\textwidth}{|c|c|c|c|c|} just use tabular. The tabularx version is evaluated multiple times with trial column widths which makes embedding calculations interesting,m but you do not want tabularx here anyway. – David Carlisle Jun 22 '19 at 17:12
  • you are missing a space after 10 in that calculation – David Carlisle Jun 22 '19 at 17:20
  • Note that you should not enclose the “true text” and the “false text” in braces. – egreg Jun 22 '19 at 20:33
  • 2
    Can you explain what the idea is? How should the entries be computed? – egreg Jun 22 '19 at 21:08
  • Not sure how you are calculating the fourth column but I suggest replaing the \foreach \y line with \foreach \y [count=\yi, evaluate=\y as \ey using {int(\x+\yi*10)}] in {-1,0,1} {...} and then using \ey later. Secondly, will there always be three rent and three cost prices or can these vary? For what it is worth, I would not use \foreach to create tables like this. Your problem is almost certainly that \foreach works inside a group so values will not be remembered outside the loop -- you could try using remember=... in the \foreach but better to rewrite with other tools. –  Jun 23 '19 at 01:17
  • @Andrew, your method worked! I'm incredibly grateful. I can edit my question to have a complete example as marmot suggested, and if you want to reply with a full "Answer" I can mark it and give you the credit. – MW2023 Jun 23 '19 at 18:50
  • If you add a MWE then I'll post an answer expanding on my comment (but probably not until later tonight Australian time). I'll probably also add a LaTeX3 solution as a second option as I think it's a better way to go, although this really depends on how many of these tables you will have. I was thinking of defining a macro so that \RentCosts{60,80,100}{10,15,20}{20} would produce your table. –  Jun 23 '19 at 23:19
  • @Andrew, the MWE is up, but I also ran into another issue. Is it possible to have the numbers be formatted with separators? When my calculations result in numbers higher than 1,000, I'd like to have the comma as the separator. Previously I did this by using \SI or \numprint, but I can't seem to find a place to apply those packages to the cell values without causing an error. Thanks. – MW2023 Jun 26 '19 at 04:15

0 Answers0